After 2 years of programming and 1.5 years of working with Unity, I still can't understand most of the black magic you're doing in your videos. But one day, I will, sir. One day, I will.
The coolest thing about using Expression Trees in Unity is you can set up different behaviors right from the Inspector - no code changes needed! Plus, with key-to-GameObject dictionaries, you can directly reference Unity components in your expressions, making it super handy for game logic binding like {sensor}.Radius = {skill.Radius}. It’s a game-changer for flexible setups!
In my 2 years of game development journey I haven't seen anyone using expression trees as a data structure in a game. Thank you for covering so insightful and advanced topics through your videos😊😊. I hope you will be creating more such videos.
Really cool, Its possible to make some really fancy stuff using Expression Trees. But some problems I See when using them like this are that u loose the ability to Cross Reference the properties for example the health of the Hero through you IDE. And you lose compile time Errors If you remove some property which name is hardcoded in some Expression behaviour. This could lead to Errors that are realy hard to find. Using them in combination with some Interfaces could solve these problems but making them less variable in some cases. But still very cool Video👍
@@git-amend A personal question, but could you how to cleanly create attack colliders for melee monsters in a 2D game ? In 3D, you can simply attach colliders to the weapon mesh, but in the case of 2D sprites, you have to generate colliders. What would be the best way to do this cleanly?I implemented 2D colliders by reusing them with an Object Pool. Could there be a better approach?
I see you've updated your assets in your scenes for your examples. This is another banger video, you've got a style of teaching and the examples that prompt alot of ideas! Looking forward to seeing how the channel grows, you're criminally underrated, but I can easily see you passing several milestones soon!
What about the performance? This seems nice and flexible but it uses a fair amout of reflection it seems. If this is adapted everywhere and used frequently during runtime, wouldn't it cause performance issues? I might not understand something, but just curious.
When you create and compile your delegate, that's the only heavy lifting. Then you can cache it for reuse. Changes to things like a runtime state machine shouldn't be done every frame, just when your game requires it. And try to structure your expressions in such a way that most of the dynamic parts can be passed in as params or a config object to the compiled code.
My biggest concern is debuging the code, because it is compiled you cannot use breakpoints. One big use of expression trees is parse of information, so you can have the damage formula as a string that be updated by the server, and the client will compile it and resolve it easily. Code generation is fun!!! Side note, If you want to go full data driven it will be better to use a node editor and send the graph as an asset and run it at runtime. :P
1) Does it work for IOS? 2) What are the benefits over using static methods with reflection (which is definitely happening here too behind the scene), which do the same?
IOS is discussed at the end of the video. Yes it uses reflection for some operations but you compile the delegate for reuse so it’s only at compile time.
Here are a few examples: The Sims, Spore, Creatures, and the classic game Black and White all rely on dynamic scripting or runtime logic evaluation because the sheer amount of boilerplate required to handle every possibility would be untenable for these types of games. These systems dynamically generate or adapt logic at runtime to handle evolving behaviors or player-driven changes. Expression trees, introduced in C# 3.0, allow developers to dynamically construct, modify, and execute logic at runtime, making them a natural fit for such systems. A similar concept exists in C++ with function objects (functors), though C#’s expression trees provide more introspection and flexibility.
I can see this being the backbones of a visual scripting implementation, but for actual game code architecture it feels like overengineering, the GetStat method could use enums, etc etc But I can see it being powerful when building a behavior tree or something like that I guess
Do you plan to do something cover editor tools, specially Graph View. Would be cool to do something like a depth scriptable object editor, so you have SO A that has B and C attached, and in 1 screen (a bit like gamemaker display stuff) you see a graph with A pointing to B and C and is able to change value for all 3 at same screen.
Kuddos! I didnt know that kind of runtime expression even existed! I'm not sure about the other examples, but the stats getter looks neat, tho it is string based, and might be error-prone in that regard? As always, thanks for the lesson :D i'll have to watch this a couple more time and try myself. Much appreciated :D
Thank you so much! You’re right-string-based approaches can be error-prone, but you can make it safer by combining strongly-typed lambda expressions or tools like source generators. Glad you enjoyed the lesson-have fun experimenting with it! 😄 e.g. var healthGetter = CreatePropertyGetter(e => e.Health);
@@git-amend interesting topic and cool video, I look forward to the next one :) Nitpick: I think the examples in this video could have demonstrated the power of expressions better, if you changed the strings at runtime via the inspector. Imho all examples of the video would have been better implemented by passing around lambdas directly, instead of creating expressions using hardcoded strings and passing that along. Since "healthGetter = e => e.Health" is just the better option compared to "healthGetter = CreatePropertyGetter("Health")" cheers
Dude I just started using these a couple days ago, what the hell. Are you gonna do a video on Lua scripting next too? Might actually be a fun topic. I used MoonSharp
@ There isn't much up-to-date info about it around anymore, and the project itself seems to be abandoned. It still works though, I'm using it in Unity 6 perfectly fine.
Suggestion: Scene State Management. What doors are locked/unlocked, or whatever can change in the environment. Not the player or enemies. The other stuff. I'm having issues finding an elegant way to do so and be able to load without having a bajillion sound effects and animations firing off on load.
Excellent question. No, it doesn’t always have to be done with strings. If you have access to strongly-typed members, you can use expression trees directly to reference properties or methods, avoiding the reliance on strings and reducing potential errors. public Func CreatePropertyGetter(Expression propertyExpression) { return propertyExpression.Compile(); } // Usage var getter = CreatePropertyGetter(e => e.Health); var health = getter(enemy);
@@git-amend That's pretty neat! Thanks! What about performance on low end devices, would you still advise to use expression trees on the average android phone? I ask because I noticed it falls under the linq namespace and linqs are known to have overhead in terms of performance.
Well, the nice thing about Expression Trees is that you compile them one time and then can reuse. So the cost of LINQ is only when you call the Compile method. After that, executing the compiled function will be very fast. So cache it if possible.
Very interesting approach! LogWin really piqued my interest. I bought it, and discovered that it is abandonware and the doc link points to a dead end. Moreover, it doesn't use assemblies, and the central class does not even use namespaces. I am pondering whether it's worth adding namespaces to the source files manually and adding an assembly to use it in my projects. Since you use it: Any advice?
Interesting, I never even noticed it's last update until you pointed that out. The tool itself is actually quite simple, and should work in any version of Unity. I think you should customize it and make it your own! Docs here: julien-foucher.com/unityassetstore/logwin/
I remember why I bought this actually. Another subscriber recommended another Asset by the same author (//TODO (Code Todo List)) which is also a great little tool. I see from it's release date it was updated more recently (2023). It was cheap so I bought this too, and it turns out I use it more than the other one that was recommended.
@@git-amend I've found unity forum conversation about AOT restrictions and that from some unity version we have shared generics so it should normally execute Expressions without restrictions in IL2CPP builds. However I also saw mentions about worse optimizations in comparison with JIT when compile expressions.
reflection, expression tree and emit(DynamicMethod): reflection is slowest, emit is powerful but need some knowledge of IL, expression tree is more restricted but simpler.
Thanks for the tutorial, but for a multiplayer game where obsfucating the codes is crucial, this type of system that rely on reflection cant be used to prevent cheating, is there any other similar solution ? its a realy usefull system for code flexibility.
You’re right that reflection-based systems can expose potential vulnerabilities in multiplayer games. A safer alternative is to use code generation at build time, where dynamic behaviors are compiled into static code. Tools like Source Generators in C# or Unity’s ScriptableObjects can provide similar flexibility while keeping the final code obfuscated and secure. We will likely have a video about source generators soon.
At the end of the video I talk about an Asset from the store you can use to overcome that limitation. Link in the description. The Asset is called C# Eval()
That's a hard question to answer, because it's really project specific and sometimes the roles are beyond just junior/intermediate/senior (such as technical product manager for example, or team lead).
Hmm, this is indeed an interesting approach. But, I can only see this being used to make editor tools that might require being dynamic based on designers. But, runtime-wise, I feel like the same benefits can be achieved using interfaces and injection, might actually be more flexible. I might be missing something, and I'd like to be educated if I am 😅 still a fantastic demo. I usually stay away from LINQ but, this looks fun to play with.
Thanks for the thoughtful comment! While interfaces and injection work well for static, pre-defined behaviors, expression trees shine when runtime dynamism is required, such as enabling modding systems, scripting engines, or data-driven AI behavior that can adapt without recompiling. They’re also great for cases like runtime property binding or dynamically building logic pipelines (e.g., AI decision-making), where pre-defined structures like interfaces fall short.
Well, Expression Trees serve a different purpose than ECS: they excel at dynamically building and executing logic at runtime, which is difficult to achieve with a static ECS architecture. Both have their strengths and can even complement each other in certain use cases.
Thank you! While these simple examples might seem overengineered, keep this concept in your back pocket for times when static solutions are not possible or practical.
I think this could be useful when you are making a game about a programmable robot and have a custom in game programming language that would represent the code with expression trees.
Happy Sunday Everyone! Looks like the channel is about to hit another milestone! Thanks for all the Likes, Shares and Comments! 🤘
After 2 years of programming and 1.5 years of working with Unity, I still can't understand most of the black magic you're doing in your videos. But one day, I will, sir.
One day, I will.
Keep it up! The journey never ends!
Same situation
same here
The coolest thing about using Expression Trees in Unity is you can set up different behaviors right from the Inspector - no code changes needed! Plus, with key-to-GameObject dictionaries, you can directly reference Unity components in your expressions, making it super handy for game logic binding like {sensor}.Radius = {skill.Radius}. It’s a game-changer for flexible setups!
That is a very good tip! Thanks for sharing that!
In my 2 years of game development journey I haven't seen anyone using expression trees as a data structure in a game. Thank you for covering so insightful and advanced topics through your videos😊😊. I hope you will be creating more such videos.
You're very welcome! Check out some of the other comments for some examples of how others have been using them and tips from the community!
My brain is too smooth to even understand what is happening.
Try out the first example for yourself, maybe it will help it make sense.
Really cool, Its possible to make some really fancy stuff using Expression Trees. But some problems I See when using them like this are that u loose the ability to Cross Reference the properties for example the health of the Hero through you IDE. And you lose compile time Errors If you remove some property which name is hardcoded in some Expression behaviour. This could lead to Errors that are realy hard to find. Using them in combination with some Interfaces could solve these problems but making them less variable in some cases.
But still very cool Video👍
Yes, I agree! Thanks for the comment!
How you always make video about the thing i need for my project when i need it? Simply amazing content 🥰
Happy to hear that! Comments like that always make my day!
Your video quality keeps improving, and the comprehensiveness and clarity of the subject matter are improving also! I love your channel!
Thank you, that is very kind to say!
Ohhh boy! Here we go! Thanks for the weekly vid :)
You're welcome!
As I always feel, I learn a lot from your videos. Studying while changing your videos to my style helps me improve my skills
Happy to hear that!
@@git-amend A personal question, but could you how to cleanly create attack colliders for melee monsters in a 2D game ? In 3D, you can simply attach colliders to the weapon mesh, but in the case of 2D sprites, you have to generate colliders. What would be the best way to do this cleanly?I implemented 2D colliders by reusing them with an Object Pool. Could there be a better approach?
Again another video that just blew my mind. Thankyou so much!
My pleasure!
Rooting for 20k subs for you ;)
Nice video XD
So close! A few more days! Thank you!
I see you've updated your assets in your scenes for your examples. This is another banger video, you've got a style of teaching and the examples that prompt alot of ideas! Looking forward to seeing how the channel grows, you're criminally underrated, but I can easily see you passing several milestones soon!
Thank you so much! I'm glad the examples are inspiring ideas-comments like this keep me motivated. Excited to keep growing and sharing more! 🎉
Dude you're awesome! Your content is exactly what this community needs. Thanks a lot for everything and godspeed 🙌🙌
I appreciate that!
Like always an amazing video, after release of your every video I refactor my practice code and find it even more logical, clean and performant.
Great to hear!
What about the performance? This seems nice and flexible but it uses a fair amout of reflection it seems. If this is adapted everywhere and used frequently during runtime, wouldn't it cause performance issues? I might not understand something, but just curious.
When you create and compile your delegate, that's the only heavy lifting. Then you can cache it for reuse. Changes to things like a runtime state machine shouldn't be done every frame, just when your game requires it. And try to structure your expressions in such a way that most of the dynamic parts can be passed in as params or a config object to the compiled code.
My biggest concern is debuging the code, because it is compiled you cannot use breakpoints.
One big use of expression trees is parse of information, so you can have the damage formula as a string that be updated by the server, and the client will compile it and resolve it easily.
Code generation is fun!!!
Side note, If you want to go full data driven it will be better to use a node editor and send the graph as an asset and run it at runtime. :P
I like that use-case! Great comment, thanks for sharing that!
1) Does it work for IOS?
2) What are the benefits over using static methods with reflection (which is definitely happening here too behind the scene), which do the same?
IOS is discussed at the end of the video. Yes it uses reflection for some operations but you compile the delegate for reuse so it’s only at compile time.
Are there actual commercial projects that felt the need to adopt such an approach?
Here are a few examples: The Sims, Spore, Creatures, and the classic game Black and White all rely on dynamic scripting or runtime logic evaluation because the sheer amount of boilerplate required to handle every possibility would be untenable for these types of games. These systems dynamically generate or adapt logic at runtime to handle evolving behaviors or player-driven changes. Expression trees, introduced in C# 3.0, allow developers to dynamically construct, modify, and execute logic at runtime, making them a natural fit for such systems. A similar concept exists in C++ with function objects (functors), though C#’s expression trees provide more introspection and flexibility.
If anyone knows I would also like to know
I can see this being the backbones of a visual scripting implementation, but for actual game code architecture it feels like overengineering, the GetStat method could use enums, etc etc
But I can see it being powerful when building a behavior tree or something like that I guess
Do you plan to do something cover editor tools, specially Graph View. Would be cool to do something like a depth scriptable object editor, so you have SO A that has B and C attached, and in 1 screen (a bit like gamemaker display stuff) you see a graph with A pointing to B and C and is able to change value for all 3 at same screen.
Not a bad idea. I've been thinking about doing a video about how to use the underlying framework of the new behavior package to do that.
@@git-amend I didn't know we could use it, now I want to see haha
now I started to doubt my way of coding , After watching your videos. Thank you.
Keep it up!
Kuddos!
I didnt know that kind of runtime expression even existed!
I'm not sure about the other examples, but the stats getter looks neat, tho it is string based, and might be error-prone in that regard?
As always, thanks for the lesson :D i'll have to watch this a couple more time and try myself.
Much appreciated :D
Thank you so much! You’re right-string-based approaches can be error-prone, but you can make it safer by combining strongly-typed lambda expressions or tools like source generators. Glad you enjoyed the lesson-have fun experimenting with it! 😄
e.g. var healthGetter = CreatePropertyGetter(e => e.Health);
@@git-amend interesting topic and cool video, I look forward to the next one :)
Nitpick: I think the examples in this video could have demonstrated the power of expressions better, if you changed the strings at runtime via the inspector. Imho all examples of the video would have been better implemented by passing around lambdas directly, instead of creating expressions using hardcoded strings and passing that along. Since "healthGetter = e => e.Health" is just the better option compared to "healthGetter = CreatePropertyGetter("Health")"
cheers
It's Sunday. The Git-Amend video has dropped - time to strap in folks....!!
Yes, buckle up!
Dude I just started using these a couple days ago, what the hell. Are you gonna do a video on Lua scripting next too? Might actually be a fun topic. I used MoonSharp
Not a bad idea!
@ There isn't much up-to-date info about it around anymore, and the project itself seems to be abandoned. It still works though, I'm using it in Unity 6 perfectly fine.
Interesting. There have been several requests on Discord for that topic.
Suggestion: Scene State Management. What doors are locked/unlocked, or whatever can change in the environment. Not the player or enemies. The other stuff. I'm having issues finding an elegant way to do so and be able to load without having a bajillion sound effects and animations firing off on load.
Maybe in the future! There's a section on Discord where we track these kinds of suggestions if you want to add it there.
Does it always have to be done with strings?
Excellent question. No, it doesn’t always have to be done with strings. If you have access to strongly-typed members, you can use expression trees directly to reference properties or methods, avoiding the reliance on strings and reducing potential errors.
public Func CreatePropertyGetter(Expression propertyExpression) {
return propertyExpression.Compile();
}
// Usage
var getter = CreatePropertyGetter(e => e.Health);
var health = getter(enemy);
@@git-amend That's pretty neat! Thanks!
What about performance on low end devices, would you still advise to use expression trees on the average android phone? I ask because I noticed it falls under the linq namespace and linqs are known to have overhead in terms of performance.
Well, the nice thing about Expression Trees is that you compile them one time and then can reuse. So the cost of LINQ is only when you call the Compile method. After that, executing the compiled function will be very fast. So cache it if possible.
@@git-amend Alright damn! Sold😅
I'll be mindful about that. And the iOS thing. Thanks again.
Whenever someone tells you not to use reflection because it's slow, just laugh and call them a noob for not using expressions.
lol noted
Very interesting approach!
LogWin really piqued my interest. I bought it, and discovered that it is abandonware and the doc link points to a dead end. Moreover, it doesn't use assemblies, and the central class does not even use namespaces. I am pondering whether it's worth adding namespaces to the source files manually and adding an assembly to use it in my projects. Since you use it: Any advice?
Interesting, I never even noticed it's last update until you pointed that out. The tool itself is actually quite simple, and should work in any version of Unity. I think you should customize it and make it your own!
Docs here: julien-foucher.com/unityassetstore/logwin/
I remember why I bought this actually. Another subscriber recommended another Asset by the same author (//TODO (Code Todo List)) which is also a great little tool. I see from it's release date it was updated more recently (2023). It was cheap so I bought this too, and it turns out I use it more than the other one that was recommended.
Is it correct that expressions need JIT and it won't work with IL2CPP compilation?
The problem is with iOS and WebGL. I talk about a tool on the asset store that will solve these issues at the end of the video.
@@git-amend I've found unity forum conversation about AOT restrictions and that from some unity version we have shared generics so it should normally execute Expressions without restrictions in IL2CPP builds. However I also saw mentions about worse optimizations in comparison with JIT when compile expressions.
Nice!
Thank you! Cheers!
@@git-amend Almost 1 Million total channel views, congrats.
Yeah, crazy. Couple more weeks!
What's the difference between this and reflection?
reflection, expression tree and emit(DynamicMethod): reflection is slowest, emit is powerful but need some knowledge of IL, expression tree is more restricted but simpler.
@verdantblast ill look more into it, thank you!
Something something something. My project. Something Something.
LOL
Thanks for the tutorial, but for a multiplayer game where obsfucating the codes is crucial, this type of system that rely on reflection cant be used to prevent cheating, is there any other similar solution ? its a realy usefull system for code flexibility.
You’re right that reflection-based systems can expose potential vulnerabilities in multiplayer games. A safer alternative is to use code generation at build time, where dynamic behaviors are compiled into static code. Tools like Source Generators in C# or Unity’s ScriptableObjects can provide similar flexibility while keeping the final code obfuscated and secure.
We will likely have a video about source generators soon.
@@git-amend Thats nice this way we would solve il2cpp probelms as well i guess.
This shouldn't work for AOT platforms, am I missing something?
At the end of the video I talk about an Asset from the store you can use to overcome that limitation. Link in the description. The Asset is called C# Eval()
@git-amend thanks!
Good stuff but I would probably avoid it for 2 reasons:
1. refactoring
2. most of devs won't understand this
These techniques are powerful but not for beginners.
@git-amend. Definitely! But I would argue that not only for beginners, but neither for mid- and even some seniors either.
@ btw, what is a percentage of juniors, middle and seniors in a general game dev team?
That's a hard question to answer, because it's really project specific and sometimes the roles are beyond just junior/intermediate/senior (such as technical product manager for example, or team lead).
For the algo!
Yes, thank you!
Hmm, this is indeed an interesting approach. But, I can only see this being used to make editor tools that might require being dynamic based on designers. But, runtime-wise, I feel like the same benefits can be achieved using interfaces and injection, might actually be more flexible. I might be missing something, and I'd like to be educated if I am 😅 still a fantastic demo. I usually stay away from LINQ but, this looks fun to play with.
Thanks for the thoughtful comment! While interfaces and injection work well for static, pre-defined behaviors, expression trees shine when runtime dynamism is required, such as enabling modding systems, scripting engines, or data-driven AI behavior that can adapt without recompiling. They’re also great for cases like runtime property binding or dynamically building logic pipelines (e.g., AI decision-making), where pre-defined structures like interfaces fall short.
have you ever tried something like Gameplay Tags for unity?
You mean like this Asset? assetstore.unity.com/packages/tools/utilities/game-tags-280149
Hm, it is interesting method. But the world already created ECS)
Well, Expression Trees serve a different purpose than ECS: they excel at dynamically building and executing logic at runtime, which is difficult to achieve with a static ECS architecture. Both have their strengths and can even complement each other in certain use cases.
Your tutorials are really good but damn, that's complex
Thank you! I try to balance depth with clarity-complexity like this pays off in flexibility and scalability for certain use cases.
FIRST
Nice congrats!
I feel like this approach requires tremendous planning on paper
Honestly sounds overengineering... way to complex to do something that can be achieved via other strategies :DO Regardless, great tutorial!
Thank you! While these simple examples might seem overengineered, keep this concept in your back pocket for times when static solutions are not possible or practical.
@@git-amend for sure, already cementing in the back of my mind!
I think this could be useful when you are making a game about a programmable robot and have a custom in game programming language that would represent the code with expression trees.
@@Tymon0000 I would likely think about integrate a lua interpreter os something else before this solution:D
The real win here is logwin. Never knew I needed something so bad until I saw it.
Haha, yes. It's a great little tool!
What do you need it for? I am curious.