Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

What C# features AREN'T available to Unity?

Discussion in 'Scripting' started by estefano-ppt, Mar 12, 2020.

  1. estefano-ppt

    estefano-ppt

    Joined:
    Feb 26, 2020
    Posts:
    8
    Topic. What isn't available? Can I use LinQ? Asynchronous language features? Reactive extensions? Tuples? Multithreading? Automatic properties? Read-only structs? I'm seeking to learn C# and I come from a solid computer science background and wanted to know what parts of the language aren't compatible with Unity. I ask in the negative figuring that listing what isn't available might be shorter than listing everything that is available.
     
    ReedMcGarveyNeudesic likes this.
  2. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You can use it all. Unity keeps current these days.
     
    Joe-Censored likes this.
  3. Cyb3rix

    Cyb3rix

    Joined:
    Feb 17, 2020
    Posts:
    15
    If you want to do things the right way in Unity, you need to 'undo' the OOP teaching that you have learned. All of your game logic revolves around Components, which are basically C# scripts (containing behavior) attached to your gameobjects.

    Unity has top quality tutorials which I recommend you try out.
     
  4. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,302
    Reactive extensions? Really?
     
  5. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Unity works with C# 8+ so just try poking it, see how far you get. I probably use the feature set of around 6 myself, nothing fancy. Unity's ECS/DOTS will use a constrained set though so do check if that's on the radar.
     
  6. estefano-ppt

    estefano-ppt

    Joined:
    Feb 26, 2020
    Posts:
    8
    No, I get this. Also, there's more to OOP than just inheritance. Good class design must also factor into account the very purpose.of the design of the underlying tool. In this case the component-pattern provided by Unity.
     
  7. Cyb3rix

    Cyb3rix

    Joined:
    Feb 17, 2020
    Posts:
    15
    Also, OOP techniques generates garbage, something which can make or break your game. You would generally want to avoid OOP in Unity as much as possible.
     
  8. Serinx

    Serinx

    Joined:
    Mar 31, 2014
    Posts:
    785
    @Cyb3rix Can you give an example of OOP techniques that break your game?
    I've been incorporating Interfaces, separation of responsibility, inheritance, code testing in a project properly for the first time and it's reduced the amount of bugs and duplicate code and it's made it so easy to make additions to the game.

    The only downside I can think of is a slight performance loss which is not noticeable for a PC game and phones are getting pretty powerful.

    Saying "avoid OOP in Unity as much as possible" is a bit dramatic since C# is an object oriented programming language.
    A gameObject and a component are both objects.
     
    matkoniecz likes this.
  9. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
  10. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,302
    "C# 8.0 is supported on .NET Core 3.x and .NET Standard 2.1" - microsoft

    Don't know what version of unity you are using, but I only have the option of Standard 2.0

    As for RX, System.Reactions is not available, VS asks to install the package... and then you try to import the dll into unity.... I have no idea how to do it, or whether it's compatible.

    People typically use UniRX which is an attempt at a unity port, so RX.Net might still be incompatible.
     
    jasonatkaruna likes this.
  11. Cyb3rix

    Cyb3rix

    Joined:
    Feb 17, 2020
    Posts:
    15
    I whole-heatedly agree with you on the first point, but you need to know when to strike the balance between readable code and good performance.

    With respect to the second point, just because hardware is getting more powerful does not mean that you should give performance and optimization a backseat.

    I think I meant to say "OO Approach" and not OOP techniques. But yes, completely avoiding OOP is close to impossible. That is why I have mentioned to avoid as much of it.

    I work with WebGL projects mostly and this is where you have to be really, really careful about how you develop your game.
     
    matkoniecz and hippocoder like this.
  12. kru

    kru

    Joined:
    Jan 19, 2013
    Posts:
    452
    https://github.com/neuecc/UniRx. It's the best thing ever. It does lack some of the latest operators, but it has more than enough to do pretty much everything I've wanted to do with it.
     
  13. Errorsatz

    Errorsatz

    Joined:
    Aug 8, 2012
    Posts:
    555
    OOP doesn't inherently create more garbage, it's just easy to do so if you're not watching out for it. I've found no need to "avoid OOP" - profiling and keeping an eye on what's using Update will keep things clean.
     
    matkoniecz likes this.
  14. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    But... components are OOP.

    Components follow the component design pattern. An OO design pattern intended to extend functionality of an entity across multiple domains/behaviours without coupling those domains/behaviours.

    OOP doesn't necessarily generate more garbage. Nevermind that Unity has been upping their GC game in newer versions.

    Constantly creating temporary objects generates garbage. As would any temporary allocation of memory would require cleaning up that memory regardless of paradigm. But considering how .net manages its memory as a stack/heap model where the stack can only hold so much memory before overflowing... you sort of have to place it in the heap. And well... the heap stores objects. That's what goes there.

    ...

    Now I'm willing to bet you mean there are some design patterns that don't necessarily mesh well with Unity.

    And this is true.

    But you don't throw out the baby with the bathwater just because some patterns don't work perfectly well. At the end of the day OO is still going to get used... it's sort of a necessity considering that Components are OO in and of themselves (well unless you just avoid components all together and go full ECS/DOTS, but that's a whole other discussion, and you suggested components).

    It'd be better to be specific about what sorts of things you may want to avoid when it comes to OOP in relation to Unity.

    Such as keeping garbage into consideration. So the creation of temporary objects can cause slow down. Where as long term objects are generally fine. And if you have to create temp objects (like say bullets), consider recycling objects whose state don't change very much between uses. Or avoid creating new arrays/collections on a whim and instead recycle them and use methods that fill existing collections (like RaycastNonAlloc).
     
    matkoniecz likes this.
  15. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,745
    While c# 8 is supported, there are major caveats you should be aware of.

    1. C# features are not .NET framework features - a big part of .net framework is not supported in unity. For instance, there are no native dialogs.
    2. When building for platforms, .net bytecode is not run directly, but instead converted to native via IL2CPP and it have it's own limitations and bugs. Something might not work or work not as expected.
    3. Unity uses assembly code stripping. It means if you or some plugins use code via reflection, it might be stripped and what is working in editor will not work when built
     
  16. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    The code-stripping thing can get a bit complicated and Unity actually gives you some decent control over it, including turning it off (except for when using IL2CPP), or giving it a list of classes/types to ignore. Anyone interested can look here:
    https://docs.unity3d.com/Manual/ManagedCodeStripping.html
     
    orionsyndrome likes this.
  17. estefano-ppt

    estefano-ppt

    Joined:
    Feb 26, 2020
    Posts:
    8
    Does this mean that I can create threads, use mutexes, and use C#'s asynchronous features? Say back when, I remember that Unity didn't support these.
     
  18. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,302
    Yes
    Haven't explicitly tried. Why don't you try?

    Yes
     
    matkoniecz likes this.
  19. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    yes, yes, and yes, but Unity itself is still non-thread-safe for the most part.
    you can use all of it on your own objects and memory accessors. if you make a smart system that doesn't run through Unity's engine in a multi-threaded fashion, you can do whatever you want. useful for parallelization of pathfinding, mesh generation, computational jobs, whatever.

    more guidelines on multithreading (on the C# part; on the Unity's it's dead simple, don't call Unity API*):
    https://docs.microsoft.com/en-us/dotnet/standard/threading/managed-threading-best-practices

    * obviously if it can affect the underlying state somehow; obviously you can call things like TransformPoint(Vector3) or Quaternion.Inverse(Quaternion) right?
     
    Last edited: Mar 16, 2020
  20. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    926
    It's still to this day not possible to use the null coalescing operator on unity objects, i.e. myGameObject?.MyProperty, which is unfortunate, and a nice source of hard to discover bugs. It requires one to deeply inspect every external object used with the operator to make sure it doesn't inherit from UnityEngine.Object
     
  21. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    this is because internally unity compares Objects (with big O) with its own type of null object. it was necessary to sweep many of the null exception scenarios, and also they have a direct control over the null object as well, making it reflective, and anything that starts referencing to it becomes noticeable in the system. there are some obscure situations when this can blow up in your face, but it works for the most part. however, when C# introduced ?? and ?. it directly circumvented this design. I don't care about this at all, it's about how you're using Unity's Objects and whether you rely too much on them, because there are other, stricter C# ways to do Unity.
     
  22. Cyb3rix

    Cyb3rix

    Joined:
    Feb 17, 2020
    Posts:
    15
    I wasn't very specific. Generally, things created on the stack aren't really the problem (like Vector3). The bigger problem is going to be reference types, which can be even more ugly if you create those type of instances every frame. I did notice that Unity has been making massive strides with its GC, but platforms like WebGL still remain an issue.
     
  23. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    But that concern is mostly up to you. How you allocate your memory has nothing to do with Unity.

    In fact, the ECS system is more like a technical guiderail for ensuring memory allocation/access optimization techniques down the line, it still has nothing to do with Unity per se (other than it having to reorient its coding framework to enable it).

    Garbage collection is, like in a city as an analogy, a necessity that arises from producing a lot of garbage. Garbage collection cannot do wonders if the citizens are irresponsible and throw their garbage everywhere and at every opportunity.

    I can only recommend you reading about memory recycling and object pooling. As you're not supposed to be creating instances every frame, most of the time, and especially if the objects are consuming a lot of memory, or are actually living longer (and thus survive the first generation of GC, or skip it entirely).

    You basically don't want:
    - to rely on GC too much
    - to fragment your heap
    - to allocate too much memory and/or too frequently
    - to have generation 2 objects that aren't supposed to be gen2

    It's just a common sense, really.

    https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals
     
    Last edited: Mar 16, 2020
    matkoniecz likes this.
  24. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    There's still no stencil buffer node for the shader graph that I know of :(
     
  25. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    That's not a C# feature and not worth of mentioning here
     
    matkoniecz likes this.
  26. Cyb3rix

    Cyb3rix

    Joined:
    Feb 17, 2020
    Posts:
    15
    It's obviously common sense to you and me, because of the experience we have with working with C# and .NET in a realtime environment such as games (something it was never initially made for). I remember the first time I came on board with Unity. I used encapsulate behaviors as an object and reference them every frame. But when I started asking questions and reading more, I started seeing that I've been doing things the wrong way, because this is how Universities and colleges do it. They ingrain the idea of OOP into you. You then have this mindset of using all of its features in every scenario, without questioning the consequence. This is especially more toxic for newcomers, to have this OOP-only approach.

    "I can only recommend you reading about memory recycling and object pooling."
    I am very well aware of this optimization technique, and have been using it for quite some time now.
     
  27. Lethn

    Lethn

    Joined:
    May 18, 2015
    Posts:
    1,583
    True, not 100% C# related my bad but still lol I want it, actually that brings up a point, is shader code in C# or something else? I never looked that up.
     
  28. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Great that you've brought this up. The idea of OOP has nothing to do with GC. In fact, F# has a GC just as well (though it can be OO, so this comparison might be unfair). What the academy doesn't ingrain into you that you should be mindful of the system as a whole. Academic solutions are, at least in the engineering terms (alone), subpar compared to the industrial ones.

    When making games, you're not supposed to be philosophical, but strictly pragmatical. And the main reasons for this, as I mentioned it already somewhere, is that any API, any framework, operates similarly to how human laws operate, than how laws of nature do. Rarely you need to overcome a natural obstacle, and when you do, there is already a well understood solution in the shape of an algorithm or quality approach, that's already escalated to industrial proportions. Think multithreading, or computer algebra in general. Would you implement your own + operator?

    But also think 3D polygonal graphics, or A*, or quaternions, or in fact the entire Unity. However it's implementation details are just like a human law, prone to conventions and precedents, workarounds and specificity, and there is no philosophy that can handle arbitrary human conventions. So the academy, naturally, ignores this aspect, and does everything under the ideal assumptions.

    There are some situations where a deeper understanding for computer sciences, information theory or superior abstract design might come in handy, but if it's not performant under the constraints of the real world usage, it's simply not worth the effort.

    There aren't that many professors and doctors making games. In fact, the only PHD's I know in this industry, come from the field of medicine (yeah, weird, I know, it's probably just anecdotal).