如何检查地形边界以避免角色走出和摔倒?

时间:2017-02-20 13:39:22

标签: c# unity3d unity5

在顶部

public GameObject[] waypoints;
public Transform target;
public float moveSpeed = 1f;
public float rotationSpeed = 1f;
Transform myTransform;

public float walkSpeed = 10f;
public ThirdPersonCharacter[] thirdPersonCharacter;

Vector3 boundLower;
Vector3 boundUpper;
public Terrain terrain;

醒来并开始:

void Awake()
{
    myTransform = transform;
}

void Start()
{
    GameObject tpc1 = GameObject.Find("ThirdPersonController");
    thirdPersonCharacter[0] = tpc1.GetComponent<ThirdPersonCharacter>();
    GameObject tpc2 = GameObject.Find("ThirdPersonController (1)");
    thirdPersonCharacter[1] = tpc2.GetComponent<ThirdPersonCharacter>();

    waypoints = GameObject.FindGameObjectsWithTag("ClonedObject");

    boundLower = terrain.transform.position - terrain.terrainData.size / 2;
    boundUpper = terrain.transform.position + terrain.terrainData.size / 2;
}

更新:

void Update()
{
    thirdPersonCharacter[0].m_MoveSpeedMultiplier = walkSpeed;
    thirdPersonCharacter[1].m_MoveSpeedMultiplier = walkSpeed;
    WayPoints();
    CheckBounds();
}

WayPoints:

int index = 0;

private void WayPoints()
{
    if (index == waypoints.Length)
        index = 0;

    target = waypoints[index].transform;
    float distance = Vector3.Distance(myTransform.position, target.transform.position);

    myTransform.rotation = Quaternion.Slerp(myTransform.rotation,
          Quaternion.LookRotation(target.position - myTransform.position),
          rotationSpeed * Time.deltaTime);

    myTransform.position += myTransform.forward * moveSpeed * Time.deltaTime;

    if (distance < 2f)
        index++;
}

CheckBounds:

private Vector3 direction = Vector3.forward;

void CheckBounds()
{
    foreach (var child in thirdPersonCharacter)
    {
        var pos = child.transform.position;
        pos.x = Mathf.Clamp(pos.x, boundLower.x, boundUpper.x);
        pos.z = Mathf.Clamp(pos.z, boundLower.z, boundUpper.z);
        if (pos.x == boundLower.x || pos.x == boundUpper.x) direction.x = -direction.x;
        if (pos.z == boundLower.z || pos.z == boundUpper.z) direction.z = -direction.z;
        child.transform.position = pos;
    }
}

一旦我添加了CheckBounds功能并从Update功能中调用它,角色就会走到位。没有移动。没有checkBounds,他们在航点之间走得很好。我想要做的是,如果角色走到地形边缘(绑定),只需让他转身/旋转或停在地方。

我必须说,角色(ThirdPersonController)正在移出地形边界并且只有在我将步行速度改为30或更高时才会下降。但无论如何我想知道如何在其他情况下使用CheckBounds,例如玩家只是走到地形边界。

1 个答案:

答案 0 :(得分:1)

有很多方法可以为游戏制作Boundary。所有的一个例子是Unity web上的第一和第二个教程:

https://unity3d.com/learn/tutorials/projects/roll-ball-tutorial/setting-play-area?playlist=17141

https://unity3d.com/learn/tutorials/projects/space-shooter-tutorial/boundary?playlist=17147

你可以用3种方式做到:

  • 在地图周围创建“Boundary”对象,创建Trigger,一旦有人点击触发器,将他推回/阻止他/不允许他通过
  • 创建填充整个地图的“Boundary”对象。在Trigger方法上创建OnExit,一旦某个对象尝试离开,停止/推回/不允许他通过
  • 坚持编程和一些“地图”概念,你知道Boundaries的位置。在这种情况下你必须检查位置,当对象离开边界时,你必须阻止他 - 这必须发生在每个更新框架,而不仅仅是触发器

根据地图的大小和游戏的复杂程度,我会选择其中一个最佳答案。一旦游戏变得复杂你必须在引擎中创建自己的引擎来处理地图控制&amp;其他事情。但首先:一步一步。

此代码应该有效(一旦有人越过边界,设置为边界位置+最小步进地图中心):

var pos = child.transform.position;
float step = 1; //adjust to fit scale/size of step

if (pos.x <= boundLower.x) pos.x = boundLower.x + step;
if (pos.x >= boundUpper.x) pos.x = boundUpper.x - step;
if (pos.z <= boundLower.z) pos.z = boundLower.z + step;
if (pos.z >= boundUpper.z) pos.z = boundUpper.z - step;

child.transform.position = pos;