0
\$\begingroup\$

I have a point and click system in a project prototype in Unity that moves the camera to defined positions around objects in a room when left-clicked and move back to a previous position with right-clicks. However, for one object (a TV), the player is no longer able to return to a defined past position, leaving them stuck and unable to move.

The Point-and-Click system is defined by 5 main scripts: Node, Location, Prop, Interactable, and Game Manager. These define several attributes that drive the point and click system. When I attempt to right-click when in the position for this object, all of those scripts except Location appear in a console error message.

    NullReferenceException: Object reference not set to an instance of an object
Interactable.LeaveInteract () (at Assets/Scripts/Interactibles/Interactable.cs:46)
Prop.Leave () (at Assets/Scripts/Prop.cs:43)
Node.Arrive () (at Assets/Scripts/Node.cs:32)
GameManager.Update () (at Assets/Scripts/GameManager.cs:20)

This is an odd instance because it's set up exactly the same way as all of the other objects yet does not want to move to the previous location upon LeaveInteract call, which lists a previous location (Loc) as a public attribute in my inspector and has been defined. However, the error suggests it's not reading the location in the Loc variable for some reason. Every other object with the same setup has responded fine to this code.

I would like some insight as to why this might be happening as I've fiddled with all of these scripts and can't seem to pinpoint the specific problem. The scripts for the 4 offending scripts are below and while I think it mostly has to do with the Interactable script, the error could signify any one of them as the problem. Additionally, I am new to programming Point-And-Click systems so if there is a better way to factor this code, I'm all ears.

Node.cs

    using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening; //DotweenLibrary

public abstract class Node : MonoBehaviour {
    // This script turns any regular gameObject into a Node that can be placed in a Node List in the Inspector as Per a List
    // Since Location, Prop, and Waypoint are inheriting Node instead of Monobehavior, they'll have many of the same attributes in the Inspector
    public Transform cameraPosition;
    public List<Node> reachableNodes = new List<Node>(); //A list of Nodes to add to or catalogue
    public float tweenFloat = 0.57f;
    public Animator animator;

    [HideInInspector] //Hide public object in Inspector
    public Collider col;

    // Use this for initialization
    void Awake () {
        col = GetComponent<Collider> (); //At start access component collider. If no Collider, it'll be null
        animator = GetComponent<Animator>();
        //col.enabled = false;
    }

    void OnMouseDown () {
        Arrive ();
        //GameManager.ins.currentNode.GetComponent<Prop>().loc.col.enabled = true;
    }

    public virtual void Arrive () {
        //Leave Existing currentNode
        if (GameManager.ins.currentNode != null) {
            **GameManager.ins.currentNode.Leave();**
        }


        //set currentNode
        GameManager.ins.currentNode = this;

        //New Camera Move Code with Camera Rig
        GameManager.ins.rig.AlignTo(cameraPosition);

        // turn off our own Collider
        if (col != null) {
            col.enabled = false;
        }

        //turn on All reachable node's colliders
        foreach (Node node in reachableNodes){
            if (col != null) {
                node.col.enabled = true;
            }
        }

    }
    public virtual void Leave () {
        //turn off All reachable node's colliders
        foreach (Node node in reachableNodes){
            if (col != null) {
                node.col.enabled = false;
                //node.GetComponent<Interactable> ().animTrigger == false;
        }
}
}
}

GameManager.cs

public class GameManager : MonoBehaviour {

    public static GameManager ins;

    [HideInInspector]
    public Node currentNode;

    public CameraRig rig;

    void Awake() {
        ins = this;
    }
    void Update() {
        //If right clicked and the props own collider is null, go back to location
        if (Input.GetMouseButtonDown (1) && currentNode.GetComponent<Prop> () != null) {
            **currentNode.GetComponent<Prop> ().loc.Arrive ();**

            //Turns on colider for location transform if the location's collider was turned off
            if (currentNode.GetComponent<Prop> ().loc.col.enabled == false) {
                currentNode.GetComponent<Prop> ().loc.col.enabled = true;
            }

        }
        // Allows location to go back to origin
        if (Input.GetMouseButtonDown (1) && currentNode.GetComponent<Location> () != null) {
            currentNode.GetComponent<Location> ().origin.Arrive ();

            //turn on All reachable node's colliders
            foreach (Node node in currentNode.GetComponent<Origin>().reachableNodes){
                    node.col.enabled = true;

            }
        }
    }
}

Prop.cs

public class Prop : Node {

    //Loc is the Location where the Prop backs off to on Leave
    public Location loc;
    Interactable inter;
    public AudioClip FlavorLine;
    //public Animator animator;
    AudioSource audiosource;

    void Start () {
        inter = GetComponent<Interactable> ();
        audiosource = GetComponent<AudioSource>();
    }


    public override void Arrive ()
    {
        if (inter != null && inter.enabled) {
            inter.Interact ();
            return;
        }

        base.Arrive ();
        audiosource.PlayOneShot(FlavorLine,1.0f);

        //make this object Interactible
        if (inter != null){
            col.enabled = true;
            inter.enabled = true;
        }
    }

    public override void Leave ()
    {

        if (inter != null) {
            inter.enabled = false;
            **inter.LeaveInteract ();**
            Debug.Log("Leave");
        }
    }
}

Interactable.cs

[RequireComponent(typeof(Prop))] //Failsafe to make this only make props "Interactable". This MUST be on a Prop.
public class Interactable : MonoBehaviour {

    Animator animator;
    public GameObject Anim_object;
    //public bool ActiveAnimTrigger;
    public Vector3 startPos;
    //public transform currentPos;
    public Vector3 movingTo;
    public GameObject GUIinterface;

    float t;
    public float targetTime;

    // Use this for initialization
    void Start () {
        this.enabled = false; //Makes things uninteractible by default on start
        animator = Anim_object.GetComponent<Animator> ();
        //ActiveAnimTrigger = animator.GetBool("active");
        startPos = transform.position;
    }

    public void Interact(){
        Debug.Log ("interacting with " + name);
        animator.SetBool ("active", true);
//      GUIinterface = true;
        //moveObject ();
    }

    public void LeaveInteract(){
        Debug.Log ("Leaving " + name);
        **animator.SetBool ("active", false);**
    }


}
\$\endgroup\$
  • 1
    \$\begingroup\$ I notice there's a lot of commented code - can you please remove any code we don't need to look at here, to keep the question as concise as possible? Can you also add comments to indicate which lines are the 46 / 43 / 32 / 20 referenced in the stack trace? Since we don't have your original line numbers to go by, it's easiest if you flag those lines specifically. \$\endgroup\$ – DMGregory Sep 22 '17 at 11:08
  • \$\begingroup\$ Fortunately here there's only one line in LeaveInteract that can throw a null reference exception, and that's animator.SetBool("active", false). So it looks like your animator variable is null. Try checking in Start to verify that the component has found a valid animator and log if it's missing. If it can't find it at the start, show us the inspector & hierarchy for that object. If it does find it at the start but it's null later, then some other script is destroying it, and we'll need more info to speculate on what that is. (Though usually we'd get a DestroyedReferenceException then) \$\endgroup\$ – DMGregory Sep 22 '17 at 11:12
  • \$\begingroup\$ Sorry about the comments. Will try to clean that up. I've updated the coding samples to put ___ around the specific lines the error is mentioning. I did consider the thing you mentioned about the animator, but what mystifies me is that the Animator has always been there, which is why this confuses me so much. I don't understand why it doesn't see anything. \$\endgroup\$ – JSparks Sep 24 '17 at 7:33
  • \$\begingroup\$ So something odd happened. By taking the Interactable script off the object, the glitch no longer occurs. However, it must be completely removed from the object to do this. Simply turning the script off doesn't fix the problem. Furthermore, as long as the Interactable Script is on the object, the Prop script can't be removed either. This is technically fixed, but I wouldn't like to know why this might be happening so I can understand what might be the technical issue behind it. If I don't know why this object wasn't working where others work fine, this may lead to problems later on. \$\endgroup\$ – JSparks Sep 24 '17 at 7:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.