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.
You can use it all. Unity keeps current these days.
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.
Reactive extensions? Really?
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.
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.
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.
@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.
Limitations are usually per platform or with specific build options rather than being general to all Unity builds. For example, WebGL probably has the most limitations, and using IL2CPP instead of Mono has some rather mild limitations.
WebGL limitations:
IL2CPP limitations:
“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.
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.
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.
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.
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).
While c# 8 is supported, there are major caveats you should be aware of.
- 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.
- 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.
- 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
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:
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.
Yes
Haven’t explicitly tried. Why don’t you try?
Yes
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?
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