State machine for a game object in Unity doesn't seem to be working. Instead of changing from "stagger" to "idle", it just keeps moving

Viewed 130

So I'm developing my first game in Unity currently (following a series by Mister Taft on YouTube called "Make a game like Zelda using Unity and C#" and just finished the 19th video).

I've currently got a "Log" enemy and am working on a knockback feature. I've followed the way that it is approached in the series is by creating a state machine that changes the Log's state to "stagger" for a couple of seconds, then return it to "idle" so it can change itself to "walk."

Whenever I hit the Log, however, it gets stuck in the stagger state and drifts without stopping until it hits a collider (note it doesn't change back to idle/walk even when it does hit the collider). If I can hit the Log correctly, sometimes, the player will actually also drift in the opposite direction.

Relevant code:

public class Log : Enemy {

    private Rigidbody2D myRigidBody;
    public Transform target;
    public float chaseRadius;
    public float attackRadius;
    public Transform homePosition;
    public Animator anim;

    // Use this for initialization
    void Start () {
        currentState = EnemyState.idle;
        myRigidBody = GetComponent<Rigidbody2D> ();
        anim = GetComponent<Animator> ();
        target = GameObject.FindWithTag ("Player").transform;

    }
    
    // FixedUpdate is called by physics.
    void FixedUpdate () {
        CheckDistance ();
    }

    //Log finds and walks towards Player.
    void CheckDistance(){
        if (Vector3.Distance (target.position, transform.position) <= chaseRadius && Vector3.Distance (target.position, transform.position) > attackRadius
&& currentState != EnemyState.stagger) 
        {
            Vector3 temp = Vector3.MoveTowards (transform.position, target.position, moveSpeed * Time.deltaTime);
            myRigidBody.MovePosition (temp);
            ChangeState (EnemyState.walk);
        } 
    }

    private void ChangeState(EnemyState newState){
        if (currentState != newState) 
        {
            currentState = newState;
        
        }
    }
}
public class Knockback : MonoBehaviour {

    public float thrust;
    public float knockTime;

    private void OnTriggerEnter2D(Collider2D other){

        if (other.gameObject.CompareTag ("breakable")) 
        {
            other.GetComponent<Pot>().Smash();
        }

        if(other.gameObject.CompareTag("enemy"))
        {
            Rigidbody2D enemy = other.GetComponent<Rigidbody2D>();
            if (enemy != null) 
            {
                enemy.GetComponent<Enemy> ().currentState = EnemyState.stagger;
                Vector2 difference = enemy.transform.position - transform.position;
                difference = difference.normalized * thrust;
                enemy.AddForce (difference, ForceMode2D.Impulse);
                StartCoroutine (KnockCo (enemy));
            }
        }
    }

    private IEnumerator KnockCo(Rigidbody2D enemy){
        if (enemy != null) 
        {
            yield return new WaitForSeconds (knockTime);
            enemy.velocity = Vector2.zero;
            enemy.GetComponent<Enemy>().currentState = EnemyState.idle;
        }
    }
}
public enum EnemyState{
    idle,
    walk,
    attack,
    stagger
}

public class Enemy : MonoBehaviour {

    public EnemyState currentState;
    public int enemyHealth;
    public string enemyName;
    public int baseAttack;
    public float moveSpeed;
}

I've tried to add an else statement after the void CheckDistance in Log.cs, but that resulted in the Log having jittery movement and jumping back along its path. I'm at a loss. Any help would be greatly appreciated!

0 Answers
Related