Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 saldavonschwartz · Oct 29, 2014 at 07:17 AM · scriptableobjectmonobehaviourcallbackmessage

calling Unity messages without attaching script to GameObject

My empirical tests seem to imply this is not possible. But just in case, I figured I'd ask:

The Unity documentation for MonoBehaviour exposes several "messages". They call them messages anyway. As fas as I can tell (I'm on C#) they are really neither delegates nor events nor overrides, but rather, arbitrary agreed methods which if you implement in a MonoBehaviour, the runtime knows can be called probably thru reflection.

So for instance, I'm trying to create a wrapper network services class around Unity's Netowrk class. And since my class needs to be available between scenes and there is only ever going to be one state, I wanted to go for either just class methods or a singleton.

My first test was with static classes and concrete classes. And my findings where:

  1. You cannot create static classes derived from neither MonoBehaviour nor ScriptableObject.

  2. You can create concrete classes derived from these, but the messages need to be instance methods; they cannot be class methods. So for instance this wouldn't work:

    public class NetworkServices : MonoBehaviour {

    public static void Init() { Debug.Log("Init"); Debug.Log(Network.InitializeServer(2, 2500, !Network.HavePublicAddress())); }

    private static void OnServerInitialized() { Debug.Log("server initialized"); }

    }

But this would:

  public class NetworkServices : MonoBehaviour {
 
   public static void Init() {
     Debug.Log("Init");
     Debug.Log(Network.InitializeServer(2, 2500, !Network.HavePublicAddress()));
   }
 
   private void OnServerInitialized() {
     Debug.Log("server initialized");
   }
 
 }

Which seems to confirm that the 'message' methods need to be instance methods. So I need an instance. Ok. Now, if I had a MonoBehaviour attached to a game object, the above code (second example) would work, because attaching the Script to a GameObject implies instantiating it. But the truth is that I don't need to create instances since I need to always access the same one. And neither do I want to go about attaching one of these scripts to some object on every scene to have it instantiate. So I tried the following:

 public class NetworkServices : ScriptableObject {
 
   private static NetworkServices _SharedInstance;
 
   public static void Init() {
     Debug.Log("Init");
     if (_SharedInstance == null) {
       Debug.Log("creating instance");
       _SharedInstance = CreateInstance<NetworkServices>();
     }
 
     Debug.Log(Network.InitializeServer(2, 2500, !Network.HavePublicAddress()));
   }
 
   private void OnServerInitialized() {
     Debug.Log("server initialized");
   }
 
 }

Which on the outside (public API) would look like simply class methods, but in reality is creating an instance (just because the message callback needs to be an instance method). So it's kind of using a hidden singleton. But this does not work. I used ScriptableObject because in theory it allows me to create instances not attached to a GameObject. But OnServerInitialized is never called. However, here's a hack that does sort of work:

In theory, you cannot attach a ScriptableObject to a GameObject. Also, in theory, OnServerInitialized is a message of MonoBehaviour and not of ScriptableObject; ScriptableObject inherits from Object and not from MonoBehaviour. But if Ido the following:

  1. change the base class in the above script to MonoBehaviour

  2. Add the script to a GameObject in the scene.

  3. change the base class back to ScriptableObject

I end up with a ScriptableObject attached to a GameObject and the the message gets called.

So from the above it seems that the requirements for the Unity messages to trigger are:

  1. They need to be instance methods.

  2. There needs to be an instance attached to a GameObject

  3. COROLLARY OF SORTS: Actually the messages are not exclusive to MonoBehaviour

My 2 questions are:

  1. Are the above requirements / facts indeed true?

  2. Is there a way around requirement 2? Basically I want to get the networking messages / callbacks but I don't want to attach a script to an object on each scene just to access the singleton / class.

Comment
Add comment
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

1 Reply

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

Answer by GameVortex · Oct 29, 2014 at 07:47 AM

  1. The requirements are true. Messages are only sent to MonoBehaviours attached to GameObjects.

  2. Why not generating the gameobject at runtime and have it set to not destroy on load? Then you will not have to add it to every scene and it will persist during your entire game.

Example:

 public class NetworkServices : MonoBehaviour
 {
     private static NetworkServices instance;
     public static NetworkServices Instance
     {
         get
         {
             if (!instance)
             {
                 instance = new GameObject("NetworkServices").AddComponent<NetworkServices>();
                 DontDestroyOnLoad(instance.gameObject);
             }
             return instance;
         }
     }
 }

It is then a singleton and it supports messages.

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 saldavonschwartz · Oct 29, 2014 at 07:51 AM 0
Share

I guess it is an option yes. And what about the fact that I was still able to get a ScriptableObject attached to a GameObject and receiving messages?

avatar image GameVortex · Oct 29, 2014 at 08:04 AM 1
Share

Well, messages are called through reflection, and because the Object was still attached to the GameObject I guess it was still able to find the function to call it. It does not change the fact that messages can only be sent to objects attached to a GameObject and having the ScriptableObject attached to the GameObject is not really a viable solution in the long term and will most likely lead to unwanted behavior at some point.

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

27 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

Related Questions

How do I detect that MonoBehaviour is modified in the Editor? 2 Answers

ScriptableObject stored in MonoBehaviour lost on quit 1 Answer

Which Scriptableobject's Callback should I use to be updated when the name of a asset file of a SO change? 1 Answer

Circular Dependency Issue 0 Answers

Unet CCU limit hit callback 0 Answers


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