0

For some reason when I'm in the normal view in-game I am able to link the scripts that I need to call in order to make an animation like so

however, whenever I start the game it automatically removes them from the slots, and it doesn't work

I am completely clueless as to why this may be happening and unity keep giving me errors that say that I'm not setting an instance to my script I really have no clue why this may be happening.

I have 3 scripts that I'm working with that is giving me the problem one is the main script for the enemy vision (I am referencing the other scripts in this one) the second is the enemy animation script which makes him go from idle to attack and the third is an animation for the gun model since I had to make it follow the hands of the enemy

scripts attached bellow

1st script(enemyAI):

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

public class EnemyAi : MonoBehaviour
{

public bool detected;
GameObject target;
public Transform enemy;

public GameObject Bullet;
public Transform shootPoint;

public float shootSpeed = 10f;
public float timeToShoot = 1f;

public EnemyAni Animation;
public GunAni GunAnimation;

void Start()
{
    Animation = GetComponent<EnemyAni>();
    GunAnimation = GetComponent<GunAni>();
}

public void Update()
{
    //makes the enemy rotate on one axis
    Vector3 lookDir = target.transform.position - transform.position;

    lookDir.y = 0f;

    //makes enemy look at the players position
    if (detected)
    {
        enemy.LookAt(target.transform.position, Vector3.up);
        enemy.rotation = Quaternion.LookRotation(lookDir, Vector3.up);
    }

    if (detected == true)
    {
        Animation.LookPlayer = true;
        GunAnimation.ShootPlayer = true;
    }

    if (detected == false)
    {
        Animation.LookPlayer = false;
        GunAnimation.ShootPlayer = false;
    }
}

//detects the player
void OnTriggerEnter(Collider other)
{
    if (other.tag == "Player")
    {
        detected = true;
        target = other.gameObject;
    }
}

void OnTriggerExit(Collider other)
{
    if (other.tag == "Player")
    {
        detected = false;
    }
}
}

2nd Script (EnemyAnimation):

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

public class EnemyAni : MonoBehaviour
{


public Animator animator;

public bool LookPlayer;

public void Start()
{
    animator = GetComponent<Animator>();
}

public void Update()
{
    if (LookPlayer == true)
    {
       animator.SetBool("IsShootingStill", true);
    }
    else
    {
        animator.SetBool("IsShootingStill", false);
    }
}
}

3rd script (GunAnimation):

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class GunAni : MonoBehaviour
    {
    
    
        public Animator animator;
    
        public bool ShootPlayer;
    
        public void Start()
        {
            animator = GetComponent<Animator>();
        }
    
        public void Update()
        {
            if (ShootPlayer == true)
            {
                animator.SetBool("IsShooting", true);
            }
            else
            {
                animator.SetBool("IsShooting", false);
            }
        }
    }

2 Answers2

0

Your code:

void Start()
{
    Animation = GetComponent<EnemyAni>();
    GunAnimation = GetComponent<GunAni>();
}

Searches the GameObject that holds the EnemyAI script for EnemyAni and GunAni. If the GameObject doesn't have those it will return null.

Sounds like you want to remove that code.

Note that if the scripts exist on a child of that GameObject you will need to use GetComponentInChildren

slaw
  • 611
  • 2
  • 7
  • 20
0

There are some things to review, good practices:

  • GameObject target is private for C#, but it is better to put private before.
  • variable names like Bullet Animation GunAnimation should always begin with lowercase, because they might be confused with a Class Name (search in internet for CamelCase and PascalCase).
  • Name should be clear. EnemyAni Animation is not clear enough, because Animation maybe any animation (player, enemy, cube, car, etc.).
    It is better enemyAnimation to be clear, as you did with GunAnimation (only just with lower case at beginning)
  • As slaw said, the Animation must be in the GO attached.

about last item
Let's say you have an empty GO (GameObject) called GameObject1 and you attach EnemyAi script to it.
In Runtime (when game mode begins), it will try to find Animation = GetComponent<EnemyAni>();, but it won't find it

Why?
Because GetComponent<> searches for the Component(Class) that is in the <> (in this case EnemyAni) in its GO (in this case, GameObject1), but the unique script attached to GameObject1 is EnemyAI.

So, you have 3 options:

  • Attach EnemyAni to GameObject1
  • Create another GO (for example, GameObjectEnemyAni), attach the script EnemyAni and drag and drop GameObjectEnemyAni to GameObject1 and delete Animation = GetComponent<EnemyAni>(); in Start

Keep in mind: if you leave that line of code, instead of getting the script EnemyAni from GameObjectEnemyAni, it will run the code Animation = GetComponent<EnemyAni>(); in Start, and obviously, it won't find it

  • Create events. It's a really good practice for avoiding code tight coupling, but that is more advanced stuff.
Hernando N
  • 305
  • 3
  • 7