Calling GetComponent on an instantiated prefab returns null,Calling GetComponent on an instantiated prefab

This seems to be a common problem but I haven’t found a solution to it yet.

I’m trying to create an enemy that can shoot projectiles at the player, so the projectile is a prefab which has a script named “attack” with the public method “shoot”, and the enemy script has a public variable with the prefab GameObject Attack. Whenever I instantiate a new Attack GameObject atk then call atk.GetComponent() it returns null.

This only happens specifically with instantiated prefabs. When I use an Attack GameObject that’s already on the scene I’m able to get the attack script. It also seems to only apply to scripts, since calling GetComponent on any pre-built components like Rigidbody2D was successful.

Edit: example code that doesn’t work

public class Enemy : MonoBehaviour
{
  public GameObject attack; //the Attack prefab
  
  void Start() {}
  void Update() {}
  
  void spawnAttack()
  {
    GameObject a = Instantiate(attack, transform.position, Quaternion.identity);
    a.GetComponent<AttackScript>().shoot(new Vector2(10f, 10f)); // this gets null reference exception
  }
}

public class AttackScript : MonoBehaviour
{
  Rigidbody2D rb;
  
  void Start()
  {
    rb = GetComponent<Rigidbody2D>();
  }
  void Update() {}

  public void shoot(Vector2 direction) {
    rb.velocty = direction;
  }
}

code that does work:

// this works:
public GameObject attack; //the GameObject I dragged on-screen

void Start() {
  attack.GetComponent<AttackScript>().shoot(new Vector2(10f, 10f));
}

// this also works:
public GameObject attack; //the Attack prefab

void spawnAttack() {
  GameObject a = Instantiate(attack, transform.position, Quaternion.identity);
  a.GetComponent<Rigidbody2D>().velocity = new Vector2(10f, 10f);
}

Post your code please, it will be a lot easier

Try forcing the type of the prefab to have a Attack component public class Enemy : MonoBehaviour { public AttackScript attack; //the Attack prefab void spawnAttack() { AttackScript a = Instantiate(attack, transform.position, Quaternion.identity); a.shoot(new Vector2(10f, 10f)); } }

1 Answer

1

Well the exact NullReference Exception would actually help. Because it’s most likely not the call to shoot() that is causing the NullReference exception but inside shoot your access to velocity because your variable “rb” is null.

You initialize “rb” inside Start. However Start is called before the next Update callback is called. So it will of course not be called between your call of Instantiate and your shoot() call. Therefore rb is still null when you call shoot(). You should use Awake to initialize such internal references. However it would actually be easier to make the rb variable public and assign the reference in the inspector of the prefab. That way you don’t need the GetComponent call at all.

Note that Awake will be called immediately when the object is created. So it will be called from inside the Instantiate call or when created dynamically from inside the AddComponent call. That means Awake will be finished before Instantiate returns and therefore before you call shoot().

Note that if this doesn’t solve your issue, then your AttackScript is not attached to the root object of your prefab. GetComponent will only look for components on that gameobject, not for components on nested child objects.

That was exactly it, thank you! I added the Rigidbody as a public variable and that solved the issue.