Search Unity

The need to have a gameobject to start a script .. :/

Discussion in 'Editor & General Support' started by n0mad, Feb 4, 2012.

  1. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Hello,

    I know, this is an old one, and that it is how Unity works ... But I'm starting to hit a big wall in regard of framework optimisation because of this restriction.

    For example :

    - In case of Additive level loading, I am forced to run a script in each level that scans for duplicated system objects and cleans any unnecessary clone (like the "core" gameobject which hosts the MVC controller). It also forces me to graduate my system functions deployment, so that there is no conflict due to these duplications. Huge pain in the ass ...

    - In case of system protection (routines that scans if everything is ok database wise), it forces me to write a flag on a DontDestroyOnLoad object at Application Start which tells that I don't need to run that test at each new level. Kind of overkill ...

    - In some way, it forces to use Additive Level Loading, so that you need to load an empty scene at start, with DontDestroyOnLoad persistant system objects that would deploy all the game views. This is the most annoying part to be honest, as it forces any game testing to start from that empty scene. I can't pick a scene, hit play, and tadam everything is ok. I have to play that empty system scene each time, and create an interface to load any random scene. Overkill once again ... :/

    - It also force to expose those system objects. Even with creating a non MonoBehaviour class inside these, they're still instanciated in a public gameObject, or we have to use static functions, which is not that optimal either.

    If there was a way to launch a script without it needing to be attached to a gameobject, we could save a lot of clunky coding workflows for sure.

    With Unity being used by big AAA studios, I don't understand why any of them had complained about that yet ?
    Flash forced me to use the same empty system scene logic back when I coded games for a very security sensitive business (national lottery). And it felt very awkward, unnatural, and unappropriate for any "serious" framework.

    Long story short, is there any alternate way to load a persistent script without attaching to a gameobject ? Or any plan from Unity to create such capability ?


    edit : Plus I guess it wouldn't be hard to implement at all, like the matter of an hour : just insert a unique, invisible, static and persistent MonoBehaviour at the start of any Application, that could be overriden by the coder.
     
    Last edited: Feb 4, 2012
    astracat111 likes this.
  2. TheCasual

    TheCasual

    Joined:
    Sep 30, 2010
    Posts:
    1,286
    I dunno if its relevant or not to your uses or methods, but static methods can be invoked without being attached through any gameObjects with ease. Creating a new instance of an object through this method might help ..

    sorry, im not to sure honestly.

    PS : Just looking through your site , nice stuff m8.
     
  3. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Yep that's what I'm doing actually, but I still need to create a GameObject in each scene that "triggers" those static deployments.
     
  4. foxter888

    foxter888

    Joined:
    May 3, 2010
    Posts:
    530
    yes the bad thing is the fact that every script that is a monobehavior needs to be atached to a game object in order to run but it doesn't has to be set up in the scene, you could make a empty gameobject at runtime then add the script at runtime to that empty gameobject.
     
  5. TheCasual

    TheCasual

    Joined:
    Sep 30, 2010
    Posts:
    1,286
    ahh right , i see what you mean.
     
  6. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    But you still need a script attached to an already existing gameObject to instantiate that script you're talking about ... :/

    aka : whatever solution is found, there is always the need to have a preloaded gameobject in any scene.
     
  7. TheCasual

    TheCasual

    Joined:
    Sep 30, 2010
    Posts:
    1,286
    I guess thats the magic there .... thats Unitys big trick... the gameObject. Haha.
     
  8. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    more like burdenObject :p
     
  9. foxter888

    foxter888

    Joined:
    May 3, 2010
    Posts:
    530
    keep in mind you could try creating the script as a class and maybe call the update on it or something? it seems that you are having problems having a script on a gameobject. it really doesn't do anything bad being like that it's just a empty game object. maybe try re coding your system to be more manegable?
     
  10. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    The problem is not to have an empty gameobject, it is the whole way of structuring that is forced to us. As I wrote extensively in the OP, the whole need to have an empty scene for management is kind of clunky (as much as the Update solution, which is the same as the first example in the OP). There's no need to recode my system actually, as it works, but I was just asking if there was any plan for proposing an alternate way of loading scripts, which would remove that way of script management.
     
    Last edited: Feb 4, 2012
  11. snortop

    snortop

    Joined:
    Dec 16, 2011
    Posts:
    194
    The reason why big company havent complain about it. Is that it SOO simpel and so good to use.

    I think it's your though wise to each coding problem that is the main problem.

    I think you need (if not already) learn to use OOP language.
    Because it look to me that way. You overthinking it all and still in the old days wise of programming.

    Think class and reuseable object!
     
  12. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Please, people, if you have anything useful to propose other than "you're doing it wrong", I'll kindly ask you not to post.
    I'll repeat : I know how to handle that way of coding, thank you (and I know OOP thank you too, lol). I was just asking for an alternate way.

    Reusability is precisely why I'm hitting a wall : you have to recreate an object at each scene for it be reused (or create it outside of that scene), which is kind of contrary to the base definition of reusability and puts unnecessary additional work to make it persistent.

    Exposing a way to systematically load an overrideable Unity script at Application start without the need to depend on any gameObject would solve that problem.
     
    Last edited: Feb 4, 2012
    Yuri-b likes this.
  13. snortop

    snortop

    Joined:
    Dec 16, 2011
    Posts:
    194
    Visual C#, whit a Graphic engine.. good alternative!
     
  14. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Can we stay professional, and on-topic please.
     
    Last edited: Feb 4, 2012
  15. _Petroz

    _Petroz

    Joined:
    May 13, 2010
    Posts:
    730
    None of the replies you have received are helpful and I can understand your frustration. I think part of the problem is your first post doesn't have a clear question in there, it's a wall of text and it pretty difficult for the reader to determine exactly what you're asking. The more specific context you give the question the less likely people are to help. If you take the time to make you question generic, short, and concise it will be easier for people to reply.

    I interpret your question as this:
    "How can I make singleton objects which work for both 'play in editor' and proper builds?"

    This is how I make singleton classes for my project:

    Code (csharp):
    1.  
    2.     bool isInitialized = false;
    3.     private static MySingleton sInstance;
    4.     public static MySingleton instance()
    5.     {
    6.         if (sInstance == null)
    7.         {
    8.             //NOTE: game object name in heirachy *MUST* be "MySingleton"
    9.             var go = GameObject.Find("MySingleton");           
    10.             if (!go)
    11.             {
    12.                 var prefab = (GameObject)Resources.Load("Singletons/MySingleton");
    13.                 go = (GameObject)GameObject.Instantiate(prefab);
    14.                 go.name = "MySingleton";
    15.             }
    16.            
    17.             sInstance = go.GetComponent<MySingleton>();
    18.             if (!sInstance.isInitialized)
    19.             {
    20.                 sInstance.init();
    21.             }
    22.         }
    23.         return sInstance;
    24.     }
    25.    
    26.     void init()
    27.     {
    28.         DontDestroyOnLoad(this);
    29.         isInitialized = true;
    30.     }
    I store all of my singleton classes in Resources/Singletons
     
  16. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Thank you for your suggestion Petroz. I thought repeating the problem X times would be clear enough :

    Mainly, the title which resumes the problem :

    then examples,

    then a short version :

    then 2 lines later, another resume :

    then, 4 posts later, yet another resume :


    then yet yet another, far more descriptive resume :

    and then a final one :



    _______________________


    Seriously, I've wrote the same explanation 6 times lol :p
    I think the problem is not the lack of concise question, but more that people are just not interested.

    So I'll write it a 7th time, maybe it'll deliver this time :

    The problem I'm trying to expose is not about bypassing the need to attach a script to a gameobject, because in the end, you will always need to trigger any non MonoBehaviour class from a MonoBehaviour script. Singletons, Static classes, etc are not solutions, they are just bypasses. But in the end, the bypasses don't change the need to start everything from a gameObject.

    Also, about wall of texts, I thought there were still some professional coders here, who are used to read walls of texts on other forums (gamedev.net, blogs, enterprise documents, etc). And even if the first post still had blurry zones, there were several posts under it which would go straighter to the point.

    So if spending 40 seconds to read a 31 lines long paragraph is too much to ask, then I should simply stop searching for help here.
    (not against you Petroz, and thank you for your time, really)

    This is another debate, but I come to see that people's attention span on forums are shorter and shorter as years go by. Which is dumb considering the very original nature of discussion forums.

    Anyway ... Thank you all, I've already started a workaround.
     
    asqewfcq2egf likes this.
  17. _Petroz

    _Petroz

    Joined:
    May 13, 2010
    Posts:
    730
    In reality it takes at least few minutes to read and digest it. If 10 people take 3 minutes each to read it that is 30 minutes spent that is not actually helping you. If you took 5 or 10 minutes to re-read it and reduce it to the minimum text to clearly convey your point then you have saved everyone else time. There are heaps of posts on these forums and when your is among 100 unread posts if each took a few minutes to read each one then this would become a full time job :)

    I still don't exactly understand why it is a problem that all code is started from a GameObject. If you need global init code to run before anything else then the singleton design pattern allows for initialization on first use which is just as good.

    I am glad you have found a solution to your problem, I still don't completely grasp what the problem is.
     
  18. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Sheesh ... I've explained why with concrete examples :/
    (I'm already using Singletons, on a sidenote)

    ok, super ultra concrete precise no-need-to-think example :

    1) you have a MVC framework, with mvc persistent classes which are monitoring everything in your whole game.
    2) these classes have to create persistent other classes at application start, and these classes should never be destroyed because of gathered info during the whole game. They are complex, so they cannot rely on PlayerPrefs.

    So here, you have either to :
    a) insert this MVC into a DontDestroyOnLoad gameObject in an empty scene at start, which will AdditiveLoad every level.
    Problem : you can't test any level on the fly. You'll always have to load that first empty scene and deploy the whole game scenario until you reach that level (or create a dev interface to that level, but with complex games, you can understand the burden).

    b) or insert the MVC gameobject into every level. Problem : you couldn't be able to AdditiveLevelLoad because of MVC duplications (and therefore conflicts. Or you have to create a cleanup routine, but good luck with it as MVC is supposed to be the first thing loaded)

    c) The script you posted is another way to go, but it still requires to be called from an existing gameObject (here, let's say a "system" gameObject put in every level), which leads to the same problem as in b). If you want to AdditiveLoad every level in your game, you'd end up having to clean each new "system" gameobject on load.

    ____

    So of course the problem is not impossible to bypass, and there are always solutions. But I can't see the elegance in them, as they all require some unnecessary clunky bypasses.
    Meanwhile, if Unity provided creating a simple unique, overrideable, invisible, systematic MonoBehaviour on Application start, which we could fill with these kinds of persistent stuff, we wouldn't need all those things we're talking about.

    In one word : why making it so complicated when it could be so simple ?
     
    Last edited: Feb 5, 2012
  19. _Petroz

    _Petroz

    Joined:
    May 13, 2010
    Posts:
    730
    So my first answer was to have a singleton which is attached to a prefab inside resources. You can load that prefab by path; which means you do not need any empty scene. It also means that no matter which scene you load if it's "play in editor" or just a normal build, it will always be there and will always be initialized first.
     
    Last edited: Feb 5, 2012
  20. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    But you need a gameobject to load this prefab ... ;-)
    (= the whole "system" scenario in my previous post)
     
  21. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    In every scene, I place a "Level" GameObject to handle everything that isn't tied directly to an object.

    With this object in every scene, and the code posted by Petroz, I don't see what problem you have left. It is similar to having the same MVC GameObject being loaded every scene, except that it will never create duplicates.
     
  22. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Problem, as I said earlier, is that after several Additive Levels, you'll end up with 10 copies of your Level gameobject.

    Nevermind guys, let's bury this topic, I seem not to be understood. Let's move on.
     
  23. _Petroz

    _Petroz

    Joined:
    May 13, 2010
    Posts:
    730
    No you don't, it is loaded as soon as it is accessed. Every gameobject which references it will be able to load it. It is guaranteed to be ready as soon as it is needed.
     
  24. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    No, do not use DontDestroyOnLoad on the Level GameObject. It is created for each level individually. It's sole purpose is to initialize the level and handle level-specific information.

    In your case it would create the MVC GameObject if there was none available, or use the one that is there. It is your exact solution you posted:
    except that it doesn't create duplicates when loading levels.
     
  25. Diviner

    Diviner

    Joined:
    May 8, 2010
    Posts:
    677
    The fact that you see this as a problem means that you're unwilling to follow Unity's Component based philosophy. This is an understandable issue when coming to Unity from different backgrounds, but it's not necessarily a problem, it's just a different way of handling things.

    Instead of giving you how-to examples to avoid what you complain about above, I should give you a more clear explanation on why MonoBehaviour scripts need an existing gameObject present. It might help you understand that what you refer to as a problem is essentially a feature.

    All scripts extending MonoBehaviour inherit the following methods :

    http://unity3d.com/support/documentation/ScriptReference/MonoBehaviour.html

    Note methods such as OnMouseEnter, OnTriggerEnter, OnCollisionEnter, OnControllerColliderHit and so forth. Said functions demand the component system present. They require instant use of GameObject, Collider, Transform and a ton of other components present, constructed and placed in the scene. Without these components, and specifically without the GameObject and Transform Components these functions can't operate.

    The only reason one extends his classes to MonoBehaviour is in order to gain functionality of those methods. Not extending to MonoBehaviour is not a work-around. It's a conscious choice not to use the MonoBehaviour methods. It's something you should do, and something that as you said, you already do.

    Unity does not force you to extend to MonoBehaviour. It gives you the option to do so in order to manipulate objects. For classes that don't need this functionality, you have no reason to do so, and as a matter of fact, it is counter-advised. It leads to redundant code, needless inheritances and resource management problems as the one you described above (DontDestroyOnLoad).

    Your issue is not with the way Unity handles MonoBehaviour scripts. It's with the way Unity handles scene transitions and the fact that all non-static objects are cleaned up between scenes. Testing a level "on the fly" as you say cannot be accomplished in any framework where each scene is treated as a separate application.
     
    Q12x likes this.
  26. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Additive loading levels.
     
  27. _Petroz

    _Petroz

    Joined:
    May 13, 2010
    Posts:
    730
    Right the Object per scene thing doesn't work because of the additive levels.

    My solution is to have no object in any scene, so no duplicates. It is created when it is first accessed and never destroyed and never duplicated.

    For example in my game I have mission objective game objects per scene. All of them depend on the MissionSystem object. They all access it as a singleton and it is created once and only once. This would work if my levels were additive, even though they are not.
     
    Last edited: Feb 5, 2012
  28. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    Oh, silly me :p


    In that case, you do not need the individual Level GameObjects but using Petroz's script, you should still be able to achieve the same effect.

    As he explained before (and again while writing this), it will create the object when it needs to, and use one already placed if it can. Still no duplicates.
     
    Last edited: Feb 5, 2012
  29. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Aaaaaaaaaah, THANK YOU ! :p

    Yes, that's precisely the problem I'm encountering.
    I want to transition all my levels with Additive Loading, for a smoothier feel, may they be menus, scenes, cutscenes, etc.

    So I'm stuck with having to write a "singleton cleaner", contained ... inside itself xD
    (plus all the job of checking if it's the right singleton to clean, in order not to clean the first one)
    edit : or the a) solution (empty scene at start)

    That's why I was proposing Unity to create an OnApplicationStart unique overrideable class, so that there won't be all this cleaning mess to perform.
     
    Last edited: Feb 5, 2012
  30. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732



    ------> which iiiiiiiiiiiiiiiiiiiiiiis .... :p
    *rolling drums*
    ----->
    (or the 3rd example in my very first post, lol)
     
  31. _Petroz

    _Petroz

    Joined:
    May 13, 2010
    Posts:
    730
    I'm pretty sure my solution fits your problem without requiring any cleaning. If you think it is insufficient could you please explain why?
     
  32. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Maybe I didn't catch it well then ?

    Ok my (re-re-rewritten) perception of your solution :
    In order to populate those DontDestroyOnLoad Singletons, you still need to :

    - either trigger them from a gameobject that is pre-put into every level, right ? which leads to cleaning this very pre-put gameObject at each AdditiveLevelLoad.
    (reference to my first post :
    )


    - either trigger them from a gameobject in an empty scene at game start (if you want to skip the cleaning job above), and then load every other levels from here, and here only (if you load levels from elsewhere, you wouldn't have populated the singletons in this scenario).
    (reference to my first post :
    )
     
  33. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    Yes, you are misinterpreting his solution.

    You use it the exact same as any other singleton, except that it creates the object if it isn't there. It doesn't matter where it is called, and doesn't require any special call from any special scene.

    The moment you call:
    Code (csharp):
    1.  
    2. MySingleton.instance ();
    3.  
    It looks for an instance of the MySingleton and if it isn't in the scene, creates it. If it is already there, it uses that instance.

    For example, lets say I want a script to show how many points I have. I would use:

    Code (csharp):
    1.  
    2. function OnGUI () {
    3.  
    4.     GUILayout.Label ("Points: "+MySingleton.instance().points);
    5.  
    6. }
    7.  
    And I don't have to do anything else. I could place this in any additively loaded level and end up with same effect. The creation (or lack thereof) is taken care of by the Singleton.


    EDIT: There is one thing I would change about Petroz's system, and that is to use a C# getter rather than a function. Then you could use MySingleton.Instance.points
     
    Last edited: Feb 5, 2012
  34. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Ok then I get why I couldn't understand your solution : none of my system classes are MonoBehaviour. They're all basic C# classes, and therefore communicate in a non-MonoBehaviour ecosystem.

    That's why I find what you consider "simple and accessable" as an "unnecessary object creation".
    Your solution implies that you call any system function from a gameObject component, which is not my case :)
    To be more precise, I'm populating my system, populating my levels, and then populating my objects. GameObjects are referenced in the system inside static structs (there aren't a lot, so I prefer the static state for accessibility). I thought it was the most logical structuration as in my eyes system never has to be a gameObject component, it has to be in the deepest level and invisible.

    So in the end I'm afraid I couldn't use this solution at all, as I really don't want to mix system framework with the versatile personality of gameObject components. Another reason is I don't want to open such critical routines as in system to every gameObject component. I prefer to keep it "locked". I'll go with the "autocleaning" method I guess.
     
    Last edited: Feb 5, 2012
  35. _Petroz

    _Petroz

    Joined:
    May 13, 2010
    Posts:
    730
    The singleton needn't be a GameObject but that would change the implementation. I only have it that way because I have state exposed to the editor as public variables. If you want just a normal class that is possible too:

    Code (csharp):
    1.         private static MySingleton sInstance;
    2.         public static MySingleton instance()
    3.         {
    4.             if (sInstance == null)
    5.             {
    6.                 sInstance = new MySingleton();
    7.             }
    8.             return sInstance;
    9.         }
    This object will be destroyed when the scene is cleaned up but it should be recreated when it is referenced in the next scene and not duplicated.
     
  36. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    It does not need a GameObject to associate with, all that needs to be changed is for it to create a new instance of itself rather than a GameObject. Here is a simplified version.
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class MySingleton {
    6.  
    7.     private static MySingleton sInstance;
    8.  
    9.     public MySingleton Instance {
    10.         get {
    11.             if (sInstance == null) {
    12.                 sInstance = new MySingleton ();
    13.             }
    14.        
    15.             return sInstance;
    16.         }
    17.     }
    18.    
    19.     MySingleton () {
    20.        
    21.     // Initialize
    22.        
    23.     }
    24.    
    25. }
    26.  
    The way you are using Unity is definitely different than most others. In your solution all the GameObjects are purely visual while all the logic occurs in static scripts?
     
    Last edited: Feb 5, 2012
  37. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    I'm sorry, but this is still requiring to call instance() from a component. Once again the problem is not about creating classes, it's about their parent. Whenever you go up to the parent root of any class, it will always need to be a component, therefore a pre-created gameObject.
    (which sends us back to the whole debate on the last pages)

    Diviner pinpointed the real problem, and I think I have no other choice ;-)
    (sidenote : your Youtube channel is great, Diviner, congrats)
     
    Last edited: Feb 5, 2012
  38. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    That's 50% true :)
    Some specific classes are easier to manage while being components of their own subject (gameobject), while some other are pure logic and framework management so shouldn't be tied to components (especially if persistent, as it would require to keep gameObjects, therefore some unnecessary stuff).

    I could make everything component based of course, but it would expose some critical function to a simple gameObject accessibility. I prefer to keep a logical pattern : versatile objects and classes in destroyable components, critical system framework in a locked and loaded invisible framework.

    Plus, we never know, some day I could want to broaden my fighting framework, so the more I keep things structured, the better it is.

    In the end we come to the debate of "should everything be component based ?", and that's why I made this thread in the first place : I think it should not, there should be a choice.
     
    Last edited: Feb 5, 2012
  39. n0mad

    n0mad

    Joined:
    Jan 27, 2009
    Posts:
    3,732
    Anyway, I'd like to thank you all guys for this discussion, you helped me pinpoint the problem, and therefore the solution.
    Cheers, have a nice day ;-)
     
  40. Glurth

    Glurth

    Joined:
    Dec 29, 2014
    Posts:
    109
    RISE rotting post! RISE from the dead!

    BEHOLD! http://docs.unity3d.com/Manual/RunningEditorCodeOnLaunch.html

    (Been searching for a solution to this myself, for a while. Since this post came up in google, figured I'd update it with this cool attribute I finally found.)

    It will allows code in a class with a static constructor, to execute when unity loads. No gameobjets needed, no scene needed.

    Some other attributes can be used to launch code at game-start(play), and script reloads. e.g http://docs.unity3d.com/ScriptReference/Callbacks.DidReloadScripts.html
     
  41. ajc200x

    ajc200x

    Joined:
    Dec 15, 2015
    Posts:
    3
    Hello Nomad, I've been trying to get, unity, to create an empty game object via script, when i click the play button, without it being attached to anything, it seems like you are having the same issue, so you are not the only one frustrated with this mechanism quirk of unity, why would i need an empty gameobject to attach my script too, to create another empty gameobject ("plane") with components, for example, I've been writing a mesh creator c# script, to create a plane mesh, then adding the mesh component and attach the scripted mesh, and the meshrenderer with my simple,unlit blue _color shader, I dont understand, why i cant execute the script to create the empty game object for me, rather then me using the menu to click empty game object and attaching the game object creation script it does not make sense to me, either, and you are more technically knowledgeable then me, and it has you stummped as well.