【问题标题】:monster ai patrol and idle怪物ai巡逻和闲置
【发布时间】:2019-09-07 14:21:54
【问题描述】:

我正在用怪物(RPG)制作游戏,我想做的是怪物左右移动(巡逻),等待一段时间后它会静止不动(空闲)。 所以一开始就是怪物:

  1. 移动 5 秒,
  2. 然后变为空闲,在空闲 3 秒后,
  3. 它又动了

这个过程一次又一次地无限重复,我写的代码只是每1秒不停地改变Idle和Patrol,我不知道,希望你能帮我弄清楚,谢谢!

`using System.Collections; 
using System.Collections.Generic; 
using UnityEngine;

public class MonsterMove : MonoBehaviour { [SerializeField] private float 
MinPatrolTime, MaxPatrolTime, MinIdleTime, MaxIdleTime; [SerializeField] 
private bool ShouldBeIdle=false; public float MonsterMoveSpeed; public 
float Distance=2f; [SerializeField] private bool ShouldBePatroling = 
true; private bool MovingRight = true;

public Transform groundDetection;
private void Start()
{
}
private void Update()
{

}
 void FixedUpdate()
{
    if (ShouldBePatroling&&!ShouldBeIdle)
 {
     Move();
     StartCoroutine(PatrolTime());
 }
 else if (ShouldBeIdle==true&&!ShouldBePatroling) { //Idle Anim
     Debug.Log("Doing Idle Anim");
     StartCoroutine(IdleTime());
 }

 }
 void Move()
 {
 transform.Translate(Vector2.right * MonsterMoveSpeed * Time.deltaTime);
 int layer_mask1 = LayerMask.GetMask("Ground");
 RaycastHit2D groundInfo = Physics2D.Raycast(groundDetection.position, 
 Vector2.down, Distance, layer_mask1);
 if (groundInfo.collider == false)
 {
     if (MovingRight == true)
     {
         transform.eulerAngles = new Vector3(0, -180, 0);
         MovingRight = false;
     }
     else
     {
         transform.eulerAngles = new Vector3(0, 0, 0);
         MovingRight = true;
     }
     }
  }
   IEnumerator PatrolTime()
 {
 yield return new WaitForSeconds(Random.Range(MinPatrolTime, 
 MaxPatrolTime));
 ShouldBePatroling = false;
 ShouldBeIdle = true;
 }
  IEnumerator IdleTime()
 {
 yield return new WaitForSeconds(Random.Range(MinIdleTime, MaxIdleTime));
 ShouldBePatroling = true;
 ShouldBeIdle = false;`
 }

【问题讨论】:

    标签: c# unity3d animation artificial-intelligence


    【解决方案1】:

    在你FixedUpdate 中,即使已经启动的协程仍在运行,你也在启动协程,从而弄乱了你的状态变量。 您可以引入更多状态变量来检查怪物当前是否已经移动/空闲,因此不需要启动协程。如果您使用enum 而不是多个bools(请参阅state pattern),则可能如下所示:

    public class MonsterMove : MonoBehaviour
    {
        ...
    
        protected enum State
        {
            Idle,
            StartPatrolling,
            Patrolling,
            StopPatrolling,
        }
        protected State state = State.StartPatrolling;
    
        ...
    
        void FixedUpdate()
        {
            switch (state)
            {
                case State.StartPatrolling:
                    {
                        StartCoroutine(PatrolTime());
                        state = State.Patrolling;
                        break;
                    }
                case State.StopPatrolling:
                    {
                        StartCoroutine(IdleTime());
                        state = State.Idle;
                        break;
                    }
                case State.Patrolling:
                    {
                        Move();
                        break;
                    }
                case State.Idle:
                    {
                        // nothing to be done
                        break;
                    }
            }
        }
    
        ...
    
        IEnumerator PatrolTime()
        {
            yield return new WaitForSeconds(Random.Range(MinPatrolTime, MaxPatrolTime));
            state = State.StopPatrolling;
        }
    
        IEnumerator IdleTime()
        {
            yield return new WaitForSeconds(Random.Range(MinIdleTime, MaxIdleTime));
            state = State.StartPatrolling;
        }
    }
    

    此外,当没有碰撞时,您似乎会在 Move 方法中切换方向,而在发生碰撞时您可能希望更改为(参见 docs):

    if (groundInfo.collider != null)
    

    【讨论】:

      猜你喜欢
      • 2019-06-07
      • 1970-01-01
      • 2014-07-03
      • 1970-01-01
      • 1970-01-01
      • 2021-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多