使用 Switch 进行简单的 Unity3D 巡逻运动

Using Switch for Simple Unity3D Patrol Movement

我正在使用 switch 语句为敌人创建两种移动类型:前进和后退。敌人有三个巡逻点。当他开始时,我希望他从第一个巡逻点开始移动,并在他到达第二个巡逻点(空 3D 游戏对象)时将当前点加 1,依此类推。然后我让他在到达终点的时候反转方向

switch (moveType)
        {
        case MoveType.Forward:
            if (transform.position == patrolPoints[currentPoint].position)
            {
                currentPoint ++;
            }
            break;
        case MoveType.Backwards:
            if (transform.position == patrolPoints[patrolPointsLength].position)
            {
                currentPoint --;
            }
            break;
        }

问题是,我想不出 "trigger" 这两个 MoveType 的方法。我如何编写代码以便当敌人到达他的最后一个巡逻点时,他切换到 MoveType.Backwards?我确定我正在使这种方式比需要的更难。感谢您的帮助!

如果我真的想使用 switch 语句,我会这样做:

    float someSmallValue = 0.5f; // Adjust this as per your needs

    if (Vector3.Distance(transform.position, patrolPoints[currentPoint].position) < someSmallValue)
    {
        switch (moveType)
        {
            case MoveType.Forward:
                currentPoint++;
                if (currentPoint > patrolPoints.Length - 1)
                {
                    currentPoint -= 1;
                    moveType = MoveType.Backwards;
                }
            break;

            case MoveType.Backwards:
                currentPoint--;
                if (currentPoint < 0)
                {
                    currentPoint = 1;
                    moveType = MoveType.Forward;
                }
            break;
        }

    }

我认为将 currentPoint 重命名为 targetPoint 会使这段代码的变量名称更加清晰。

编辑:我忘了递减 Backwards case 块内的 currentPoint。更新了我的答案。

我这里的解决方案增加了一些东西,比如暂停时间。它还确保快速移动的实体不会超过目的地并且不会掉头之类的。

// Movement speed normalized. So 1 is instantaneous travel and zero is no movement.
public float movementSpeed = 0.025;
// Let's add a 'pause' time where the unit waits a while at the turning point.
public float waitTime = 1;
// Lets say the list has 5 points.
public List<Vector3> patrolPoints ... 
// We keep track of our starting and ending points. Here we start at zero and move to position 1.
public Vector2 currentLeg = new Vector2(0,1);

// We use a coroutine
IEnumerator Patrol()
{
    // This keeps track of where we are. 0 is at the starting point and 1 is at the destination.
    float progress = 0;

    while(true)
    {
            Vector3 startingPoint = patrolPoints[currentLeg.x];
            Vector3 destination = patrolPoints[currentLeg.y];

            // Please note this won't compile. It's for brevity. You must lerp x,y,z indiviualy in C#.
            transform.position = Mathf.Lerp(startingPoint, destination, progress);
            progress+= movementSpeed;

            // If we are at our destination
            if(progress >=1 )
            {
                // Reset our progress so wa can start over.
                progress = 0;

                // Our current point is now what our destination was before.
                currentLeg.x = currentLeg.y;

                switch(moveType)
                {
                    case MoveType.Forward: 
                    {
                        // If this condition is true then it means we are at the final point (4 in this case). So we invert the movement direction and set the current point to 3.
                        if(currentLeg.y == patrolPoints.Count()-1)
                        {
                            currentLeg.y -= 1;
                            moveType = MoveType.Backwards;

                           // We wait 1 seconds and then do everything again.
                           yield return new WaitForSeconds(waitTime);
                        }
                        else
                            currentLeg.y++;
                    }
                    break;
                    case MoveType.Backward:
                    {
                        // If this condition is true then it means we are at the starting point (0). So we invert the movement direction and set the current point to 1.
                        if(currentLeg.y == 0)
                        {
                            currentLeg.y += 1;
                            moveType = MoveType.Forward;

                            // We wait 1 seconds and then do everything again.
                            yield return new WaitForSeconds(waitTime);
                        }
                        else
                            currentLeg.y--;
                    }
                    break;
                }

            }
    }
}

为了快速解决问题,Jayson 的回答会更好。但是单位移动快了可能会失败,单位移动太慢会过早停止。

编辑:等待时间错误。

因为一次只能选择 1 个枚举,所以您想使用开关进行巡逻?

为什么不使用 public Transform target; 变量并让您的 AI 始终遵循该变量中的内容?然后只需制作一个空的游戏对象并将其粘贴到该变量中,他就会跟随它 无论它走到哪里。他不会局限于 "Forward" 和 "Backward",当你想为一个从 "Left" 移动到 "Right"[ 的 AI 回收代码时,你不必重新编码或感到困惑=16=]

这将加快执行速度,清理你的代码,摆脱成吨的代码行,你仍然可以使用你的 switch 语句,因为这实际上会让你的代码拥有更多的动态能力,比如如:

public enum ActionType
{
    Patrol,
    Veer,
    Stop
}

假设他正在巡逻,在到达目标的半路上发现了一个敌人,ActionType curAction;可以设置为ActionType.Veer,现在他正在偏离巡逻线攻击敌人,在你之后可以将其设置回 ActionType.Patrol,然后他继续前往目标。

因此,对于巡逻,您可以设置一个 public List<Vector3> wayPoints; 并在其中添加一堆 Vector3。当他到达目标时,他可以停下来一两秒,然后让空的游戏对象目标跳转到列表中的下一个 vector3。