#IL2CPP Performance Helps Unity Visual Scripting?

1 messages · Page 1 of 1 (latest)

dawn ivy
#

I've been reading about "scripting restrictions" from this manual doc

https://docs.unity3d.com/6000.2/Documentation/Manual/scripting-backends-il2cpp.html

And reading about it... It says on compile (build) turns any c# code from unity to c++... Including Unity Visual Scripting (uVS)

IL2CPP literally means:

Intermediate
Language
To
C
Plus +
Plus +

So c# is considered intermediate?

That means c++ is superior and more compatible with other platforms such as android and windows? (My targeted platforms btw, specially android)

So i was wondering... Does it mean, whatever you make in uVS, on build and using this settings...

All code is transformed in c++... Making it as performant as c++??

This is a common complaint from using uVS that its slow that c# is better... Etc...

But isnt this like the holy grail fix for this?

I dont know about it. Im asking. And i went ahead searching online and here's what gemini says:

"Yes, Unity's IL2CPP (Intermediate Language to C++) scripting backend converts code from Unity Visual Scripting graphs into C++."

#

I started my investigation because i use a lot AOT dictionaries... And i saw this AOT means "ahead of time".

And one thing led to another.

JIT mono backend compiles script on the go. (Unity Default Setting)

Which explains why it may lag and because uVS possibly has more unnecesary code behind the scenes... Could explain why it can be slower.

Even if it still gets translated to c# after a build.

BUT... IL2CPP does the compile "AOT" - means BEFORE the .exe even runs, that's why it takes longer to compile but may run ultra faster than its counterpart.

This is interesting. And if its true, uVS is a good thing to learn and use until the end (the final build) 🤓✌️

thin blade
#

I think the main slow down is that UVS uses Reflection(I don't think there is another way to get around that for any Visual Scripting tool)

dawn ivy
thin blade
#

Reflection is a way to trigger code (or access data) indirectly, by name or metadata, instead of directly through normal code references.

so instead of

// Store the Vector3 in a variable
var vector3 = new Vector3();
// Trigger logic on the Vector3
vector3.Normalize();

you might do:

// Get the type of the Vector3
var type = typeof(Vector3);
// Look through its methods to find Normalize
var method = type.GetMethod("Normalize");
// Trigger the normalize method
method.Invoke(vector3, null);

If you don't understand this code i can do a UVS example because I know you haven't had much luck with C#

so it has these extra steps to do the same thing in the first example

So reflection is a way to inspect and interact with code indirectly at runtime like finding and calling methods or accessing fields without referencing them directly in your code.

IL2CPP does make sure everything including UVS ends up as native code. But UVS is slower not because of “C# vs C++,” it’s slower because of the extra runtime layers (like reflection). IL2CPP preserves that logic, it doesn’t remove it.

I don't know all of this I am not a expert I also recently started to learn about it but it seems like the way it works is yes it converts to C++ but that does not change much because the extra layers are still there its not converting the graphs to this:

// Store the Vector3 in a variable
var vector3 = new Vector3();
// Trigger logic on the Vector3
vector3.Normalize();

it converts them to this:

// Get the type of the Vector3
var type = typeof(Vector3);
// Look through its methods to find Normalize
var method = type.GetMethod("Normalize");
// Trigger the normalize method
method.Invoke(vector3, null);

So the slow down does not get removed

dawn ivy
#

• var vector3 = new Vector3();
• vector3.Normalize();

• Var type = typeof(Vector3);
• Normalized var method = type.GetMethod("Normalize");
• method.Invoke(vector3, null);

==={

So instead of 2 simple lines that does a direct operation...

The other one does 3 line of operations and using getMethod and invoke that method? Giving it extra steps / overload to the logic?

How do you know uVS does this with c#? Or it was an example?

Even though the nodes to normalize a Vector3 seems very straightforward...

Guess i should look into each node's c# logic to see this behind the nodes.

Someone sent me the cooldown c# behind the node once... I think it was you?

I wonder how i could look behind each node. I've seen there's few tips to maintain uVS performant - such as:

  1. avoid onUpdates
  2. avoid find components
  3. keep logic simple, independent, and with less dependencies (unlinked from other graphs/objects)
  4. cache reusable things such as main camera, or managers (like singletons)

And more...

thin blade
# dawn ivy • var vector3 = new Vector3(); • vector3.Normalize(); ===== • Var type = typeof...

I’ve looked at how the node’s code works that’s how I know. Here’s an example of the InvokeMember it’s actually quite complicated.
but if you look at private object Invoke(object target, Flow flow) you can see it uses member.Invoke() and this uses reflection

Basically, UVS doesn’t create a unique unit for every method or property. Instead, it reuses a generic InvokeMember unit and just fills it with the specific information (Type, Method, Field, Property, or Constructor).

For example, you won’t find a dedicated Mathf.Clamp unit in UVS. Instead, UVS generates an InvokeMember unit and supplies it with the reflection data needed to call Mathf.Clamp.

thin blade
thin blade
#

Like the first Image is faster than the second one because in the second one you get the component twice but the first one you get the component once and reuse it where ever you need, So from what i have seen its more common to do the second Image

dawn ivy
#

Hmm interesting. It uses the previous node twice...

thin blade
dawn ivy
#

I do that cache-results now, accidentally found the issue with it before.

A random node output connected to 2 different multipliers... Were getting 2 different numbers.

That made me see that node was running twice.

So yeah it makes sense. And also, graph variable is faster than object variable.

I assume flow is even more.

thin blade
thin blade
#

Ahh interesting it seems like its possible that there could be a performance increase by connecting the Control Inputs even when you only want the value because looking at the code for the Unit triggering the ControlInput cache's that value so its the same as storing it in a variable then reusing the variable so basically doing this it only triggers once

#

But doing this it triggers everytime you try to get its value because it does not cache the value so it triggers the Random.Range both times

#

I always though it was the opposite

#

Also looking at the variables yeah everytime you call Get Or Set Object variable it does a GetComponent call so it might be slower than graph or Flow looking at these 2 though they might be the same speed if not Flow may be slightly faster but the speed up will be extremely low that its not noticeable

#

I wonder if setting them directly is faster, mmm probably not because now that i think of it all of these nodes are using reflection so yes it does do a GetComponent call but that get component call is faster because its triggering directly where here we GetComponent using reflection then Get the variables using reflection then set the variable using reflection so i can imagine that this is slower

#

I guess they almost the same speed but any way maybe there is a slight difference in variable types it does not seem like its that much

dawn ivy
dawn ivy
dawn ivy
thin blade
thin blade
thin blade
young echo
#

Hi guys, quick question. Can uVS be compiled into C# that is then built like normal c#?

thin blade
stone hill
dawn ivy
# stone hill Very interesting. So you will get the same value for both randoms in the first i...

Yeah thats something i discovered by accident and shared it here.

So to avoid 2X execution:

Set a flow variable. And get that variable throughout the flow.

If its used elsewhere in the same graph, graph variable.

If its needed in another object, as object or even scene variable.

When i was testing i wasnt getting all item drops... Because i needed one number rolled not more than once. Thats when i noticed that in livemode actual numbers