質問

Building a FSM for my Game AI class using C# in Unity3D game engine. I have 2 simple game objects right now, a Cube (AI) and a bullet (instantiates when a function is called, code below). Just building the foundation for a much more complex FSM, but early in the semester so building it as I'm learning.

My AI shoots out bullets in throws 5 bullets at a time, when bulletCount is 5 then it changes the state. So essentially I just want it to shoot 5 bullets, wait for a time I choose, reload, shoot 5 more, and continue same process. Basically what happens is perfectly what I want it to do first, as soon as it exits my IEnumerator, it shoots an infinite amount of bullets, even though the first time it did what I wanted.

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);
}
}
役に立ちましたか?

解決

I suspect this is what you are trying to do, stripped down slightly for simplicity:

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;       
}

I didn't change much with the original code. I just moved a state change in to a Reload coroutine that switches back to Firing after 10 seconds and resets the bulletCount. Alternatively you could have the state change in the reload case of your switch. But instead of calling a coroutine just check if bulletCount >= 5, if not then reloading is done and you can switch back to firing.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top