代码之家  ›  专栏  ›  技术社区  ›  Fattie

团结,得到“真实”的当前地形?

  •  3
  • Fattie  · 技术社区  · 6 年前

    团结是有作用的 Terrain.sampleHeight(point) 这是伟大的,它立即给你脚下的地形高度,而不是必须投。

    然而,任何非平凡的项目都有不止一个地形。(事实上,任何物理上的大型场景都不可避免地以地形为特征 缝合 ,不管怎样。)

    团结是有作用的 Terrain.activeTerrain 哪个- 我不是瞎编的 -给你:第一个装的

    显然,这是完全无用的。

    事实上,有没有一个快速的方法让地形“在你下面”?然后可以使用fast函数 .sampleHeight ?

    {请注意,当然,你可以。。。投出一个地形在你下面!但是你会有你的高度,所以不用担心 .样品高度 !}

    sampleHeight 让函数知道 给定xyz要使用的地形?

    (或者说确实是 只是一个相当无用的演示功能,只能在一个地形的演示中使用?)

    2 回复  |  直到 4 年前
        1
  •  3
  •   miralong    5 年前

    地形.GetPosition() = 地形变换位置=世界地位

    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;
    }
    
    
        2
  •  2
  •   Programmer    6 年前

    然后使用快速功能。sampleHeight?

    是的,可以做到。

    (或者说,sampleHeight只是一个相当无用的演示函数, 只能在一个地形的演示中使用?)


    Terrain.activeTerrain 返回 主要的 场景中的地形。还有 Terrain.activeTerrains 活跃地形 在现场。

    获得地形 它回来了 Terrain 然后使用数组 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;
    }
    
        3
  •  1
  •   Fattie    6 年前

    事实证明答案是否定的,统一并不能提供这样的功能。

        4
  •  0
  •   Ingo    4 年前

    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);
    
      }