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

时间:2015-06-10 04:46:55

标签: c# unity3d switch-statement

我使用switch语句在敌人上创建两种移动类型:Forward和Backwards。敌人有三个巡逻点。当他开始时,我希望他从第一个巡逻点移动并在他击中他的第二个巡逻点(空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;
        }

问题是,我无法找到一种方法来触发"两个MoveTypes。我如何对此进行编码,以便当敌人击中他的最终巡逻点时,他会切换到MoveType.Backwards?我确信我的这种方式比它需要的更难。谢谢你的帮助!

3 个答案:

答案 0 :(得分:1)

如果我真的想使用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案例块中减少currentPoint。更新了我的答案。

答案 1 :(得分:0)

我在这里的解决方案增加了一些停顿时间。它还可以确保快速移动的实体不会超出目的地而不会转身或其他东西。

// 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的答案会更好。但如果装置移动速度很快,或者如果装置移动太慢,装置会过早停止,可能会失败。

编辑:等待时间错误。

答案 2 :(得分:0)

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

为什么不使用public Transform target;变量并让您的AI始终关注该变量中的内容?然后只需制作一个空的游戏对象并将其粘贴到该变量中,他将跟随的任何地方。他不会被限制为“前进”和“后退”,当你想要回收代码为AI移动“左”到“右”时,你不必重新编码或混淆

这将加快执行速度,清理代码,清除大量代码行,并且您仍然可以使用switch语句,因为这实际上会将代码打开到更具动态性的能力,例如:

public enum ActionType
{
    Patrol,
    Veer,
    Stop
}

让我们说他在目标中途巡逻并发现敌人,ActionType curAction;可以设置为ActionType.Veer,现在他正在偏离巡逻线攻击敌人,然后你可以设置它回到ActionType.Patrol并继续目标。

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