OnTick delegate and other tick optimization question

Hey all!

As many of us, I’m using *Tick *and *TickComponent *a lot in my game. I have several question about tick optimization, hope we can find the best answers for our games.

1) Sometimes, when something happens in game, I don’t need to trigger some parts of the code in my Tick function. How to handle this best in terms of optimization?

Do I need to use *boolean *for checking it every tick:



void ATestActor::Tick(float DeltaTime)
{
    if (bRunning)
        //Do something
}


Or it’s better to create *OnTick *delegate and manually bind and unbind to him various functions?



void ATestActor::Tick(float DeltaTime)
{
    OnTick.Broadcast();
}


What makes code more optimized in terms of code execution?

I in Unity heard that it’s better to use *Coroutines *with loops rather than tick, if some code need to be triggered every *DeltaTime *but condition based. I don’t know the way of doing that better in Unreal.

2) What is less time consuming - calling function in tick:



void ATestActor::Tick(float DeltaTime)
{
    SomeFunction()
}

void ATestActor::SomeFunction()
{
    //Do something
}


or straight code, placed inside the tick?



void ATestActor::Tick(float DeltaTime)
{
    //Do something
}


As far as I know, packed part of the code in .dll with that SomeFunction() may be placed in different place unlike Tick(float DeltaTime), so it makes a little bit time consuming to jump between these two functions. But placing straight code in Tick may made code a less read-friendly and more messy. What the better way of handling this?


void ATestActor::Tick(float DeltaTime)
{
        SomeFunction()
}

I pretty much do that everywhere, personal choice.
Except my Blueprints are FSMs, and every time I “change state”, “SomeFunction()” automatically becomes a different function called from Tick…

i.e: Tick() -> OnUpdateWalk(), Tick() -> OnUpdateRun(), etc.

So I don’t really have to keep changing Tick’s body ever, adding “if this” or “if that” to Tick().

Bruno, how you’re changing SomeFunction() to different kind of function? Like in your example, how OnUpdateWalk() becomes OnUpdateRun()? Or each one of your states have unique Tick()?

P.S. FSM is great plugin, always wanted to have a look on it. Definitely will buy it, when I will have more free time! Thanks for your work!

I use “Reflection” :slight_smile:
For example, the only code I run inside “Tick()”, and never change it, is like this:



if (AutoFlowFSM == true) {
    FString N_State = States[id].Name.ToString();

    FName NID_State = *(FString("On Update ")+N_State);

    UFunction* Function = FindFunction(NID_State);

    FSM_UpdateArguments.StateID = StateID;
    FSM_UpdateArguments.StateTime = StateTime;

    if (Function) {
        ProcessEvent( Function, &FSM_UpdateArguments );
    }
}


When I need to halt everything, I set “AutoFlowFSM” to false.
In that case “N_State” could be anything from my states list, it’s selected using the “id” index, so the only thing replicated over the network is the "id" number.
FSM_UpdateArguments” is a struct the component later can read the function call results from, doing extra stuff somewhere else.

That is slower than simply calling “On Update Something” directly (because the call to FindFunction), but in other hand the only condition I am forced to check is if that “AutoFlow” is true, reducing the boilerplate inside Tick when the code grows; Then I don’t have to recompile the code every time someone create/destroy/modify “On Update Something” functions… they can create those functions on Blueprint Editor and I don’t have to know if the function exists in C++ or not.

So, I’m using it on classes that need replication the most, random level actors I don’t like to use the FSM Component if the logic is simple, would be “overkill”.
Focusing on OnTick.Broadcast() is a good idea, but debugging this becomes convoluted when your project grows, if you are the only programmer using the classes, I think I would do it this way.

How bad is it performance-wise to have one or more branches inside a tick? And would implemeting a “select” of sorts to avoid the branch be worth it?

I don’t think I would “care” about that unless you’re talking about millions of calls…
Compilers are very elusive, they optimize a ton of things;

I usually focus more on workflow and productivity instead of going psycho on micro performance management.

some interesting related topic:

+100000000 to this. I see far too many people attempting to micromanage their code when it comes to performance, especially in the early stages of development. Native Tick is considerably faster than Tick within blueprints, and even in blueprint do I rarely find that I absolutely need to optimize my code. A recent case was when I was prototyping in blueprints: running ~50 actors doing some moderately complex calculations every tick, tested on my school laptop (i5-8250U 3.1GHz). FPS capped at 120, rarely hit below ~100 FPS.

I’m not saying that micromanaging your code is necessarily a bad thing, but when you’re sacrificing productivity for less than 10 to 15 FPS, that’s when I would take a step back and ask myself if it is worth it.

Personally, it wouldn’t be worth it to me in most cases. Having multiple functions (MyAnimationTick, MyWeaponTick, UpdatePlayerRotation, etc) within tick works just fine for me, however if your Tick is getting filled up to the point that this question should be asked, then maybe an alternative to relying on tick for them is in order.