- Home /
Update function not being called/freezing.
In my game when you get within a certain radius of an object an interaction icon appears. That all works fine except for the interaction. I'm going with a hold down blank button to interact sort of thing. In my world some of the object work I can hold down the interaction button and the script runs perfectly fine, but some are sort of frozen. Ill go up to them and they'll be stuck in the middle and wont accept new input and then at random times for a few seconds they will start working again and allow interaction and then they freeze up again. I added a debug.log to their update function and for whatever reason it seems the update function is not running even though others work perfectly fine and I have confirmed they are on an active gameobject and the script is active and there are no errors in the console. Here is the code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Serialization;
using UnityEngine.UI;
//A class for making the interact hold circles that appear in the world
public class holdButtonInteraction : MonoBehaviour
{
[Serializable]
public class ButtonClickedEvent : UnityEvent { }
[FormerlySerializedAs("onClosed")]
[SerializeField]
private ButtonClickedEvent m_OnClick = new ButtonClickedEvent();
[Tooltip("The key that we should listen for.")]
public KeyCode keyToListenFor;
[Tooltip("The time you should be required to hold down the key for. [SECONDS]")]
public float holdTime;
[Tooltip("The image who's fill should be adjusted")]
public Image iRenderer = null;
//A float to keep track of how long you have held the button/how much to fill the image
public float time;
// Start is called before the first frame update
void Start()
{
//Make sure the time is reset
time = 0;
//Make sure the image is valid, if not set it equal to the image attached to this gameobject
if (!iRenderer) { iRenderer = GetComponent<Image>(); }
}
// Update is called once per frame
void Update()
{
//Make sure Irenderer is not null (If there is no image object attached to the gameobject)
if (iRenderer)
{
//Update the fill on the image
Debug.Log("Fill adjusted!"); //Debug.Log that is not being called
iRenderer.fillAmount = time;
}
else
{
//Warn in the console
Debug.LogWarning("No image component attached to GameObject or iRenderer component is set to an inccorect value.");
}
//Check if we have pressed down the key
if (Input.GetKey(keyToListenFor))
{
//When we are pressing the key increase the value of time
//Ensure we do not go over 1
if (time < 1)
{
//Increment the time by 1 / holdtime each frame use time.deltatime to find out how much to increment by
time += 1 / holdTime * Time.deltaTime;
}
}
else
{
//Decrement the time var when not pressed
if (time > 0)
{ time -= 0.1f / holdTime * Time.deltaTime * 3; }
}
//Check if we have met the time requirement and if so reset the time and invoke the event
if (time >= 1)
{
time = 0;
m_OnClick.Invoke();
}
}
}
BTW: I'm on Unity 2019.4.1f1 and am upgrading to 2019.4.4f1 to see if that changes anything. Also, I have another monobehaviour on the parent object of said script and when one freezes they both do.
Answer by Bunny83 · Jul 15, 2020 at 11:43 PM
There are several things not clear, at least to me. You said you can interact with the objects when you are within a certain radius. However nothing in this script takes care of any distances. So we would assume that there's another script that is enabling / disabling your "holdButtonInteraction" script on the various instances? We don't know when and how that might happen but it of course has a huge effect on what this script does. If you disable the script Update won't be called anymore and therefore the fillAmount of your image would of course stay where it was when you disabled the script. If you don't disable the script I don't really get how you distance check should work.
Another thing I'd like to point out is when your time reaches the value of 1 you set time back to 0. We don't know what actually happens in your callback. However if the object is still there it would start counting up again.
Another possible issue is your automatic decrement. You will always undershoot the value 0 and end up with a slightly negative value. I'm not sure if the Image fillAmount has any issues with negative numbers but I would generally avoid it.
If you actually disable / deactivate the objects when you are too far away I would recommend to keep them active and enabled all the time and just set a state that the script can check.
ps: You really should reduce your amount of comments ^^. This is widely received as bad commenting style. Stating the obvious is counter productive and might even lead to wrong comments in the long run. Wrong comments are much worse than no comments. Comments that just repeat everything that the line of code does it pointless and just makes it harder to read. I would recommend to have a look at Comment (wikipedia)
Thanks for the tips on comments, I will keep that in $$anonymous$$d and give the Wikipedia page a read. There is an external object that activates/deactivates the game object this script is on, I have confirmed in the inspector that the script is still active when it freezes. I was thinking of switching to a != null and will try that when I get back. Interesting point about the image renderer ill make sure to cap that. ill also try just using a bool to set active or not ins$$anonymous$$d of changing the active status of the game object. thanks for the tips, ill get back to you!
Thanks for the help, I implemented the changes, using != null, toggling via just a if(bool) {return;} instead of enabling/disabling the gameobejct, making sure the image component always ends on zero, and cutting down on my comments ;) and now everything is working super smoothly!!! Thanks a bunch!
Answer by UnityedWeStand · Jul 15, 2020 at 10:50 PM
Try switching out if (iRenderer)
and any similar instances with an explicit comparison with null like if (iRenderer != null)
.
While I also prefer the explicit null check, it doesn't make any difference since every UnityEngine.Object has an implicit boolean conversion operator. So this doesn't change anything ^^.