Yeah i agree we shouldn't waste time optimizing stuff that don't matter, I just had performance issues on a specific heavy task in my game but I managed to solve it by making my own Addons.
Anyway i went ahead and released a new Addon Pack that fix all the issues i've been mentionning for months and that i've been using extensively using in my project for about a year, it basically implements all the things i've been advocating for. I couldn't imagine making any project without those now :
ADVANCED SIGNALS & CUSTOM EXPRESSIONS
GRAB IT HERE
A powerful ADDON PACK containing 3 new behaviors for Construct 3
It contains :
- ADVANCED SIGNALS Behavior (Per-Instance Functions on steroid)
- CUSTOM EXPRESSIONS Behavior
- SIMPLE TRIGGER Behavior
- (all those behaviors also support polymorphism, making the Family feature way more powerful)
- Example/Documentation .c3p project
Those are the 3 addons I used in all my systems to create a highly modular and maintainable Roguelike. Thanks to this pack : you can create scalable systems easily, decouple your logic to avoid spaghetti code. It also makes the Family feature way more powerful thanks to the polymorphism support.
Above all, it allows you to "CREATE YOUR OWN BEHAVIORS" only using the eventsheet.
(In fact it's even more powerful than Behavior on some aspects, thanks to the polymorphism feature allowing each member of a Family to act differently)
There is so much use-case and advantages of being able to create Custom Signals, Triggers and Expressions (supporting polymorphism and multiple parameters)
it's hard to explain all use-cases and advantages, take a look at the addon pack page for more info !
ADVANCED SIGNALS & CUSTOM EXPRESSIONS
(currently running a sale/bundle to grab all my packs with a discount)
Regarding the performance issue I faced at some point calling a bunch of Advanced Signals, a good thing with this improved solution is that Custom Expressions and Custom Signals are 2 different behaviors, this way you just add the functionality you need on the relevant object and the "workload" is split, on top of being better UX-wise. (Calling an expression will only check the expressions triggers of the same behavior, same for signals, they are separated). There are also a few optimization tricks we can do that i explain in the last part of this post.
In most situations performance doesn't matter at all, I agree, we should only worry about them when we need to optimize very heavy stuff
In my project I wanted to optimize further because it happenned very often that many many entities were hit at the same times calling a bunch of signals (on hit received, on critical hit received, on death, on damage dealt, on critical damage dealt etc...), and I had many many different signals handled by a single behavior with many Triggers blocks so it was like :
(a bunch of entities + their damage dealer)
* (a lot of signal that are triggered at the same time)
* (a lot of existing signal handled by the same behavior)
* (a lot of listeners blocks for each Signal
= the exponential overhead i was talking about, and fixed
I think it's pretty rare to have that and i reckon Trigger Overhead wasn't the main bottleneck (it's just that I wanted to make sure that scenario was as optimized as possible, even if it would just save a few CPU% on those especially heavy frames), I mainly solved those heavy frames thanks to some other addons i'll probably release soon that weren't related to Trigger overhead I had.
My goal was being able to hit 100 entities at the same frame yet being able to launch a bunch of signals doing a bunch of extra checks and logic on many eventsheets for all of them without any noticeable perf drop and I managed to do it.
(Those behaviors are all as optimized as they can be, nothing is happening on tick - as opposed to Timers Behaviors - and they don't require to init anything fancy etc)
Here are a few tricks on how to enhance the performance if someone also has specific events in their game with very very intensive use of the Advanced Signal behavior on a single Object and needs to save every CPU% they can :
• Create several Advanced Signal on your object : "HitSignals", "MiscSignals" each handling just a subset of all your signals
• Use the SimpleTrigger variant for the most commonly used "Signals" or requiring the biggest number of eventblocks.
As ever with optimization, and i join Ashley on this : only do it after you actually runned into perf issue