Vengeance
Vengeance

Reputation: 3

(Unity C#) NPC Movement Script + Animations Not Running Smoothly

I have created a NPC that follows the main player. When the player is in a certain range of the NPC, the NPC is supposed to walk, run, and attack based on the distance between the player and the NPC.The NPC has a C# MutantMovement Script attached, which also contains Animations. The NPC is also a NavMesh Agent. My problem is that the Animations do not run smoothly with the logic. I hope someone can help. Below is the MutantMovement Script and the Animation Controller.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

[RequireComponent (typeof (NavMeshAgent))]
[RequireComponent (typeof (Animator))]
public class MutantMovement : MonoBehaviour {
    [SerializeField] private float _range = 10f;
    public Transform _goal; // destination
    public Transform _player;
    private Animator _anim;
    private bool _alive;
    private float _distance;
    private NavMeshAgent _agent;




    void Start () 
    {
        _goal = GameObject.Find("Player").transform;
        _player = GameObject.Find("Player").transform;
        _alive = true; 
        // get a reference to the NavMesh Agent component
        _agent = GetComponent<NavMeshAgent>();
        _anim = GetComponent<Animator>();
    }

    void Update()
    {

        Vector3 direction = _goal.position - this.transform.position;
        float angle = Vector3.Angle(direction, this.transform.forward);
        if(Vector3.Distance(_goal.position, this.transform.position) < 10 && 
angle < 50){

            _anim.SetBool("isIdle", false);
            if ((_alive && direction.magnitude > 5))
            {
                _agent.destination = _goal.position;
                _anim.SetBool("isWalking", true);
                _anim.SetBool("isAttacking", false);
                _anim.SetBool("isRunning", false);
                if((_alive && direction.magnitude > 6.5)){
                    _agent.destination = _goal.position;
                    _anim.SetBool("isRunning", true);
                    _anim.SetBool("isWalking", false);
                    _anim.SetBool("isAttacking", false);
                }
            }
            else{
                _agent.isStopped = false;
                _anim.SetBool("isAttacking", true);
                _anim.SetBool("isWalking", false);
                _anim.SetBool("isRunning", false);
            }
        }else{
            _anim.SetBool("isIdle", true);
            _anim.SetBool("isWalking", false);
            _anim.SetBool("isAttacking", false);
        }
    }
    public void SetAlive(bool alive)
    {
        _alive = alive;
    }
}

Animation Controller

Upvotes: 0

Views: 1810

Answers (1)

alpha_rats
alpha_rats

Reputation: 128

I would use Animator triggers rather than booleans in your particular case, so the transitions from one animation to another are triggered only once.

In your state machine, you can then set the transitions so :

walking or attacking ---[trigger run]----> running animation
running or walking -----[trigger attack]---> attack animation
running or attacking ----[trigger walk] ---> walking animation

It makes it overall easier as you don't have to turn the other bools to false when triggering a new animation state.

Another thing you can check to make sure the transitions are fluid, is to have a look at the exit time of your animations - if you turn "Has Exit Time" off, your transitions will be instant. You can find this option if you open your animator controller and click on your state machine transition arrow.

Upvotes: 0

Related Questions