PlayMaker Help & Tips > PlayMaker Tips & Tricks

Don't use RunFSMs in instantiated GameObjects!

(1/2) > >>

Deek:
I had a problem in my game for a while in which I got severe lag spikes when instantiating enemies at runtime (see attached screenshot).
Finally took some time to look into it and it turns out it's because those enemies had FSMs on them that are using RunFSM Actions. The templates those RunFSMs use are also big and have even more RunFSMs nested inside of them.

It seems to be that PlayMaker creates a new FSM for every RunFSM the original FSM contains, thus adding up instantiation time in the Awake()-Function (which is actually the best place for heavy operations, but still not efficient enough for big and nested FSMs).

I didn't know that and it's described nowhere that it actually creates new FSMs, I was hoping it would take all actions out of those templates and append those internally to the host FSM or any other way that would be more efficient.

So it should be best to avoid using RunFSMs on objects that have to be instantiated at runtime (and I can't use pooling or create them at scene start since the spawn-amount is indefinite).
Alternative approaches would be to copy over the content of the RunFSMs to the host FSM (useful when the content is small in action/state size) or to outsource the template into a global manager that you ping with a global event instead of creating that template at runtime.

tcmeric:
If you do want to use pooling, you can still do so. The asset pooly for example allows you to set a start amount, and a cap amount for the pool. You can also set no cap (or no start amount). It will dynamically increase your pool size as you need it. But, you can still get the benefit of a pool if even if your pool size is unknown to begin.

jeanfabre:
Hi,

 I'll do some research on this to see exactly what's happening.

 but I would not say you should never use it, but in your case indeed, maybe something could be refactored.

 the questions would be what is inside theses fsm you run dynamically, maybe the issue is inside them and not because of the instantiation? have you experiment with this? like do you get still a huge spike if you runfsm on an empty fsm template?

I'll experiment on my side too anyway.

Bye,

 Jean

Deek:
@tcmeric
I always thought pooling could only be used to re-use the same objects over and over again, so having an indefinite amount doesn't it mean that there is still some instantiation happening for every new object?

@jeanfabre
I tried it with small templates and that doesn't cause any noticeable spikes so it's likely because of the size of the template (see screenshot, the template is also in the attachments but I don't know if those are portable).
I used that template 3 times in the enemies FSM because I wanted to manage all enemy actions globally, causing the big spikes, but that is just the extreme example.

In my custom Inventory every Slot had a fairly complex FSM on them but hadn't have any performance problem at runtime.
So I took some of that logic, put that in a template and ran it with RunFSM (to create a better overview and make it more manageable) and just then it started lagging when opening my Inventory.
It was the same amount of actions and states before but putting them in RunFSM caused my game to lag and pretty much the same goes for the enemies, which means it must be the RunFSM actions that increase the overhead.

I already fixed all those lagspikes by outsourcing the majority to a global manager, but it still means that using RunFSM creates a worse performance than putting everything in one FSM.
As you can see in the profiler screenshot it increases the instantiation time in Awake(), which lead me to believe that it is creating a new FSM for every RunFSM that is prevalent, because I read somewhere in this forum that for every FSM you have in your scene, the loading time increases by like 0.05s.

jeanfabre:
Hi,

 ouch...

You need to refactor this, this is indeed not how you should approach fsms.

 instead of having such a big fsm for so many types of enemies,
have one for each type of enemies:

- easier to debug
- easier to build
- easier to scale up
- no spikes ( not as much should I say)
- no unnecessary loading of 90% of states that will be unused in each case.

Bye,

 Jean

Navigation

[0] Message Index

[#] Next page

Go to full version