Deactivating a script on keydown

Hi All

I’ve run into a strange problem. From everything I have researched this code should allow me to enter into into a trigger collider, have a text pop up to state “press e to talk” and on pressing e show a dialogue UI, turn off the camera control script I have on another game object and reveal the cursor so I can select options in the dialogue.

This works all the way up to the camera controller script being disabled and the cursor becoming visible. My vague suspicion is that it’s because I’m doing this in the update function and there is something I don’t understand about why I shouldn’t do that.

Insight into how to fix this and why I’m getting this wrong would be great.

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

public class DemoConversation : MonoBehaviour
{

    public Canvas ConversationCanvas;
    public bool ConversationEnter;
    public Text EnterConversation;

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            EnterConversation.enabled = true;
            ConversationEnter = true;
        }
    }


    private void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            EnterConversation.enabled = false;
            ConversationEnter = false;
        }
    }

    // Start is called before the first frame update
    void Start()
    {
        ConversationCanvas.enabled = false;
    }

    // Update is called once per frame
    void Update()
    {
        if (ConversationEnter)
        {
            if (Input.GetKeyDown(KeyCode.E))
            {
                ConversationCanvas.enabled = true;
                GameObject.Find("CharacterBase").GetComponent<CameraFollow>().enabled = false;
                Cursor.visible = true;
            }
            if (Input.GetMouseButtonDown(1))
            {
                ConversationCanvas.enabled = false;
                GameObject.Find("CharacterBase").GetComponent<CameraFollow>().enabled = true;
                Cursor.visible = false;
            }
        }
    }
}

Many thanks

For starters, don’t use GameObject.Find, especially in Update(). It’s slow, unreliable, and gives poor feedback. The linked article contains suggestions for better alternatives to GO.F. Perhaps in this case, a singleton would be appropriate.

Tough to tell from this info whether that’s not your main issue though. When you say

Which parts, exactly, do and don’t work? Are you saying that the ConversationCanvas gets enabled, but CameraFollow isn’t disabled and the cursor.visible isn’t set to true? If so, that probably means there’s an exception - do you have any error messages in your Unity console?

And if it’s a NullReferenceException, then it’s a problem with GameObject.Find as described above - either GO.F isn’t finding the object (maybe it’s inactive?) or it’s finding an object that doesn’t have a CameraFollow component.

The ConversationCanvas works fine, CameraFollow doesn’t disable and the cursor doesn’t show.
No errors in the console

So from that your suggesting it’s an exception?

It’s acting like an exception, but it’s odd that you don’t have anything in your Console. Is it possible you’re hiding errors on the console? (Top right button in the console)

it’s not generating any errors except for one advisory about mixed line endings being MAC OS etc, which doesn’t usually harm anything.

Interestingly, I modified the update code to remove the initial text displayed after the lines disabling the other script and showing cursor and I can remove the text line.

I’ve looked at singletons and based on the bit reading and watching, I think I will need to see some more practical examples. I do fear that won’t work in this case as I’m going to need a lot of things to disable that camera script and allow UI elements to be selected.

That’s actually the perfect use case for singletons: one object that many scripts need to access. Make your CameraFollow script a singleton, and then any object can access CameraFollow.instance.enabled easily.

If that line isn’t causing an exception I’m not sure what could be causing those two lines to not work while the one before it does. Try putting two Debug.Log statements (one before and one after those lines, both inside the if block) and confirm that it’s getting executed?

The if statement and things in it are definitely running. I also tried a dirty fix to get around gameobject.find in the hope it might work and it still doesn’t. If statement looks as below and is annotated with working parts, I think the debug logs will not prove anything this doesn’t already show, unless you think otherwise.

if (Input.GetKeyDown(KeyCode.E))
            {
                ConversationCanvas.enabled = true; // this runs
                CameraControl.GetComponent<CameraFollow>().enabled = false; // this doesn't
                Cursor.visible = true; //this doesn't
                EnterConversation.enabled = false; // this does

Looks like it’s worth me looking at this from a singleton point of view as the idea is that all conversations will need to turn off the third person camera move (which is what camera follow does) so that you can select buttons from within the UI. It’s strange that even doing it this way where I explicitly add the item into the CameraControl variable and the CameraFollow element is being found by intelisense it doesn’t work. Stranger still that the cursor won’t activate, but I think that is potentially related to what the CameraFollow script is doing.

Done some digging and it looks like I have something keeping that script alive as i can’t deactivate it via the checkbox whilst the game is running.

Edit:
Think I’ve found the two culprits in the CameraFollow script

void Start()
    {
        Vector3 Rot = transform.localRotation.eulerAngles;
        RotY = Rot.y;
        RotX = Rot.x;

        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

Is this being in the start function preventing me changing it from a different script?

void LateUpdate()
    {
        CameraUpdater();
    }

    void CameraUpdater()
    {
        Transform target = CameraFollowObject.transform;

        //move towards the game object that is the taget
        float step = CameraMoveSpeed * Time.deltaTime;
        transform.position = Vector3.MoveTowards(transform.position, target.position, step);

    }

Is the fact that I have this late update function on the camera preventing the whole script from being deactivated in the update function of another script?

No, nothing in either of those scripts would prevent the component from being disabled. There must be something else that would set .enabled to true.

The fact that Cursor.visible doesn’t appear to run is very suspicious and makes me think that you have some code elsewhere which is canceling out both of those things. Or let me put this another way: on your “this runs/this doesn’t” comment’s code, if the last line is being run, all four lines are being run, period. It doesn’t skip over lines, that just doesn’t happen. So something else is setting .enabled to true and setting Cursor.visible to false. in the same frame, and likely every frame if you can’t disable the component via a checkbox either.