Pending Review

ScriptRunBehaviourUpdate Performance

Real World 3 years ago updated by Lazlo Bonin (Lead Developer) 3 years ago 8

I've got a horrible feeling my apps performance is being killed by Bolt. I have one main flow machine that controls all the UI flow in my app. To clean up the graphs and reduce duplication I'm using a lot of Super Units. Not one of those super units uses the Update unit. Pretty much everything is just "do A" then "wait for custom event B" then "do C" etc. This is how the profiler looks.

I've tried using a state machine before. I figured that might disable huge chunks of my flow that aren't being used but its quite difficult to divide my app into states. Especially since I can't fire an event from a flow graph to say "Go to state X".

Is there any way I can improve this?

Bolt Version:
Unity Version:
Scripting Backend:
.NET Version (API Compatibility Level):
Pending Review

It's hard to tell from this screenshot, because the tree isn't fully expanded. I know Unity's debugger is painfully slow when you start expanding nodes, but I'd need you to get to that bottom of that tree to know what's happening exactly (what exactly takes 212ms).

The good news is that the Self time from these items is very low (0% / < 1ms),  so it's probably not the Bolt architecture itself that is slowing down your game. There might be some very slow code in one of the units in a deep nested graph, but we need to dig to that level to see it.

Edit: For clarification, even if you're not using Update nodes, Bolt has to hook into the Unity update event at the component level, because it's the only way of receiving that event, and it's needed for some other types of units (e.g. the "On Keyboard Input" unit has an internal update loop to pool for input) and to enable Update support is you decided to add an Update event while in play mode. This might be something could be avoided in 2.0 with script generation.

Not got to the bottom but theres a big drop off at this point. Not sure what GameObjectEvent.Update is though

That is any kind of event that takes a Game Object input as a target. The target gets updated (and fetched) at every Update call in case it changes. If you have a very intensive code to fetch a target, this might be the issue. For example:

A simple solution to mitigate this would be to cache the result of that fetch to only be whenever you need it:

That being said, that's just 4% / 12%, so I wonder what the rest is!

Just more instances of the same thing. I don't think I've used any methods on GameObject other than in one graph to do a SetActive call. Though a few Super Units might take a GameObject as an input parameter. Would that be the same?

Though a few Super Units might take a GameObject as an input parameter. Would that be the same?

What do you mean?

Also, did implementing a start cache help improve the performance?

I might have found some stuff that could be cached but I'm having problems. I've got this Super Unit that looks up a menu by its component type and returns an instance of it

As you can see, this is working fine. This Super Unit exists in a flow machine in the main scene.

This one isn't working though

The difference here is that this super node is in a flow graph that is part of a state machine. The state is active but it doesn't look like start is called?

If I add an "On Enter State" unit and hook that up to the same input node Start is hooked up to then it works.

That's normal, the Start event does not get sent in flow machines. You can safely connect both Start and On Enter State to the Cache input, as they will never both get called.