Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
2 captures
12 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by dpidev · Nov 17, 2019 at 10:21 PM · eventeventsystemgameobject.findlistener

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?

Comment
Add comment · Show 5
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bonfire-Boy · Nov 18, 2019 at 11:18 AM 0
Share

What do you mean by "break"? Are you saying that the logging at UI line 15 appears but not the logging at line 17?

avatar image dpidev Bonfire-Boy · Nov 18, 2019 at 03:37 PM 0
Share

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!

avatar image Bonfire-Boy Bonfire-Boy · Nov 18, 2019 at 07:25 PM 0
Share

Seems unlikely that your code that you say "works ok" really does.

It shouldn't compile (what is dt at line 22?).

avatar image Bonfire-Boy Bonfire-Boy · Nov 18, 2019 at 07:31 PM 1
Share

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

avatar image dpidev Bonfire-Boy · Nov 18, 2019 at 09:00 PM 0
Share

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!

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

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!

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KaspianR · Nov 19, 2019 at 10:00 AM 1
Share

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!

avatar image
1

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!

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image dpidev · Nov 18, 2019 at 03:40 PM 0
Share

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!

avatar image KaspianR dpidev · Nov 18, 2019 at 04:47 PM 0
Share

@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!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

121 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Assigning events on runtime 0 Answers

How to drag gameobjects (other than ui elements) using the event trigger? 2 Answers

Can't fire a Custom Event on UI Button Touch OnClick 1 Answer

Adding custom BaseEventData to UnityEngine.EventSystems NOT Unity.Events 1 Answer

Where is my OnClick in the button script? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges