Search Unity

Unity 5 Beta Insights

Discussion in 'Unity 5 Pre-order Beta' started by rwetzold, May 11, 2014.

  1. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,625
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,603
    If you followed the basic optimization guidelines from the Unity documentations (added with 3.0 or so), then you will already have the code caching components anyway, as it was one of the top 3 things to do if you ever intend to touch mobile with your game or script.

    As nice as the convenience accessors look, their impact on performance is one to be feared (its the second worst performance killer after Unity GUI considering purely code related things), as it can not only drown mobile games, you can even cause desktop / web builds to become very slugish.

    Also its not just a matter of pure cpu here but of a memory hits too as every access to something that in reality contains a struct (transform position / rotation) yields a copy operation, not just an access.

    I personally could imagine that the WebGL targeting might be involved here too as its performance characteristics are not comparable to the native code mono execution engines on all other platforms.
    Also there is the problem that various legacy systems have these accessors, systems I doubt will still exist in Unity 5 for optimization and WebGL / new platforms reasons (legacy particles, potentially legacy animation, ...)

    Also one thing often forgotten is, that you are not forced to move a project to Unity 5, its up to you.
    I personally wouldn't move a project mid production to Unity 5 unless its required to go there or the benefits seriously outscaling the work effort to get there. That is at least not without doing indepth tests on performance and behavior (with the new PhysX version, removed Beast, SpeedTree and a few other things, there are tons of situation where the behavior could be different enough to cause a lot of work to resolve it)
     
  3. squared55

    squared55

    Joined:
    Aug 28, 2012
    Posts:
    1,819
    Sure, I already do. I just like that my Start/Awake functions are nice and short, easy to read and understand, and very easy to add stuff too.


    The fact that that needs to be said isn't exactly a point in Unity's favor. :) Everything in U5 looks great. Except this.
     
  4. Per

    Per

    Joined:
    Jun 25, 2009
    Posts:
    456
    This I was not aware of, but it adds more misgivings about the decision. More verbose, non discoverable and now slower too. It's not exactly selling it.
     
  5. LukaKotar

    LukaKotar

    Joined:
    Sep 25, 2011
    Posts:
    377
    Thanks for the info, I didn't know that. I checked the reference, 'transform', 'collider' and 'rigidbody' all appear to be the property of RaycastHit.
     
  6. Neeko

    Neeko

    Joined:
    Mar 9, 2012
    Posts:
    24
    Forgive me if this has been linked already, but if losing the properties is that big of an issue to you, it's extremely easy to fix. Just implement https://github.com/nickgravelyn/UnityToolbag/tree/master/CacheBehaviour or a similar solution. Performant, and the API stays the same.

    I'm assuming that gameObject.rigidbody doesn't call GetComponent under the hood? It's only Component that does?

    Edit: Read the thread again, so it looks like that gameObject uses GetComponent as well. This is a bit tricky for me then since I follow a MVC style architecture for my code; I pass around a gameObject reference and do the majority (if not all) of my game logic in Command classes, outside of the MonoBehaviour views.
     
    Last edited: May 12, 2014
  7. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,606
    More verbose, why is that bad?

    Non-discoverable? I'd say the opposite is true. With the old system, you start typing, and your IDE will suggest options, some of which may be component accessors, some other things, and some components will not show up, because they don't have accessors. With the new system, you type "GetComponent<" and the IDE auto complete will suggest exactly what you want: A list of all components you can get. If that isn't more discoverable, then I don't know what.

    Now slower too? Barely so, The biggest overhead is still the call from mono into native. I was just writing this to point out the overall performance implications and that this is not cached internally. Likely, if performance was not an issue with the old accessors, it won't be now.

    Plus, as i pointed out, one of the main reasons for doing this is technical - as it allows better stripping, ie, smaller distribution size for your projects.
     
  8. srogee

    srogee

    Joined:
    Mar 5, 2014
    Posts:
    1
    I think it's fine they're doing this, as it means less bloat when I'm looking through member variables and functions with the suggestion box. However, I don't really understand why they decided to do this now.
     
  9. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,625
    Yes, RigidBody is a component attached to GameObject. So in this case Yes, it does GetComponent<RigidBody>() under the hood when you do gameObject.rigidbody
     
  10. Swearsoft

    Swearsoft

    Joined:
    Mar 19, 2009
    Posts:
    1,621
    I don't know why people are confused or have such a tough time getting this. It's really simple.

    Previously (now) you had shorcuts for various components.

    You never have to access one component through another, so doing something like gameObject.collider.renderer whatever is not useful, it's possible, but it has no actual use. You shouldn't be doing this in the first place, because you aren't doing anything useful, you are just abusing the possibilities for no benefit.

    The only difference now is that instead of a bunch of random shortcuts that actually confuse new users (why can't they find that other script they made, when rigidbody is just a word away?), you will have to say GetComponent.

    This should be trivial to fix in scripts automatically, since it's basically just a replace. DOT isn't affected, shortcuts to components are.

    Edit: it is possible that people confuse the stacking of scripts in the editor as some kind of order, which is why they would assume that you should anything more than rigidbody, instead of gameObject.render.collider.rigidbody. This is the only reasonable explanation I can imagine for this fundamental misunderstanding - if it actually exists.

    So essentially someone did it this way it worked, didn't question it and no he thinks he has to go through all components to reach the one he wants to access.
     
    Last edited: May 12, 2014
  11. squared55

    squared55

    Joined:
    Aug 28, 2012
    Posts:
    1,819
    Well, considering that most programmers use "++" and never use "+= 1", or use "!" instead of " == false"...

    But if there's no speed increase (and, in fact a loss in performance), then the only thing is smaller build sizes - how small are we talking about here? And, personally, I'd take a small performance boost over a small decrease in build size. It really feels as if I'll be writing more and getting less.
     
    Last edited: May 12, 2014
  12. Per

    Per

    Joined:
    Jun 25, 2009
    Posts:
    456
    Verbosity is not the same thing as clarity.

    That's great to hear it's been massively improved, because as you know that's not what happens with Monodevelop and 4.x with the existing GetComponent (or any generic), instead you get nothing and if you start typing the options are completely non contextual.

    The point was just that despite the advantages it doesn't sell the need for change well to hear that it's slower (even minutely). Optimization is a hot topic.
     
  13. kat0r

    kat0r

    Joined:
    Sep 20, 2012
    Posts:
    19
    Will .transform in Unity5 finally be as fast as caching it yourself?
     
  14. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    People ask this constantly but Unity never answers, so I'll ask again: Why can't Unity implement the caching on the .NET side itself? Especially if you're going to leave "transform" in there as a shortcut, it seems really dumb to not cache it. I know the official response is "Well, duh, all of our users should all be constantly searching the forums for the obscure occasional posts filled with misinformation about how GetComponent works where occasionally a Unity dev says that everyone should always be caching everything in Start()!" But... I don't really think that's a good way to do it. If Unity just cached the transform themselves then it magically fixes every asset on the asset store and all users' code without anyone having to scour these forums for shaky advice.
     
  15. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    282
    For what it's worth, I find it silly that there are performance concerns with something like GetComponent<>() in the first place. Something as basic and core to using an engine as getting a component should be fast and reliable, with any and all optimizations such as reference caching being done in the background where we don't have to care about it, maintain it or debug it.
     
  16. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,606
    I'd argue that it adds clarity in this case, though. We've often seen newbies struggle to understand the implications of .rigidbody, and to understand the difference between lowercase "rigidbody" and uppercase "Rigidbody". That, and the inconsistency of having some components have accessors and others not.

    Sorry, I just checked and you are right on this one. I overestimated MonoDevelop's capabilities (personally I tend to use dumb text editors over IDEs most of the time). Not sure if VisualStudio handles it better.
     
  17. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,606
    The difference is, that when you cache components in your code, you have the knowledge of when that cached information changes (because you remove or replace components on your GameObject). We don't have that knowlegde, so in order for the functions to stay functioning correct, we'd have to build logic to go into all MonoBehaviours and invalidate all these caches whenever you add or remove these components, which as a net result may not end up being any better.
     
  18. techmage

    techmage

    Joined:
    Oct 31, 2009
    Posts:
    2,068
    I've still not seen any mention of anything concerning mono upgrades or garbage collection issues for Unity5. Kind of makes me worry.
     
  19. rwetzold

    rwetzold

    Joined:
    Oct 10, 2013
    Posts:
    228
    VS indeed does a great job at code completion for GetComponent<> :)
     
  20. BIG-BUG

    BIG-BUG

    Joined:
    Mar 29, 2009
    Posts:
    456
    I don't see a big problem with those removed shortcuts. Today there are already many cases where you have to use GetComponent for access - be it custom scripts or a standard component without a shortcut. So at least in the future you don't have to wonder why component A is exposed via a shortcut but component B is not.

    Also if I have to use GetComponent I tend to make a private object variable anyway - not for the caching but for easy access within the script. So no need for engine caching here.
     
  21. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,140
    Huh? Having a consistent API has nothing to do with scripting, and it's always preferable over having an inconsistent API.

    Because it's for Unity 5.0, which means it's a good opportunity to make changes like this. And better now than Unity 6.0.

    --Eric
     
  22. Deleted User

    Deleted User

    Guest

    Well I have to admit this doesn't make much sense to me, the whole API is designed around Unity's toolsets and you code a subset calling various functions / methods from other pre-made classes. If you don't like it, then consider building your own engine. As another said on page 3, all they are doing is removing some fluffy short cuts.

    IMO they should deprecate much more and focus on core structure to improve the whole experience, not keep masses of legacy components and shortcuts causing hindrance. You need to clean out the closet once in a while.. It will ultimately provide a better experience for all of us, Unity included.
     
    Last edited by a moderator: May 12, 2014
    Ryiah likes this.
  23. Sparta5_6

    Sparta5_6

    Joined:
    Apr 25, 2014
    Posts:
    2
    What is better Unity 4 or Unity 5? What is different?
     
  24. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,140
    Clearly Unity 4 is better, since Unity 5 is newer and will have some new features and some changes and stuff, and nobody likes that.

    --Eric
     
  25. squared55

    squared55

    Joined:
    Aug 28, 2012
    Posts:
    1,819
    Everyone scripts differently. Therefore, it's not consistent. I don't see why Unity should care how I script. I give it an input, and it gives an expected output. Unless the support forum is incredibly bogged down by confusion over periods?
     
  26. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    282
    The compiler should just replace x.rigidbody with x.GetComponent<Rigidbody>() in a prepass. That solves the stripping down problem.

    Short-handedness is a good thing.
     
  27. minionnz

    minionnz

    Joined:
    Jan 29, 2013
    Posts:
    391
    Because the entire user base will benefit from these changes with smaller packages sizes etc. I don't think it's a case of them saying "You're scripting it wrong!", but instead "We've added some optimisations to Unity and removed some unnecessary properties that were causing issues for us. This is a breaking change, you will need to use the XYZ methods in the future"
     
  28. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,140
    That really doesn't logically follow even a little bit. The scripting API should be consistent, which currently it is not. This change makes it consistent, regardless of how you script.

    --Eric
     
  29. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    But if I understand correctly, the transform is just a pointer to an object that is passed across the native code boundary. You can't add or remove a transform, and you can't change what it's pointing to. I can't think of any possible situation where a cached transform would be invalidated. The only way to destroy one is to destroy the game object itself which would also remove the cache.
     
  30. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    I feel like he answered this. They're not changing it because they care how you script. They're removing it because it will decrease the size of builds and allow them to make their internal MonoBehaviour code more modular.
     
  31. Nelson LaQuet

    Nelson LaQuet

    Joined:
    Oct 1, 2013
    Posts:
    6
    This makes no sense. Not only is this syntax impossible (C# generics do not support variable length generic parameter lists), it doesn't solve anything. Navigating from
    GameObject -> Component1 -> Component2 -> Component3

    Is the same thing as going from
    GameObject -> Component3

    In fact, the GetComponent method on MonoBehavior itself is simply a wrapper over GameObject's GetComponent method anyway. In effect, the first example is actually this (remember that Mono Behaviors are components):
    MonoBehavior -> GameObject -> Component1 -> GameObject -> Component2 -> GameObject -> Component3

    You're just calling back into the *same* game object on every navigation.

    I think the question was about caching the Transform component as a local field (preferably a protected readonly field on the Component class, since I can't remember if Mono's JIT inlines simple properties). Is it even possible to remove a transform from a game object? That should really never be the case. If it isn't possible to remove, or add, a Transform component to a game object, then caching the reference in a protected readonly field is completely viable. If it *is* possible to remove a transform component from a game object, then your first order of business is to make that impossible in the first place :D

    Code takes time to execute. Even if the only overhead of GetComponent was a simple, managed, method call with no instructions (which, C# will use the "callvirt" IL instruction for all non-static methods, adding more overhead), there will still be a few wasted nanoseconds for that call to be processed. It doesn't sound like much, but in reality, the implementation of GetComponent is more complicated than that.

    I'm willing to bet that GetComponent uses some data structure that gives O(log n) lookup performance. In theory, you could make it constant by pre-allocating an array where each component type gets its own index in that array, but that would be both challenging and require a "large" amount of wasted memory per game object.

    Even if you managed to do that though (constant time component lookup): you're still looking at a variety of instructions required to process that method - and, to boot, the marshaling between native and managed code. I'm sure that by the time you're querying the data structure for a component, you're many stack frames deep. We're still talking nanoseconds here, but it can very, very, easily add up. Ever have a line of code in your "Update" method that at some point in the future gets added to a loop? You've just increased the amount of times you're invoking a needlessly unperformant method.

    It may seem like I'm a massive stickler for performance, but in fact I am quite the opposite. Code clarity typically takes precedence in my projects, and I'm always willing to sacrifice some level of performance for a decrease in development time and maintenance costs (in fact, you all should be like this - else, why would you be using Unity in the first place?!).

    Yet, I find it irresponsible to *not* cache your components. It not only makes your code shorter (since you're not repeating GetComponent<> all over the place) you also get a chance to add more semantics to your logic by being able to name the component you're working with. The performance benefit is a real one, but to me is hardly the most important reason I have for pushing people to do this.

    There is a lot of room for expression in code; just as there is with music. But like music, there are established rules, metrics and practices that are, for all intents and purposes, immutable. In many, many, cases, the quality of your code is not subjective. Claiming individuality isn't an excuse to do something that is demonstrably incorrect.

    Instead of claiming that everyone "scripts differently", perhaps instead you should outline concrete reasons why this practice is better or worse in terms of readability, performance and maintainability. Once a conclusion is reached (which, I think it already has by the Unity guys), we should focus on educating beginners so that they know the proper way to interact with Unity's component system. Telling them that they can "script differently" is hardly something that will properly prepare the next generation of game logic programmers.
     
  32. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    12,029
    Yeah, I'm wondering this myself. Transform is a special case because it is guaranteed/required to exist and its lifetime matches that of the GameObject. MonoBehaviours can't be moved from one GameObject to another. I can't think of any possible way for that reference to become invalidated during the lifetime of a MonoBehaviour.

    I assume there is a reason, I just can't think what it might be.
     
  33. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    12,029
    I agree.

    It's pretty darn obvious what "GetComponent<Rigidbody>()" does regardless of where you see it in the code. That's explicitly telling you that it's getting a new reference to a thing that may or may not be there.

    At the moment, though, it's not obvious what ".rigidbody" does - it looks like it's directly accessing a reference, but in plenty of cases it might not be. In some contexts that might give you an existing reference, but in others (in MonoBehaviour) it transparently goes and looks stuff up for you. Experienced coders know that and are aware that they need to pay attention in cases where it matters, and probably do it by second nature after working with Unity for a short while. Inexperienced coders don't know that and will most likely treat it as the direct reference that it looks like it is.

    As for "verbosity", we're talking about going from...
    Code (csharp):
    1. x.rigidbody.blah = y;
    ... to ...
    Code (csharp):
    1. x.GetComponent<RigidBody>().blah = y;
    ... which I don't think is a big deal. (Though I'm biased in that that's how I'd do it anyway.) It's a few more characters, sure, but it's not like we're adding lines of code. And regardless of context, one look at both of those and it's immediately obvious that one of those is more appropriate in a tight inner loop than the other (though I do realise that's probably not a concern for a Rigidbody).
     
    Last edited: May 13, 2014
    Ryiah and landon912 like this.
  34. squared55

    squared55

    Joined:
    Aug 28, 2012
    Posts:
    1,819
    TBH, the more I reflect on this, the more it seems like I'm in the "I don't like change; all change is bad" mindset. So I'll try and take your word on it. That said:

    Would be great, if possible. :)
     
  35. bizziboi

    bizziboi

    Joined:
    Feb 24, 2013
    Posts:
    17
    Hmmm, that's not nice. Some of the component references were faster to retrieve than others, and I actually used that to store userdata on objects without the hack people use with hashtables to tie userdata to objects. Can we at least get a userdata object ref on gameobject? That way I can store data on each gameobject for the cost of a cast (like I do now, I just abuse the networkcomponent and cast it to my userdata)
     
  36. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,606
    For the special case of transform, you are right. Caching should be possible and not too difficult. It just hasn't been done yet (probably we should). For all other components it's a more tricky subject.
     
  37. Nanity

    Nanity

    Joined:
    Jul 6, 2012
    Posts:
    148
    Remains the question wether this special case justifies another exception. Consistency looks very promising, especially in the case when new users or those who didn't read all the patchnotes might cache the transform reference though it's cached internally. Old tutorials don't vanish from one day to another.

    Current
    Code (csharp):
    1. private void Start ()
    2. {
    3.     _transform = transform;
    4. }
    vs Future
    Code (csharp):
    1. private void Start ()
    2. {
    3.     transform = GetComponent<Transform>();
    4. }
    I prefer the latter.
     
    Last edited: May 13, 2014
  38. Neeko

    Neeko

    Joined:
    Mar 9, 2012
    Posts:
    24
    I'd like to make the request to make the GameObject class no longer sealed. Because it's sealed it can't be extended, thus users can't implement their own form of component caching when dealing with GameObjects.
     
  39. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,140
    The .transform shortcut isn't going away.

    --Eric
     
  40. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    I'd absolutely say you guys should. Any time an API starts to have advice like "You should always, always, do this" it's a sign that the API should do that automatically. There's never a good reason not to cache the transform, so it should be done automatically.

    The other fields are all going away anyway, so for those it's kind of a moot point. I'd agree that it wouldn't make sense to cache "audio" for example since you can have multiple audio sources on one object and the user has no idea which one "audio" actually points to... that's kind of a reason the shortcut doesn't make sense in the first place and why I agree the API will be clearer without it.
     
  41. Dusho

    Dusho

    Joined:
    Jul 10, 2010
    Posts:
    22
    well all this seems like clean and nice solution.
    What worries me is the backwards compatibility of existing scripts and examples on web. It can be really frustrating for newbies if some code snippets will stop working even though they are slow (because of that implicit GetComponent call)
    Maybe if Unity would provide some build-in extension for MonoBehaviour class that would have all previously used accessors (<UT5) doing the GetComponent<> for you and maybe also putting warning to console, to cache it in order to improve the performance.
     
  42. Gigiwoo

    Gigiwoo

    Joined:
    Mar 16, 2011
    Posts:
    2,981
    Got statistics on how often people add/remove components at runtime? I for one didn't know it was even possible until Eric5 explained it in this very thread. The number of times a component is added/removed dynamically cannot possibly be but a fraction of 1% of the calls to GetComponent<>() made by millions of developers. Especially once the dot-accessors are removed.

    Gigi
     
  43. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    Even if people don't remove components that often they would still need to check for it, otherwise it would crash when you did do it, or best case throw an unexplained null reference exception.
     
  44. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,298
    Also, I would recommend that anyone who read that OP thoroughly washes their brain out with soap and water because it's mostly nonsense. Unity is not doing anything special to the dot operator, and there is no magical special "dot override" or anything, and it is not true that using a dot on a Unity component has some effect that "does not apply to normal properties". They are just properties. Properties can be fast or slow, if you have a property like "public int myInt { get { return FunctionThatTakesTwoMillionYearsToComplete(); } }" it will be slow. I think the author is not aware that Properties exist, and is mistaking them for fields, calling those "normal properties", and thinks that Unity is doing some secret magic on the dot operator.
     
  45. Nanity

    Nanity

    Joined:
    Jul 6, 2012
    Posts:
    148
    Did some research and give you Kudos. But one has to admit that Aras' comment under the article is quite easy to miss ;)

    And yes, then caching is a must. (Though I'd secretly prefer caching the transform myself.)
     
  46. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    12,029
    For reasons already mentioned, Transform is the only one really I'm interested in having it for.
     
  47. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    12,029
    I do it frequently. Also, plenty of stuff on the Asset Store works like that, with tweening libraries and GUI systems immediately jumping to mind.

    The ability to add or remove components at runtime is a huge part of the power and flexibility of component oriented systems.
     
  48. Brainswitch

    Brainswitch

    Joined:
    Apr 24, 2013
    Posts:
    270
    I add and remove components at runtime all the time. In some games almost all of them.
    I'm rather happy the built in dot shortcut properties are going away because they are mainly annoying.
     
  49. Glader

    Glader

    Joined:
    Aug 19, 2013
    Posts:
    364
    People should be forced to be aware of the expensive operations they're preforming. I support this GetComponent change.
     
  50. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Caching transform internally would indeed make a lot of sense. I don't see a need to cache any other component than transform, as it is the only component that will always exist.
    I really like this improved api, well done! I know it is not a huge change, but I like it to see that Unity also cares about consistent APIs.