Why is C# the [only] scripting option?

It’s basically the biggest weakness of Unity so it’s a weird thing to copycat. It’s a language designed for windows forms and has intrinsic weaknesses for realtime applications.

a) Garbage Collection. GC can happen at inopportune times and trying to avoid it either means programming C-style through C# which can be grueling or force GC on your own and kill many optimizations. It’s a huge pain to deal with toward the end of a project.

b) C# as a language is not designed for high-churn of data. Exactly the opposite of what’s needed in games.

c) Optimization options are quite limited. There is basically a checkbox for optimized or not optimized.

d) Also, if you’re using .NET the product won’t be as portable. Running the editor on Macs or having the game play on embedded systems like Playstation will be a pain.

Hello @Sol_Aries

I see a lot of misconceptions in your message. So I’ll try to answer each point with my personal take on it.

a. Garbage collection is not necessarily an issue. It relieves the developer from having to deal with memory directly (and prevent wheel-reinventing). And in case GC becomes an issue there are workaround and good practices to mitigate it. As well as the ability to use/call native code if necessary for tight loops or runtime critical section.
In some cases, GC language can actually run faster because of better memory locality, since GC compacts memory when it releases it.

b. Just because it has a GC doesn’t mean that. In fact the less allocation you do, the better the GC’s performance is. So good house keeping is also required when writing C# code.

c. The C# compiler and JIT do a lot of work to run very fast code. Some optimizations that aren’t possible with static language are possible with JIT thanks to the compiler having more context when producing native code. Some future version of the runtime will allow more targeted (tiered) optimization (see https://blogs.msdn.microsoft.com/dotnet/2018/08/02/tiered-compilation-preview-in-net-core-2-1/).
Also C# can be AOT.

d. C# runs on almost all platforms including PlayStation (which we don’t support at the moment anyway).
There is something called .Net standard that makes .net code (amongst it C#) supported in all platforms with no code change (but still allow to write platform specific code). And there is .net core which is a new runtime with a specific focus on performance and portability.

e. (yes you didn’t have that one) Nothing prevents you from writing code in another language as long as it can call .net libraries (since the engine is mostly .net) and you can call native libraries from your scripts.

Anyway, welcome to Xenko. I hope that you will join our adventure. :wink:

1 Like

These are some broad generalizations I can’t say I agree with. It’s true that C# isn’t going to beat C/C++ for title of #1 speed, especially out of the box, but it’s not going to be slower by an overwhelming margin if you take advantage of things that do exist.

  1. C# allows you to take over a lot of the memory management if you want / need by using the unsafe keyboard and implementing your own memory cleanup.

  2. Anything that needs absolute memory control can be written in C++ and wrapped and easily invoked.

  3. You can also compile .net to native code instead of JIT for more performance.

  4. Roslyn can be directed to in-line methods by simply simply marking them as such.

These are just a few things you can do that are more than a checkbox. Again, I have no delusion of C# competing with C++ for absolute performance but memory and optimization options exist and can close a large portion of the gap.

1 Like

A correction: In (b) I meant to say C# is not designed for high churn of data.

A disclaimer: I know .net is better than mono, but I’m not sure to what extent in terms of GC issues late in the cycle.

All that sounds good in theory, and I’ve heard it before, but in practice there’s a whole market for programmers to fix GC issues for games in Unity. Once a game starts seeing the very distinct GC hitch pattern / slowdowns it’s too late, and worse of all, it tends to happen late in the cycle. Saying “you could’ve done this or that” is no consolation at that point. A grueling process follows to fix GC issues, often hiring expensive contractors to help.

People tend to program lazyly until a need comes to change that. Not uncommon to see devs churning thousands of game objects a frame. There’s no good way for a GC to smoothly handle that. You can say, well write your own allocator, or something like that but by the time you see the issue, that would be a mountain of bug-prone work. You can also say, “you programmed it poorly” to devs using your engine, but that’s not productive or helpful at that point.

Aside from C# specific issues, most engines provide choices to protect developers from themselves: Lua, GDScript, Blueprints, etc. It helps your engine be more accessible to a wider market. It makes learning your engine easier and thus faster adoption. Most importantly, they narrow the choices to safe but powerful operations. I mean, you provide something for shaders, isn’t game code just as important?

EDIT: you have to wonder why people don’t make AAA games using Unity. Maybe Hearthstone, but that’s still a mobile game and they heavily modified the engine. If your engine is for mobile, then maybe it’s ok, but I’d still think making a scripting language that non-programmers can use is worthwhile.

EDIT2: Also consider your target audience. A lot of them are young. Just out of college, in college, or self -taught. Requiring high technical abilities and rigorous software engineering training does not cater to them. In addition you’re expecting great engineers to also be great designers, so you’re stacking odds exponentially against each other.

EDIT3: .Net seems much slower than Mono at JIT compiling. Iterating is significantly slower than Unity or Godot. Another advantage of a (non-gc/jit) scripting language is faster iteration.

I addressed those points in my post when I said your alternative to issues is a grueling process. It defeats the point of using a GC language for game scripting.

Taking over memory management, writing C++ wrappers, and other methods is not a dev-friendly process. Not something I have to worry about with Unreal’s Blueprints, for instance (which also nativize).
You don’t want to be in the position where you’re telling devs they did their game wrong.