Unity,获取"actual"当前地形?
Unity, get the "actual" current Terrain?
Unity 有一个很棒的功能 Terrain.sampleHeight(point)
,它可以立即为您提供脚下地形的高度,而不必投射。
然而,任何不平凡的项目都有不止一个 Terrain。 (事实上 ,任何物理上大的场景都不可避免地具有地形拼接,以某种方式。)
Unity 有一个函数 Terrain.activeTerrain
,它 - 这不是我编的 - 给你:"first one loaded"
显然那是完全没用的。
事实上,有没有快速获取地形的方法"under you"?然后你可以使用快速函数 .sampleHeight
?
{请注意,当然,您可以...施放以在您下方找到地形!但是你会有你的高度,所以没有必要担心 .sampleHeight
!}
简而言之,是否有一个与 sampleHeight
一起使用的匹配函数,它让该函数知道 哪个 地形用于给定的 xyz?
(或者实际上,sampleHeight
只是一个相当无用的演示功能,只能在一个地形的演示中使用吗?)
Is there in fact a fast way to get the Terrain "under you" - so as to
then use the fast function .sampleHeight ?
是的,可以做到。
(Or indeed, is sampleHeight just a fairly useless demo function,
usable only in demos with one Terrain?)
没有
场景中有 Terrain.activeTerrain
which returns the main terrain in the scene. There is also Terrain.activeTerrains
(注意末尾的 "s")returns 活动地形。
用Terrain.activeTerrains
得到地形returnsTerrain
数组然后用Terrain.GetPosition
函数得到它的位置。通过寻找距离玩家位置最近的地形来获取当前地形。您可以使用 Vector3.Distance
或 Vector3.sqrMagnitude
(更快)对地形位置进行排序。
Terrain GetClosestCurrentTerrain(Vector3 playerPos)
{
//Get all terrain
Terrain[] terrains = Terrain.activeTerrains;
//Make sure that terrains length is ok
if (terrains.Length == 0)
return null;
//If just one, return that one terrain
if (terrains.Length == 1)
return terrains[0];
//Get the closest one to the player
float lowDist = (terrains[0].GetPosition() - playerPos).sqrMagnitude;
var terrainIndex = 0;
for (int i = 1; i < terrains.Length; i++)
{
Terrain terrain = terrains[i];
Vector3 terrainPos = terrain.GetPosition();
//Find the distance and check if it is lower than the last one then store it
var dist = (terrainPos - playerPos).sqrMagnitude;
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrains[terrainIndex];
}
用法:
假设玩家的位置是transform.position
:
//Get the current terrain
Terrain terrain = GetClosestCurrentTerrain(transform.position);
Vector3 point = new Vector3(0, 0, 0);
//Can now use SampleHeight
float yHeight = terrain.SampleHeight(point);
虽然可以用 Terrain.SampleHeight
做到这一点,但这可以通过从玩家位置到地形的简单光线投射来简化。
Vector3 SampleHeightWithRaycast(Vector3 playerPos)
{
float groundDistOffset = 2f;
RaycastHit hit;
//Raycast down to terrain
if (Physics.Raycast(playerPos, -Vector3.up, out hit))
{
//Get y position
playerPos.y = (hit.point + Vector3.up * groundDistOffset).y;
}
return playerPos;
}
原来答案很简单NO,Unity没有提供这样的功能。
Terrain.GetPosition() = Terrain.transform.position = 世界排名
工作方式:
Terrain[] _terrains = Terrain.activeTerrains;
int GetClosestCurrentTerrain(Vector3 playerPos)
{
//Get the closest one to the player
var center = new Vector3(_terrains[0].transform.position.x + _terrains[0].terrainData.size.x / 2, playerPos.y, _terrains[0].transform.position.z + _terrains[0].terrainData.size.z / 2);
float lowDist = (center - playerPos).sqrMagnitude;
var terrainIndex = 0;
for (int i = 0; i < _terrains.Length; i++)
{
center = new Vector3(_terrains[i].transform.position.x + _terrains[i].terrainData.size.x / 2, playerPos.y, _terrains[i].transform.position.z + _terrains[i].terrainData.size.z / 2);
//Find the distance and check if it is lower than the last one then store it
var dist = (center - playerPos).sqrMagnitude;
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrainIndex;
}
您可以使用此功能获取离您当前位置最近的地形:
int GetClosestTerrain(Vector3 CheckPos)
{
int terrainIndex = 0;
float lowDist = float.MaxValue;
for (int i = 0; i < _terrains.Length; i++)
{
var center = new Vector3(_terrains[i].transform.position.x + _terrains[i].terrainData.size.x / 2, CheckPos.y, _terrains[i].transform.position.z + _terrains[i].terrainData.size.z / 2);
float dist = Vector3.Distance(center, CheckPos);
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrainIndex;
}
然后你可以像这样使用函数:
private Terrain[] _terrains;
void Start()
{
_terrains = Terrain.activeTerrains;
Vector3 start_pos = Vector3.zero;
start_pos.y = _terrains[GetClosestTerrain(start_pos)].SampleHeight(start_pos);
}
public static Terrain GetClosestTerrain(Vector3 position)
{
return Terrain.activeTerrains.OrderBy(x =>
{
var terrainPosition = x.transform.position;
var terrainSize = x.terrainData.size * 0.5f;
var terrainCenter = new Vector3(terrainPosition.x + terrainSize.x, position.y, terrainPosition.z + terrainSize.z);
return Vector3.Distance(terrainCenter, position);
}).First();
}
Unity 有一个很棒的功能 Terrain.sampleHeight(point)
,它可以立即为您提供脚下地形的高度,而不必投射。
然而,任何不平凡的项目都有不止一个 Terrain。 (事实上 ,任何物理上大的场景都不可避免地具有地形拼接,以某种方式。)
Unity 有一个函数 Terrain.activeTerrain
,它 - 这不是我编的 - 给你:"first one loaded"
显然那是完全没用的。
事实上,有没有快速获取地形的方法"under you"?然后你可以使用快速函数 .sampleHeight
?
{请注意,当然,您可以...施放以在您下方找到地形!但是你会有你的高度,所以没有必要担心 .sampleHeight
!}
简而言之,是否有一个与 sampleHeight
一起使用的匹配函数,它让该函数知道 哪个 地形用于给定的 xyz?
(或者实际上,sampleHeight
只是一个相当无用的演示功能,只能在一个地形的演示中使用吗?)
Is there in fact a fast way to get the Terrain "under you" - so as to then use the fast function .sampleHeight ?
是的,可以做到。
(Or indeed, is sampleHeight just a fairly useless demo function, usable only in demos with one Terrain?)
没有
场景中有 Terrain.activeTerrain
which returns the main terrain in the scene. There is also Terrain.activeTerrains
(注意末尾的 "s")returns 活动地形。
用Terrain.activeTerrains
得到地形returnsTerrain
数组然后用Terrain.GetPosition
函数得到它的位置。通过寻找距离玩家位置最近的地形来获取当前地形。您可以使用 Vector3.Distance
或 Vector3.sqrMagnitude
(更快)对地形位置进行排序。
Terrain GetClosestCurrentTerrain(Vector3 playerPos)
{
//Get all terrain
Terrain[] terrains = Terrain.activeTerrains;
//Make sure that terrains length is ok
if (terrains.Length == 0)
return null;
//If just one, return that one terrain
if (terrains.Length == 1)
return terrains[0];
//Get the closest one to the player
float lowDist = (terrains[0].GetPosition() - playerPos).sqrMagnitude;
var terrainIndex = 0;
for (int i = 1; i < terrains.Length; i++)
{
Terrain terrain = terrains[i];
Vector3 terrainPos = terrain.GetPosition();
//Find the distance and check if it is lower than the last one then store it
var dist = (terrainPos - playerPos).sqrMagnitude;
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrains[terrainIndex];
}
用法:
假设玩家的位置是transform.position
:
//Get the current terrain
Terrain terrain = GetClosestCurrentTerrain(transform.position);
Vector3 point = new Vector3(0, 0, 0);
//Can now use SampleHeight
float yHeight = terrain.SampleHeight(point);
虽然可以用 Terrain.SampleHeight
做到这一点,但这可以通过从玩家位置到地形的简单光线投射来简化。
Vector3 SampleHeightWithRaycast(Vector3 playerPos)
{
float groundDistOffset = 2f;
RaycastHit hit;
//Raycast down to terrain
if (Physics.Raycast(playerPos, -Vector3.up, out hit))
{
//Get y position
playerPos.y = (hit.point + Vector3.up * groundDistOffset).y;
}
return playerPos;
}
原来答案很简单NO,Unity没有提供这样的功能。
Terrain.GetPosition() = Terrain.transform.position = 世界排名
工作方式:
Terrain[] _terrains = Terrain.activeTerrains;
int GetClosestCurrentTerrain(Vector3 playerPos)
{
//Get the closest one to the player
var center = new Vector3(_terrains[0].transform.position.x + _terrains[0].terrainData.size.x / 2, playerPos.y, _terrains[0].transform.position.z + _terrains[0].terrainData.size.z / 2);
float lowDist = (center - playerPos).sqrMagnitude;
var terrainIndex = 0;
for (int i = 0; i < _terrains.Length; i++)
{
center = new Vector3(_terrains[i].transform.position.x + _terrains[i].terrainData.size.x / 2, playerPos.y, _terrains[i].transform.position.z + _terrains[i].terrainData.size.z / 2);
//Find the distance and check if it is lower than the last one then store it
var dist = (center - playerPos).sqrMagnitude;
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrainIndex;
}
您可以使用此功能获取离您当前位置最近的地形:
int GetClosestTerrain(Vector3 CheckPos)
{
int terrainIndex = 0;
float lowDist = float.MaxValue;
for (int i = 0; i < _terrains.Length; i++)
{
var center = new Vector3(_terrains[i].transform.position.x + _terrains[i].terrainData.size.x / 2, CheckPos.y, _terrains[i].transform.position.z + _terrains[i].terrainData.size.z / 2);
float dist = Vector3.Distance(center, CheckPos);
if (dist < lowDist)
{
lowDist = dist;
terrainIndex = i;
}
}
return terrainIndex;
}
然后你可以像这样使用函数:
private Terrain[] _terrains;
void Start()
{
_terrains = Terrain.activeTerrains;
Vector3 start_pos = Vector3.zero;
start_pos.y = _terrains[GetClosestTerrain(start_pos)].SampleHeight(start_pos);
}
public static Terrain GetClosestTerrain(Vector3 position)
{
return Terrain.activeTerrains.OrderBy(x =>
{
var terrainPosition = x.transform.position;
var terrainSize = x.terrainData.size * 0.5f;
var terrainCenter = new Vector3(terrainPosition.x + terrainSize.x, position.y, terrainPosition.z + terrainSize.z);
return Vector3.Distance(terrainCenter, position);
}).First();
}