xyberr
xyberr

Reputation: 67

Error "Object reference not set to an instance of an object" when dealing with prefab

I was trying to get the camera follow my player (which is instantiated from a prefab) but I keep getting the error in my camera script.

My camera script (the error is in line offset = transform.position - Game.currentPlayer.transform.position;):

public class CameraControl : MonoBehaviour
{
    private Vector3 offset;

    private void Awake()
    {
        offset = transform.position - Game.currentPlayer.transform.position;
    }

    void LateUpdate()
    {
        transform.position = Game.currentPlayer.transform.position + offset;
    }
}

I set my currentPlayer variable here:

void Start()
    {
        GameObject newPlayer = Instantiate(player,transform.position,transform.rotation);
        newPlayer.name = "Player";
        currentPlayer = newPlayer;
    }

If you need anymore scripts to help, just ask :)

Upvotes: 1

Views: 94

Answers (1)

derHugo
derHugo

Reputation: 90872

Awake is called before Start. Actually even all Awake methods are finished before the first Start is called (also see Order of Execution for Event Functions).

Therefore the reference is not set yet in Awake.

You will have to either move it to the Start method or move the instantiation part to Awake.

In both cases it is still no warranty that the Game script will have its Start executed before the GameControl. Therefore you will still have to adjust the Script Execution Order thus that Game is always excuted before GameControl. Simply

  • open the Edit > Project Settings > Script Execution Order
  • drag&drop in the Game script before the DefaultTime block
  • optionally also sortr already existing items

Alternatively you could use an event system:

public class Game : MonoBehaviour
{
    public static event Action OnInitilalized;

    public static GameObject currentPlayer;

    privtae void Start()
    {
        GameObject newPlayer = Instantiate(player,transform.position,transform.rotation);
        newPlayer.name = "Player";
        currentPlayer = newPlayer;

        OnInitilalized?.Invoke();
    }
}

and then in the GameControl add a callback to the OnInitialized event like

private void Awake()
{
    // This makes sure the callback is added only once
    Game.OnInitialized -= OnGameInitialized;
    Game.OnInitialized += OnGameInitialized;
}

private void OnDestroy()
{
    // always make sure to remove callbacks if no longer needed
    Game.OnInitialized -= OnGameInitialized;
}

privtae void OnGameInitialized()
{
    offset = transform.position - Game.currentPlayer.transform.position;
}

Upvotes: 1

Related Questions