Search Unity

Dumb question: why not execute scripts in the order they appear on the inspector?

Discussion in 'General Discussion' started by Not_Sure, May 14, 2021.

Thread Status:
Not open for further replies.
  1. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    I think just about everyone who first faces an order of execution error immediately tries to move the scripts around in the component list, so I’d say the intuitive thing would be to do that, but then have the script execution in the editor override it so that older users don’t have anything new to learn.

    Am I crazy here?
     
  2. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    If you went by order on the gameObject you'd have to hand-check the order on every object. One monster might be attacking funny since, only for that one monster attackScript and moveScript are in the wrong order. Every time you made a new monster you'd have to check the script were in the correct order. If you wanted to swap the order of the attack and move scripts you'd need to change it in every monster prefab (and also check places your your code may create them).

    I also suspect Unity may group scripts by type. One list of every monsterMove script which it works through every frame. Looking through the order in each gameObject each frame would be more awkward.

    The only advantage your idea has is if you wanted scripts to run Move, Attack on some things, but Attack, Move on others. I can't think of any time I'd want that. And even if I did, I could have some other object do it:
    if(type==0) { move(); attack(); } else { attack(); move(); }
    .
     
    Meltdown likes this.
  3. NotaNaN

    NotaNaN

    Joined:
    Dec 14, 2018
    Posts:
    325
    While you are not crazy, there are many downsides to something like this:
    1. Major changes to the engine may be required in order for this new execution order to be guaranteed at runtime for all platforms.

    2. If this was an editor-only feature (because changing the engine for Unity is usually a big Unity no-no), similar to that of children-order not being guaranteed between editor and runtime, this could cause even more problems for newbies.

    3. Even if the Unity Engine supported the feature 100% safely and consistently, it would likely be considered bad practice (for a lot of reasons) and it would only act as a bandaid to Unity's much larger execution-order problem.

    The fact of the matter is that you pretty much should always be using a custom-updater if many per-script execution orders need to be guaranteed within a package, framework, or game. And until Unity decides to move the engine to C# (and ditch the magic Update methods), this will pretty much always be the case.

    So to recap; no, you are not crazy. But no, it's not going to happen.
     
  4. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Never design your code so it's dependant on update execution order.
     
    Joe-Censored likes this.
  5. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    Blanket statements are made to be disproven.
     
    angrypenguin and NotaNaN like this.
  6. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    I do think Unity's official tutorials should emphasize the importance of when to use
    Awake
    and
    Start
    , because that's really the key difference-maker in whether or not you'd get execution order conflicts.

    It really doesn't help that the default auto-generated MonoBehaviour script tells new users to "Use Start for initialization", when it, more often than not, should be
    Awake
    instead. It's just setting up new users to run into this script execution order conflict when they inevitably do something like this...
    Code (CSharp):
    1. public class ScriptA : MonoBehaviour {
    2.   public Rigidbody body; //Assume this is not assigned in the inspector.
    3.  
    4.   void Start() {
    5.     body = GetComponent<Rigidbody>();
    6.   }
    7. }
    8.  
    9. public class ScriptB : MonoBehaviour {
    10.   ScriptA scriptA;
    11.   float scriptAMass;
    12.  
    13.   void Start() {
    14.     scriptA = GetComponent<ScriptA>();
    15.     scriptAMass = scriptA.body.mass;
    16.   }
    17. }
    ...Which has the potential for Unity to call ScriptB's
    Start
    method before ScriptA's, meaning ScriptA's
    body
    reference is null at the time ScriptB tries to do something with it.

    The key things to note about
    Awake
    and
    Start
    however are:
    • Both methods are called once at initialization-time in the script's lifecycle.
    • Awake
      is always called before
      Start
      .
    • All
      Awake
      methods are guaranteed to be called before the first
      Start
      method for every script in the scene.
    The above problem would be fixed by just changing ScriptA to assign it's
    body
    field in
    Awake
    instead of
    Start
    :
    Code (CSharp):
    1. public class ScriptA : MonoBehaviour {
    2.   public Rigidbody body; //Assume this is not assigned in the inspector.
    3.  
    4.   void Awake() {
    5.     body = GetComponent<Rigidbody>();
    6.   }
    7. }
    8.  
    9. public class ScriptB : MonoBehaviour {
    10.   ScriptA scriptA;
    11.   float scriptAMass;
    12.  
    13.   void Start() {
    14.     scriptA = GetComponent<ScriptA>();
    15.     scriptAMass = scriptA.body.mass;
    16.   }
    17. }
    So in general, you should:
    • Use
      Awake
      to initialize a script's own data.
    • Use
      Start
      to initialize data that depends on other scripts.
    But this is really not mentioned anywhere in Unity's official docs or tutorials.
     
    Last edited: May 14, 2021
  7. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    @GliderGuy Yeah, I don’t know why they would ever do it outside of the editor. And also just add it to a new version so it won’t effect prior projects.
     
  8. NotaNaN

    NotaNaN

    Joined:
    Dec 14, 2018
    Posts:
    325
    With that kind of statement the next thing you'll be asking us to do is write equations that magically do not need to adhere to the mathematical order-of-operations. :rolleyes:

    Trust me. Ignoring the necessity of execution-order will only bring pain. It is far better to embrace it as part of your design and ensure key behaviors (or all behaviors) follow a defined execution order.

    I mean, how else would you achieve determinism if Machine A is not guaranteed to process the game's logic in the exact same order as Machine B, C, or D? o_O
     
  9. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    If you write code that do not depend on Unity execution order of monobehaviors then it will never be an issue.

    Its also very tight coupling if two mono behaviours have thst kind of dependency.
     
  10. Komikom

    Komikom

    Joined:
    May 20, 2015
    Posts:
    38
    *Meanwhile Unity's official docs*

    https://docs.unity3d.com/ScriptReference/MonoBehaviour.Awake.html

    ,,...Because of this, you should not rely on one GameObject's Awake being called before or after another (for example, you should not assume that a reference set up by one GameObject's Awake will be usable in another GameObject's Awake). Instead, you should use Awake to set up references between scripts, and use Start, which is called after all Awake calls are finished, to pass any information back and forth...."
     
  11. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    Well, I stand corrected.
    Nice find.
     
    Komikom and NotaNaN like this.
  12. NotaNaN

    NotaNaN

    Joined:
    Dec 14, 2018
    Posts:
    325
    ... Yes?
    In all my posts I am referring about the high-level concept of the necessity of a defined, somewhat static execution order — not Unity's implementation specifically. (However looking back I can understand the confusion when I used the word "behaviours")

    If you create your own updater, yes, you no longer need to worry about it updating relative to other monobehaviours as everything in the updater will update at the updater's given monobehaviour Update().

    I do not believe this is tight coupling. Tight Coupling is where Object A requires Object B in order for it to function.
    Whatever the case, though — assuming we're using Unity's Script Execution Order, Object A and Object B do not need to even know about one another in order to execute in an defined, order manner.
     
  13. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Here we are talking about unity execution order. If your domain relies on it to work properly its fragile and will break and be a headache to maintain.

    Well, if two conponents are dependant of each others execution order they are very much too tightly coupled.
     
  14. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,195
    Having objects be tightly coupled is precisely why the [RequireComponent] attribute exists. Because like it or not you will be tightly coupling some portion of your code in order to use the built-in components (eg rigidbodies).

    https://docs.unity3d.com/ScriptReference/RequireComponent.html

    Plus the mentality that everything should be loosely coupled isn't necessarily the correct one.

    https://softwareengineering.stackexchange.com/questions/405308/coupling-theory-vs-reality
     
    Last edited: May 14, 2021
    Joe-Censored, NotaNaN and ippdev like this.
  15. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    You always have some degree of coupling in a computer software. You should strive to minimize it.

    And you never ever in the case of unity should be dependant on the execution order of other components update.
     
  16. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,195
    If that were true we wouldn't have LateUpdate().
     
    JoNax97 and NotaNaN like this.
  17. NotaNaN

    NotaNaN

    Joined:
    Dec 14, 2018
    Posts:
    325
    I hadn't realized that Unity's Script Execution Order was what you were referring to in your original post. Apologies for the confusion.

    I agree — generally speaking Unity's Script Execution Order should only be used for ordering frameworks / packages / plugins relative to one another. Unity's Script Execution Order is wholly unsuitable for ordering each and every single monobehaviour within a given project.


    That's a dangerously broad statement.
     
  18. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Yeah because unity is known to have the best APIs and coding methodologies.

    Its not robust and it creates weak domains.
    Framework like webforms suffered from the same lifetime/life cycle problems.
     
    Last edited: May 14, 2021
  19. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Its the default statement, there can be valid
    nuances though, but not a whole lot
     
  20. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,195
    Just because you can use enterprise coding methodologies to create games doesn't mean it's efficient to do so.

    In fact just about everything you recommend to those around you comes with some degree of slow down to the overall development process in addition to the performance overhead. For a large scale project it can make sense to take some of these approaches but for everything else they're not a great way to do things.
     
    Last edited: May 14, 2021
  21. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Slow down the process? If you build code that's so fragile so it needs to be run exactly at the right time in your frame life cycle, that will surely slow down development time when requirements change etc. Or a new team member is introduced to the code base etc.

    MonoBehavior api should not be looked at like some god like manual how to make game domain APIs
     
  22. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,195
    We're game developers not enterprise developers. Outside of projects with indefinite lifespans like MMOs if your requirements are changing during the main development of the game you likely did something wrong during the prototyping stages.

    While this may sound great in theory in reality unless you limit yourself to hiring enterprise developers you will be hard pressed to find a game developer that won't struggle with enterprise methodologies.
     
    Last edited: May 15, 2021
    NotaNaN and Lurking-Ninja like this.
  23. NotaNaN

    NotaNaN

    Joined:
    Dec 14, 2018
    Posts:
    325
    Hey, at least the code will not have random bugs from machine to machine depending on whether or not script A randomly decided to run before Script B.
    But yeah sure, let all the scripts update in a random order. :rolleyes:
    1 out of a 100 players should have a fun time playing your game if they get lucky. ;)
     
    Last edited: May 15, 2021
  24. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    What you describe is called waterfall development model, that's not how most well organised teams work. Software development is a agile business, things change, you might need to pivot because of some other game releases which changes things etc
     
  25. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Well internal changes between unity versions could very well change in which order components execute
     
  26. Haaaaaaahhaahahahahahaaa... good joke. :D
    And that's why we have Script Execution Order settings in case we need it.
     
    Last edited by a moderator: May 15, 2021
  27. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,195
    Game development is not software development. Outside of edge cases where content is expected to be added on a constant basis what you describe here is not how this industry behaves. We make them with the expectation that they will have a finite amount of content and for the most part this content is planned ahead of time.
     
    Last edited: May 15, 2021
  28. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    Gonna be honest, did not expect this post to become the clash of the Unity Titans.

    I feel like a kid at thanksgiving listening to adults argue politics.

    No idea what everyone is talking about, but also intrigued by the passion.
     
    JoNax97 and NotaNaN like this.
  29. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Gamasutra used to have post-mortems of games. Some explained how they had extensive late changes since they game wasn't fun, or the client needed a change. Ideally you play-test with the crudest possible thing, only building textures, models, fancy scripts... when you're sure you need them. but that seems to rarely happen. People I knew in the business were all about the Agile model -- make enough to playtest, change plans based on that, make more ... and plan to have at least 2 unexpected random changes.

    I don't think I've ever used script execution order. Sure, it matters for set-up, but Awake/Start handle most of that, or else a "manager". Otherwise, take my Move/Attack example. Whichever order they run in will still give you Move, Attack, Move, Attack, Move, Attack ... alternating. Script order won't change gameplay, just _maybe_ a small visual difference. I feel like it's mostly for 3+ stage initializing in multiple scripts for old-style game designers who prefer letting scripts run on their own.
     
    Lurking-Ninja likes this.
  30. I always wanted to be the hideous but friendly hippie uncle at thanksgivings, but probably I grew up to be a grumpy grandpa instead.

    Yeah, that's the thing, this argument is about a fringe edge-case which almost never happens and when it does it's in a "write it once in the engine lifetime" code.
     
  31. Komikom

    Komikom

    Joined:
    May 20, 2015
    Posts:
    38
    People should really get their terminology straight...

    Maintainable code != Enterprise code
    Optimized code != Maintainable code

    Your code should be maintainable. How you do it is your business.
    Your code should be optimized. How you do it is your business.


    You can optimize your code by efficient architecture.
    You can kill your performance by pushing unnecessary architecture.
    Your code can be well maintained with good architecture
    Your code can be hard to maintain with bad architecture.

    //OT:
    Funny thing how all devs here has the need to flex and push their ideas to others.
    Everyone comes from different background, working on different games with different expectations. Thats fine.

    But don't be toxic jackasses on forums, that is not helpful to anyone.
     
    NotaNaN and MDADigital like this.
  32. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,572
    The reason why people object to your stance because in domain of gamedev the approach you advocate is less maintenable than KISS.

    Why do you think people bother arguing with you to this day?

    Because maintenable code is important and in domain of gamedev what you propose usually ain't it. And ideas you promote, especially when given to newbie, drive development and maintenance costs up. In gamedev. They're often harmful.

    Like Ryiah said:
    That's the issue.

    I honestly don't care what you believe in, what practices you use, what is your hardware, and how much cash you saved on tax returns. You have your own WIP thread, you could sing praises to valve index and dependency injection there all day long. That doesn't concern me.

    But the problem is that you drag practices that are ill suited to problem domain, and give them as advice to people.

    That's the reason for the reaction you receive.
     
    Last edited: May 15, 2021
  33. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    I know you believe that but it's wrong. I believe in KISS too. Our game is modular with a set of reusable components for interacting with VR items and objects. It's very simple creating a new item because lf this. It also out of the box get networked.
     
  34. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    I wonder if the OP "Not_Sure" can say the specific type of scripts they needed to change the order for? I'm wondering if it's a case where both use Start and they didn't know you could also use Awake, or if it's the an actual case where Update A needs to run each frame before Update B (or, which is most common, it's "Just do it this more normal way and what you're worried about isn't even an issue").

    Game-style-wise, I feel like MADdigital is working on a very different type of thing. Ultra-realistic games don't have much give -- they're always ultra-realistic. It's a real niche market, and I think so is VR these days. A version of World of Tanks with the correct chances to throw a tread, lose an arm reloading ... would have 1% of the WoT player base say "finally" and jump on it. They would stop in the middle of matches to talk about how their granddad was also in a tank that suffered these 3 random accidents but lived when the other tank exploded for no reason. The rest would think it was much less fun. A more typical game is a theme, art style, general types of mechanics, and and gladly iterate until it's fun. If play-testers really enjoy trigger-pulling to be saying "bang" into the microphone -- that's how it works now. Back to an ultra-reaslitic game, you can't even change how saying saying "fire" and firing has a random 0.5 to 1 second delay, since that's how it really worked. You'd only change it it you got better historical research.
     
  35. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Its for sure a niche in a already niche market. But you also have a content hungry audience.

    Sure a complex and realstic VR game needs more maintainable domain than a much simpler desktop game. But maintainability always have importance in any domain.
     
    Last edited: May 15, 2021
  36. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    @Owen-Reynolds Oh, I don’t have any issues.

    A script of mine changed its order and caused bugs that took me about 5 minutes to figure out.

    When I went to change it I found myself instinctively changing it in the inspector, although I new it wouldn’t work, then thought to myself “why shouldn’t this work?” And posted this thread.
     
  37. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,998
    Right. But what caused the bug? Was it actually a problem with the execution order? If so, was it merely start-up and using Awake() in one script fixed it? Or was it what we'd say is the _real_ purpose of execution order: you actually needed the 2 script's Update's to run in a certain order?
     
  38. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    I have a movement script for a FPS controller and I have independent scripts for various movement abilities like double jump.

    The double jump has to go before the movement or else it will trigger after the initial jump.

    I also want my movement script to be completely independent of the other scripts so that it’s easy to keep adding stuff to the controller for various games.
     
    NotaNaN likes this.
  39. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,572
    In this scenario you're going against YAGNI principle (You ain't gonna need it) and are trying to plan ahead for something that might not happen in the future. Meaning you think you might need to extend the script (which is not necessarily true) and you think you might want to reuse it in the future (also not necessarily true). You're also trying to isolate it completely, which is not necessary.

    The simple way to get it working is to make a monolithic class that handles player movement and control double jump from there. This will not be "easily extensible" with modules and subclasses, but you'll be able to hack it to suit your needs later and it will be all in one place and likely easy to understand.

    If you want to make it "extensible" and keep every mode independentn from each other, you'd need to utilize Decorator pattern ( https://en.wikipedia.org/wiki/Decorator_pattern ) and basically controll all movement from an equivalent of state machine written in C#. Meaning the player woudl be unable to move, and would forward update() calls to the currently active decorator. But this will take longer to write, will produce more code, and the movement logic will be split across multiple classes or multiple files.

    I would recommend the simple way to do it....

    P.S. Reminds me of Monolithic vs Microkernel debate...
     
    NotaNaN, Not_Sure and stain2319 like this.
  40. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    I would make that with a single monoB, than add the abilities as strategies onto that monoB.
     
  41. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,195
    No. You may want to believe you're developing a game on their scale and maybe that's your end goal but what you have now is nowhere near the same scale as large studios.

    Large studios take four years to ship games because they have scope that even with hundreds of devs needs years to be accomplished. Meanwhile you're taking years not because you legitimately have the scope and content to do it but because you're part time developers working on a passion project.

    Plus large studios have accomplished something in that four years that you're nowhere near accomplishing. A game that is both polished and successful. In fact we could strip off one of those two and you would still have failed the comparison.

    What you have built would be at best a late stage prototype to the studio.

    And we have said it hundreds of times. Game development is a completely different beast. Just because you can force a square peg into a round hole with sufficient effort doesn't mean the square peg belongs in that round hole.

    Enterprise development has all of that because it needs to be in existence for a very long period of time. Just look at the companies out there still running COBOL. A software platform needs to be capable of running for decades and the techniques used there were developed specifically for that requirement.

    Once again though outside of edge cases games are not intended to have a lifespan beyond a few years and most of them are not intended to be actively developed past a few months of post-release patches.
     
    Last edited: May 16, 2021
    NotaNaN and neginfinity like this.
  42. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,195
    You need a master control script. This script will be responsible for telling the other scripts when they are allowed to perform their tasks as well as remembering which script represents the current state of the character.
     
  43. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Plain wrong. But let's agree to disagree and move back to subject

    This can be solved many ways.

    For example like I said above with ability strategies. The main monob executes these strategies when it deem fit.

    https://en.m.wikipedia.org/wiki/Strategy_pattern

    You can also solve it with pub sub, when main monob mutates you publish a event. Subscribers update their state.

    https://en.m.wikipedia.org/wiki/Publish–subscribe_pattern
     
    Last edited: May 16, 2021
  44. stain2319

    stain2319

    Joined:
    Mar 2, 2020
    Posts:
    417
    This post... Yes.

    I've been making a more serious effort to learn Unity for the past few months and this is NEVER mentioned!
     
  45. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    It’s a pretty common gotcha that a lot of people run into.
     
  46. stain2319

    stain2319

    Joined:
    Mar 2, 2020
    Posts:
    417
    It really seems like Awake() should be part of the default template for scripts the way update is. I think it would be helpful for newbies (who are probably most of the people who are still using the default)
     
  47. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,572
    Here's a good diagram.
    https://docs.unity3d.com/Manual/ExecutionOrder.html
    upload_2021-5-16_19-25-11.png
    One of the most useful pieces of information in unity docs, pretty much.
     
    angrypenguin and NotaNaN like this.
  48. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    Awake should have been the constructor and with proper constructor injection possibility.
     
  49. Komikom

    Komikom

    Joined:
    May 20, 2015
    Posts:
    38
    Well, that would most likely not work.

    Since your code will never be fully responsible for creating instance of MonoBehaviour, constructors should not be used.
    Plus there would be pretty much no way to pass parameters to the constructor, beacause MonoBehaviours are created by Instantiating gameobject, adding components to gameobjects or are just handled by Scene when it loads. That is why using ,,native" constructors is not really a good idea. It would be just ,,sugarcoating the code" for no reason.

    Awake() can be used ,,as constructor", since it is the first thing that gets called. I don't see any problem with it.
     
  50. MDADigital

    MDADigital

    Joined:
    Apr 18, 2020
    Posts:
    2,198
    You misunderstand me. They should have designed it so that the constructor was the awake. And that you could inject dependencies properly.

    This would be more C# like and you could use readonly keyword for all members. More robust code over all
     
Thread Status:
Not open for further replies.