Member variables getting deleted post-initialization

I’m having an absurd problem where I intantiate a number of member variables when the object is created, then by the time I call a method of the object, the variables have been deleted. I’ve been looking for related forum topics for a while now but haven’t been able to find anything remotely similar.

When I run this code it dosen’t post anything about the members failing to initialize, but when SetVelocity() is called it suddenly says that GrappleHeadController is null.

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

public class GrappleController : MonoBehaviour {

    public GameObject GrappleHead;
    public GameObject GrappleChain;

    private GameObject grappleHead;
    private GameObject grappleChain;

    private GrappleHeadController grappleHeadHandle;
    private GrappleChainController grappleChainHandle;

    new private Transform transform;

    // Use this for initialization
    void Start () {

        transform = GetComponent<Transform>();
        transform.position = Vector3.zero;

        grappleHead = Instantiate(GrappleHead, transform);

        grappleHeadHandle = grappleHead.GetComponent<GrappleHeadController>();

        if (grappleHead == null)
        {
            print("Grapple head failed to initialize");
        }

        if (grappleHeadHandle == null)
        {
            print("The Grapple head handle failed to initialize");
        }


    }
   
    // Update is called once per frame
    void Update ()
    {

    }

    public void setVelocity(Vector2 velocity)
    {

        if (grappleHeadHandle == null)
        {
            print("grapple head handle is null");
        }else
        {
            grappleHeadHandle.setVelocity(velocity);
        }

       
    }
}

Any thoughts?

Yeah. What calls setVelocity? It’s probably being called before Start is called. Perhaps in the “Awake” or “Start” of some other script?

My guess as to how you can handle this is to track the velocity passed in through setVelocity and then use the set velocity in Update. If, for some reasons, calling setVelocity is expensive, you have a number of ways of making sure that it happens one time. Here’s an example…

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrappleController : MonoBehaviour {
    public GameObject GrappleHead;
    public GameObject GrappleChain;
    private GameObject grappleHead;
    private GameObject grappleChain;
    private GrappleHeadController grappleHeadHandle;
    private GrappleChainController grappleChainHandle;

    private Queue<Action> pendingChanges;
    new private Transform transform;
    // Use this for initialization
    void Start ()
    {
        transform = GetComponent<Transform>();
        transform.position = Vector3.zero;
        grappleHead = Instantiate(GrappleHead, transform);
        grappleHeadHandle = grappleHead.GetComponent<GrappleHeadController>()
        while (pendingChanges.Count > 0) changes.Dequeue()();
        pendingChanges = null;
    }
  
    // Update is called once per frame
    void Update ()
    {
    }

    void DoChange(Action change)
    {
        if (pendingChanges != null)
            pendingChanges.Enqueue(change);
        else
            change();
    }
    public void setVelocity(Vector2 velocity)
    {
        DoChange(() => grappleHeadHandle.setVelocity(velocity));
    }
}

Don’t get all bent out of shape if that doesn’t compile because of some typo. :slight_smile:

Well after some testing I’ve found that despite me instantiating the object before calling SetVelocity(), the Start() method was being called second. Thanks for bringing this to light Max.

If you want something to happen as something’s instantiated, use the Awake method. Awake gets called before Instantiate returns, while Start gets called at the beginning of the first frame after the object has been instantiated.