SetActorLocation() update immediate or next physics tick?

Hi all,

This is probably a basic question, but it seems to slip past me.

When we do SetActorLocation() on an actor with just one static mesh component(with physics disabled, collision enabled), will the location update immediately or during next physics tick?

For Eg;

for( auto x:{1,2,3.....100})
{
    MyActor->SetActorLocation(FVector(x, x+1, 0));
}

I’m doing this during BeginPlay(). Will actor location change instantly 100 times or they are all stacked up in some queue and executed one by one during physics ticks?

Also, if they update instantly, does the collision also update? In my case, I don’t get a valid collision response from the actor when I’m doing it like above.

Cheers!

Transforms and collision info will be updated all during SetActorLocation() (aka, immediatelly).

Moving actors isn’t particularly cheap, when you consider overlap events and potential reinsertion into the collision broadphase. The less you do it the better in general.

Disabling overlap events when you don’t need them is a good way to get a lot of performance back.

@TheJamsh, that’s interesting (that collision is also updated immediately), cuz in my case, I’m moving my actor without sweep and the return boolean is not as expected (i.e. false when a collision occurs).
Indeed, I’ve disabled generate overlap and hit events as well, as I do not need them for collision checking. However, I’m curious. if I do enable hit events, will they be generated immediately 100 times or during physics ticks?

@AntiGravity , I’m using the above method to check for collision at certain locations in my map before the game starts so as to remember beforehand where in the map collision occurred and use that later during the game. Is the above method a bad approach to accomplish this?
I’m just moving one actor for now during BeginPlay(), so that’d be in just one frame. For now, I don’t have to deal with multiple actors at once :smiley:

Also, I do not want sweep during this movement as I’m using this method to check for collision at a particular location. Not sure what I’m missing here.

You won’t get hit events from kinematic actors, these are only ever generated by the physics engine from physics-simulating actors/rigid bodies.

It’s expected behaviour to return false if you move the actor without sweeping, because that just means you’re setting it’s transform directly without caring whether there is blocking collision in the way. If you want to stop the actor short of collision (as best it can anyway), then you need to sweep, which will also output the sweep “contact” collision if there is one after resolving penetration.

Note that also, you are only sweeping the Root component. The engine will not resolve penetration for a heirachy of components attached together, but when their transforms are updated, they will update their own overlaps.

You will get overlap events, which are updated all at once after the transform has been set. These can be very expensive, because overlaps will be updated (assuming they are enabled) on both the component(s) and actor(s) you moved, as well as the component(s) and actor(s) that they overlap after being moved (both need to generate overlap events to get any events at all).

1 Like

Hmm, I thought if I don’t sweep, the collision would just be checked at the required set location. Because, I don’t want to have collision detected in the path to my set location. In this case, how do I then go about checking collision at a particular location?

My case has just an actor with a single static mesh component (this is the root component). So, I’m not worried about performance impact as I also do not want overlap events.

If you want to check whether there is collision there before you move it, then you would need to do a manual collision overlap test for blocking collision at the target location first. Using something like GetWorld()->OverlapBlockingTestByProfile();

However those queries only support basic shapes (Box, Sphere, Capsule) and not convex/triangle collision.

If you wanted to test body instances using their actual geometry, you can use FBodyIntance::OverlapMulti to check for blocking overlaps at a given transform (a static mesh only has one body instance which you can get from the primitive component)

1 Like

@TheJamsh, Thanks for the suggestions! Most likely I have simple collision enabled on my meshes, so I’m hoping GetWorld()->OverlapBlockingTestByProfile() should do the job. I’ll give them a try.