Attack System Error(s) (Object Reference Not Set to Instance of Object)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class attack : MonoBehaviour
{
    Animator animator;
    AudioSource audioSource;

    PlayerInput playerInput;
    PlayerInput.MainActions input;

    public Camera cam;

    [Header("Attacking")]
    public float attackDistance = 3f;
    public float longAttackDistance = 4f;
    public float attackDelay = 0.4f;
    public float attackSpeed = 1f;
    public float longAttackSpeed = 0.4f;
    public int attackDamage = 1;
    public int longAttackDamage = 2;
    public LayerMask attackLayer;

    public GameObject hitEffect;
    public AudioClip thinSwordSwing;
    public AudioClip hitSound;

    bool attacking  = false;
    bool readyToAttack = true;
    int attackCount;

    public const string IDLE = "Idle";
    public const string ATTACK1 = "Attack 1";
    public const string ATTACK2 = "Attack 2";

    string currentAnimationState;

    public void Attack()
    {
        if (!readyToAttack || attacking) return;

            readyToAttack = false;
            attacking = true;

        Invoke(nameof(ResetAttack), attackSpeed);
        Invoke(nameof(AttackRaycast), attackDelay);

        audioSource.pitch = Random.Range(0.9f, 1.1f);
        audioSource.PlayOneShot(thinSwordSwing);

        if (attackCount == 0)
        {
            ChangeAnimationState(ATTACK1);
            attackCount++;
        }
        else
        {
            ChangeAnimationState(ATTACK2);
            attackCount = 0;
        }
    }
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Awake()
    {
        animator = GetComponentInChildren<Animator>();
        audioSource = GetComponent<AudioSource>();

        playerInput = new PlayerInput();
        input = playerInput.Main;
        AssignInputs();
    }

    // Update is called once per frame
    void Update()
    {
        if (input.Attack.IsPressed())
        { Attack(); }

        SetAnimations();
    }
    void ResetAttack()
    {
        attacking = false;
        readyToAttack = true;
    }
    void AttackRaycast()
    {
        if(Physics.Raycast(cam.transform.position, cam.transform.forward, out RaycastHit hit, attackDistance, attackLayer))
        {
            HitTarget(hit.point);

        }
    }
    void HitTarget(Vector3 pos)
    {
        audioSource.pitch = 1;
        audioSource.PlayOneShot(hitSound);

        GameObject GO = Instantiate(hitEffect, pos, Quaternion.identity);
        Destroy(GO, 20);
    }

   

    public void ChangeAnimationState(string newState)
    {
        if (currentAnimationState == newState) return;

        currentAnimationState = newState;
        animator.CrossFadeInFixedTime(currentAnimationState, 0.2f);
    }

    void SetAnimations()
    {
        if(!attacking)
        {
            { ChangeAnimationState(IDLE); }
        }
    }

    void AssignInputs()
    {
        input.Attack.started += ctx => Attack();
    }
}

Most likely you animator is null, try to assign it from editor and check if it works.
Also a little reccomendation: Do not use strings to identify things, in you case states, rather use enums, they suit this case perfectly

1 Like