NullReferenceException from GetComponent on Instantiated object

Hi,

A. Problem:
I’m writing a n-body gravity simulation and I’m currently getting the following NullReferenceException errors while trying to get a reference to an instantiated gameobject via GetComponent.

  1. NullReferenceException: Object reference not set to an instance of an object Init.Awake () (at Assets/Scripts/Init.cs:12)

  2. NullReferenceException: Object reference not set to an instance of an object GravityManager.FixedUpdate () (at Assets/Scripts/GravityManager.cs:53)

Any help would be greatly appreciated!

B. Expected behavior
Init.cs should:

  1. Instantiate a GravityManager instance
  2. Instantiate Sphere “sphere1” (line 12), which should be added to the gravity manager’s Sphere list “bodies”. <This is where the NullReferenceException is occurring>

The gravity manager instance should update the positions of each sphere in “bodies” each frame via FixedUpdate(). Currently, the manager only implements SHM about the origin using a 4th order symplectic integrator (Symplectic integrator - Wikipedia).

C. Code
(also at: orbits/Assets/Scripts at gm · Justin08784/orbits · GitHub)
Init.cs:

using UnityEngine;

public class Init : MonoBehaviour
{
    public GameObject Sphere_Prefab;
    public GameObject Gravity_Manager_Prefab;

    void Awake()
    {
        Instantiate(Gravity_Manager_Prefab, Vector3.zero, Quaternion.identity);
        GameObject sphereObject1 = Instantiate(Sphere_Prefab, new Vector3(2, 0, 0), Quaternion.identity);
        Sphere sphere1 = sphereObject1.GetComponent<Sphere>();
        // Sphere sphere2 = Instantiate(Sphere_Prefab, new Vector3(-2, 0, 0), Quaternion.identity).GetComponent<Sphere>();

        GravityManager.register_body(sphere1);
        // GravityManager.register_body(sphere2);
    }
}

GravityManager.cs:

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

public class GravityManager : MonoBehaviour
{
    private static GravityManager Instance; // there should be only 1 manager
    private static List<Sphere> bodies;

    private readonly double c = Math.Pow(2.0, 1.0/3.0);

    /* integrator coeffs */
    double[] cs; // displacement update coeffs
    double[] ds; // velocity update coeffs

    private double dt = 0.01;

    private int upd_cnt = 0;

    private void Awake()
    {
        if (Instance != null) {
            // manager already init
            Destroy(this); 
            return;
        }

        Instance = this;
        DontDestroyOnLoad(Instance);

        cs = new double[4] {0.5, 0.5*(1.0-c), 0.5*(1.0-c), 0.5};
        ds = new double[4] {0.0,         1.0,          -c, 1.0};

        double divisor = 2.0 - c;
        for (int i = 0; i < cs.GetLength(0); i++) {
            cs[i] /= divisor;
            ds[i] /= divisor;
        }
    }

    public static void register_body(Sphere sphere)
    {
        bodies.Add(sphere);
    }
    double compute_accel(double x)
    {
        double k_by_m = 1; // k / m
        return -k_by_m * x;
    }

    void FixedUpdate()
    {
        Sphere curr_body = bodies[0];
        for (int i = 0; i < cs.GetLength(0); i++) {
            double a = compute_accel(curr_body.r.x);
            curr_body.v.x += (float) (ds[i] * a * dt);
            curr_body.r.x += (float) (cs[i] * curr_body.v.x * dt);
        }
        upd_cnt += 1;
    }
}

Sphere.cs:

public class Sphere : MonoBehaviour
{
    // Start is called before the first frame update
    public Vector3 v;
    public Vector3 r;

    void Start()
    {
        v = Vector3.zero;
        r = transform.position;
    }

    void FixedUpdate()
    {
        transform.position = r;
    }
}

Hi, I think your code works correctly assuming that prefab references are hooked up correctly.

Note that register_body throws an exception because the bodies list is never created. (Also, I wouldn’t make that list static.)

As a side note, your repository doesn’t contain all the files necessary to open the project correctly. I recommend that you use .gitignore to set up which files you want to add to the repo. Here’s a template: gitignore/Unity.gitignore at main · github/gitignore · GitHub

As far as I can tell your prefab does not contain component “Sphere”. Maybe you can show your Inspector window when you select your prefab in project so I can see all components this prefab has?

Also quick advice, you can rewrite you code like this

public class Init : MonoBehaviour
{
    public Sphere Sphere_Prefab;

void Awake()
    {
        Sphere sphereObject1 = Instantiate(Sphere_Prefab, new Vector3(2, 0, 0), Quaternion.identity);
...

This way you can pass only prefabs that have Sphere component, and you will get Sphere component from instantiated object right away without using GetComponent

I’ve pushed the rest of the project using the provided .gitignore (@apkdev).

Here is a screenshot of my “Sphere” prefab, (@mlodinov):

hey @shinej777 I checked your project and it seems like the problem is here

public class GravityManager : MonoBehaviour
{
	private static List<Sphere> bodies;

I changed it to this

public class GravityManager : MonoBehaviour
{
	private static List<Sphere> bodies = new(); 

and I don’t have any errors right now

1 Like