- Home /
GameObject.Find breaks code with UnityEvent
I have set up a listener that fires UnityEvent but when function reaches GameObject.Find statement it just breaks the code without any error or warning, just stops there and game is going on.
NetworkingManager.OnMessageRecieved (called when message from server recieved) -> MatchModel.ServerReportResultUpdate (Invokes an UnityEvent) -> UI.OnResultChanged (function works until it reaches GameObject.Find statement).
NetworkingManager:
using UnityEngine;
using System.Net;
using System;
namespace Scripts.Networking
{
public class NetworkingManager
{
private static NetworkingManager instance;
public static NetworkingManager Instance
{
get
{
if (instance == null)
{
instance = new NetworkingManager();
}
return instance;
}
}
// ---------- GETTING MESSAGES FROM THE SERVER ------------- //
private void OnMessageRecieved(object sender, MessageReceivedEventArgs e)
{
//// Data dt; ///
MatchModel.currentMatch.ServerReportResultUpdate(dt);
}
}
}
MatchModel:
using Scripts.Networking;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace Scripts.Models
{
public class ResultChangeEvent : UnityEvent<Data> { };
public class MatchModel
{
public ResultChangeEvent OnResultChange;
public static MatchModel currentMatch;
public MatchModel(ushort id)
{
ID = id;
OnResultChange = new ResultChangeEvent();
}
public void ServerReportResultUpdate(Data dt)
{
OnResultChange.Invoke(dt);
}
}
}
UI:
using Scripts.Models;
using Scripts.Networking;
using UnityEngine;
using UnityEngine.UI;
public class UI : MonoBehaviour
{
public void AddListeners()
{
MatchModel.currentMatch.OnResultChange.AddListener(OnResultChanged);
}
private void OnResultChanged(Data dt)
{
Debug.Log(" OK ");
Text report = GameObject.Find("TextReport").GetComponent<Text>();
Debug.Log(" BREAKS ABOVE");
report.text = " dt: " + dt.x + " : " + dt.y;
}
}
EDIT:
If I change UI code to this it works ok, but it's some wonky workaround:
using Scripts.Models;
using Scripts.Networking;
using UnityEngine;
using UnityEngine.UI;
public class UI : MonoBehaviour
{
public void AddListeners()
{
MatchModel.currentMatch.OnResultChange.AddListener(OnResultChanged);
}
bool flag = false;
private void Update()
{
if (flag)
{
flag = false;
Debug.Log(" OK ");
Text report = GameObject.Find("TextReport").GetComponent<Text>();
Debug.Log(" OK ");
report.text = " dt: " + dt.x + " : " + dt.y;
}
}
private void OnResultChanged(Data dt)
{
flag = true;
}
}
Any clues?
What do you mean by "break"? Are you saying that the logging at UI line 15 appears but not the logging at line 17?
That's right, log at UI line 15 appears, log at UI line 17 does not, it breaks function at line 16 doing nothing. I've made some workaround but it's a bit messy if I had to make all messages handlers like this, please take a look at my edited post. Thanks!
Seems unlikely that your code that you say "works ok" really does.
It shouldn't compile (what is dt
at line 22?).
Are there no errors in the log?
For debugging you should split the line your Find call is in, into two- one to find the object and then (after a null check) one to get its Text component. That way 1) you can add logging to verify what's been found, and 2) if it's failing, it will now do more usefully.
Is your Network manager invoking the callback on the main thread? If not then that would explain why your workaround works - it moves the UnityEngine stuff into the main thread where it should be. Alternatives to using your flag solution in every case would include 1) adding something to the network manager that makes it send the messages on the main thread 2) creating another object to perform the task of receiving these messages and passing them on on the main thread
I've shortened the code, there may be some issues when getting it directly but there is no errors.
You are right, Network$$anonymous$$anager does not invoke callbacks on main thread, and this was the issue. Thanks!
Answer by dpidev · Nov 18, 2019 at 08:53 PM
So the problem was as I assumed a threading issue. Several functions from UnityEngine namespace needs to be executed on main thread - server messages are handled on other thread. To fix this issue and run these functions on main thread I'm using solution below. It's way cleaner than flags and update function on my first try.
https://github.com/PimDeWitte/UnityMainThreadDispatcher
@KaspianR @Bonfire-Boy Thanks!
Oh, I'm glad you found a solution! I think the majority of Unity's built-in functions are limited to the main thread although there are some workarounds that have worked for me in the past so if you worry about performance it might be worth doing some more testing. Regardless, thank you for posting a GitHub link and posting such a clear answer to possibly help someone else in the future. Good luck!
Answer by KaspianR · Nov 18, 2019 at 12:09 PM
I honestly can't tell you why this is happening but what I can do is hopefully give you a few options to not fix but avoid the issue by not using GameObject.Find().
Use GameObject.FindGameObjectWithTag("") instead and just give your TextReport object a unique tag. You will get an array of objects but as long as you tag i unique you can just access the first object in the list with a standard [0] at the end.
Use a variable that stores the Text object. Of the object exist from start and is the same every time you can make a
Text
variable that shows in the inspector and just drag the object in to that slot or if it gets spawned in at runtime just set the variable in the spawn script. This is the by far best solution!
GameObject.Find() is very convenient but can, especially in larger projects, be very slow and resource intensive so trying to avoid it will only save you the hassle of changing it later when your project is huge and you can't keep a stable framerate.
Hope this helps you and good luck with the rest of you project!
Thanks for the tips! I'm aware of these issues, it's just temporal function before making futher changes. I've also tried using GameObject.FindGameObjectWithTag(""), but it just breaks like GameObject.Find("") as well. It must be some Unity threading bug. Thank you!
@dpidev Oh it does?! Then that's really, really weird! Would you $$anonymous$$d sharing a github link to your project so that I can have a look at that because if we can't figure it out you might be better of putting this on the bug tracker!