有限状态机问题

时间:2014-02-20 18:26:09

标签: c# unity3d state-machine

在Unity3D游戏引擎中使用C#为我的游戏AI类构建FSM。我现在有2个简单的游戏对象,一个Cube(AI)和一个子弹(在调用函数时实例化,下面是代码)。只是为更复杂的密克罗尼西亚联邦建立基础,但是在学期的早期,所以我正在学习它。

我的AI一次投出5发子弹投射子弹,当bulletCount为5然后它会改变状态。所以基本上我只想要它射出5发子弹,等待我选择的时间,重新加载,再射5次,并继续相同的过程。基本上发生的事情完全是我想要它首先做的,一旦它退出我的IEnumerator,它就会射出无数的子弹,即使它是第一次做到我想要的。

AIClass

using UnityEngine;
using System.Collections;

public class AIClass : MonoBehaviour
{

public GameObject bullet;
int bulletCount;
float stunned;

public enum CombatAIStates
{
    Firing = 0,
    Stunned = 1,
    Reloading = 2,
    Following = 3,
    Idle = 4
}

public CombatAIStates currentState = CombatAIStates.Firing;

void Update()
{

    switch (currentState) 
    {
    case CombatAIStates.Firing:
        StartCoroutine (WaitMethod ());

        if(bulletCount <= 5)
        {
            spawnBullets ();
            Debug.Log ("Firing. ");
            Debug.Log ("Bullet: ");
            Debug.Log (bulletCount);
            StartCoroutine (WaitMethod ());
            ++bulletCount;
        }

        if(bulletCount > 5)
        {
            currentState = CombatAIStates.Reloading;

        }
        break;

    case CombatAIStates.Stunned:
            Debug.Log ("Stunned.");
        StartCoroutine(WaitMethod());
        currentState = CombatAIStates.Firing;
        //currentState = CombatAIStates.Firing;
        break;

    case CombatAIStates.Reloading:
        Debug.Log ("Reloading.");
        StartCoroutine (WaitMethod ());
        currentState = CombatAIStates.Stunned;
        break;
    }



}

IEnumerator WaitMethod()
{
    float waitTime = 10;
    Debug.Log ("Before yield.");
    yield return new WaitForSeconds (waitTime);
    Debug.Log ("After yield.");
    bulletCount = 0;

}

void spawnBullets()
{
    Instantiate(bullet, transform.position, transform.rotation);
}
}

1 个答案:

答案 0 :(得分:3)

我怀疑这是你要做的事情,为了简单起见略微剥离:

public int BulletCount = 0;
public enum CombatAIStates
{
    Firing = 0,
    Reloading = 1,
}
CombatAIStates currentState = CombatAIStates.Firing;

// Update is called once per frame
void Update () {
    switch (currentState) {
        case CombatAIStates.Firing:
            if (BulletCount < 5) {
                Debug.Log ("Firing: " + BulletCount);
                ++BulletCount;
            } else {
                currentState = CombatAIStates.Reloading;
                StartCoroutine(Reload ());
            }
            break;
        case CombatAIStates.Reloading:
            // Nothing to do here, Reload() coroutine is handling things.
            // Maybe play a 10 second animation here or twiddle thumbs
            break;
    }
}
IEnumerator Reload()
{
    yield return new WaitForSeconds (10.0f);
    BulletCount = 0;

    //Now update the current combat state
    currentState = CombatAIStates.Firing;       
}

我对原始代码的改动并不多。我刚刚将状态更改为Reload协程,在10秒后切换回Firing并重置bulletCount。或者,您可以在交换机的重新加载情况下进行状态更改。但是,不是调用协程只是检查是否bulletCount >= 5,如果没有,那么重新加载完成,你可以切换回射击。