Hello,
I’m working on an airport game and I need to perform backward movement for the entity I’m creating. Since the aircraft is full ECS, I’m using the custom authoring component for the Follower Entity Agent from this repo :
https://gitlab.com/lclemens/AStarPfpBenchmark
I managed my way in the JobMoveAgent where I allow the FollowerEntity to move my agent when I decide to (I have custom physics for the airborn part).
Unfortunately, I’m unable to have it going backward. Here is what I tried :
- Setting a negative follower.speed. As I understand, we always want a positive move speed meaning that we move towards the target point.
- Tricking the system with a false currentRotation using a +180° rotation.
The last one is working partially. I managed to have to aircraft with the tail facing the target point. However, it seems that it cannot reach the target speed with some jittering when the rotation is finished (i.e, in straight line) (which is not hapenning when going forward). Here is the modification I made in JobMoveAgent :
// multiply rotation by 180 on y axis
var backRotation = transform.Rotation * Quaternion.Euler(0, 180f, 0);
var currentRotation = movementPlane.value.ToPlane(backRotation);
and,
transform.Rotation = movementPlane.value.ToWorldRotation(newInternalRotation + state.rotationOffset + state.rotationOffset2) * Quaternion.Euler(0, 180f, 0);
Does anyone suceeded in getting an agent to move backward ?
Thanks
- A* version: 5.3.3
- Unity version: 6000.0.23f1
Well, I guess the approach here depends on why you want to move backwards. For an airport game, I’m assuming the reversing of the aircraft. In that case, you may just want to control rotation manually (as you are) and then set a path to the backwards location? So it’s moving forward along the path but it’s visually reversing.
What’s your use case?
That’s exactly the case I want to implement. However I tried to get it work just by modifying the JobMoveAgent. I managed again to get the correct rotation by changing the resolvedMovement.targetRotation with my own value but then a strange behaviour happens. The entity start a 180° turns and start to move in the opposite direction regarding the path. When checking for the internal rotation value, it seems to be desynchronised with the current entity which is kinda weird. This desync happens at the moment the entity is aligned with the target making me think that a line somewhere really prevent the entity to move in backward direction (the forward vector of the entity must always be in the direction of the path, even leading to a weird backward movement, increasing the distance to the target).
This led me to create a custom rotation script. Again, I managed to get the correct rotation but the entity will not move anymore using the JobMoveAgent script. I tested by applying a PhysicsVelocity.ApplyLinearImpulse in the backward direction but again nothing happens. However, when using the same function in the forward direction, the entity start to move. So I’m 99.99% sure that somewhere a line prevent the movement if it’s not in the forward of the entity.
I will try to deactive the SimulateMovement component and go full custom but that’s kinda sad since the A* movement are really good for my application.
Would you be able to provide a video of this happening? I think I’d need to see it in action to get a better understanding of what’s going on and possibly why.
Sure, I managed to recreate this behaviour
https://youtu.be/RF5fJSopOIM
On the video you can see the current calculated Path. The entity is rotating toward it. However the rotation does not stop and continue until it face the target direction. When align, it starts moving backward. I made a change in the destination to show you the behaviour. At soon as the target is in the back of the aircraft, it will proceed to a 180 turn to face the target.
Here is the line I modified in ResolveRotation() from JobMoveAgent:
var heading = 0f;
if (math.degrees(math.Euler(transform.Rotation).y) < 0)
{
heading = (math.degrees(math.Euler(transform.Rotation).y) + 360) % 360;
}
else
{
heading = (math.degrees(math.Euler(transform.Rotation).y)) % 360;
}
var backRotation = transform.Rotation * Quaternion.Euler(0, 180f, 0);
var currentRotation = movementPlane.value.ToPlane(backRotation);
currentRotation = math.radians((math.degrees(currentRotation) + 360) % 360);
var currentInternalRotation = currentRotation - state.rotationOffset - state.rotationOffset2;
var headingError = heading - math.degrees(currentInternalRotation);
//Debug.Log("Heading Error : " + headingError);
float3 dir = math.normalize(state.nextCorner - transform.Position);
float targetRotation = 0;
if (dir.x > 0)
{
targetRotation = 90 - math.degrees(math.atan2(dir.z, dir.x));
}
else if (dir.x < 0)
{
targetRotation = 270 - math.degrees(math.atan2(dir.z, dir.x));
}
else if (dir.x == 0 && dir.z > 0)
{
targetRotation = 0;
}
else if (dir.x == 0 && dir.z < 0)
{
targetRotation = 180;
}
targetRotation = targetRotation + 180;
var deltaRotation = math.clamp(math.radians((targetRotation - heading + 540) % 360), -resolvedMovement.rotationSpeed * dt, resolvedMovement.rotationSpeed * dt);
and these line from MoveWithoutGravity() :
var localDir = movementPlane.value.ToPlane(resolvedMovement.targetPoint - transform.Position);
if (movementSettings.isPushBack)
{
localDir = -localDir;
}
I tested some other options :
- Removing the + 180 from targetRotation → Same behaviour
- Removing the -localDir change → Not the correct results either
Hope with the video it is clear for you now and thank you for your help on this subject !
When I watched the video I was sorta confused because I’m under the impression that the backwards movement was the desire- but in that situation it should be moving foward towards the path? Like, the video you sent it’s not supposed to be going backwards? I am most likely misunderstanding the intention here, very sorry!
That’s the problem ! I made it go backward but now it’s moving away from the target when, as per the code, it should not with the small change I made to it ! And I really don’t understand why it is doing this with these little change.
That’s why I suspect some other function embedded in A*PF that mess with the movement I want to make. I think going full custom will work, I already managed to get a correct rotation, now I need to figure out the translation.
Unsure if this is on your radar, but if you’re looking to circumvent everything by using your own movement script, you can actually make one that works with Astar. Check out this part of the documentation for more information.