I have a complex issue that involves networking, and am trying to understand better how the internals of A* Pathfind Project work. Just for context, what I am seeing is that when a host has a client connected to it, if I set the destination of a fast moving agent to Infinity it will just keep sliding in the direction it was moving when set. (This is all on the host)
Syncing the entity position with the GO transform is handled on our own component that syncs the GO transform with components as well.
The weird thing I am seeing is that the position of the LocalTransform ecs component of the entity keeps moving in the direction it was going as well. I have double checked that nothing else in the project ever sets the followerEntity.position property or ever access a LocalTransform even. I attached a screenshot of the configuration of the FollowerEntity that is doing the sliding.
So I guess my question would be if there is any scenario that you can think where the entity would be matching the position of the transform instead of the transform matching the entity? Or the entity keep moving in a direction (not along a path) even when the destination has been cleared?
I’ll tag Aron to look at this, as the underlying ECS for FollowerEntity isn’t my strong suit and I wouldn’t want to lead you wrong. He’ll get back to you when he can but feel free to document any other findings for others and myself.
Totally understandable, thank you will do!
Okay I have managed to repliably reproduce it in a clean project without any networking! It does appear to be a A* bug. But also very possible that it is an intended behavior that I just don’t understand.
Steps to reproduce:
- Create a plane and a AStar Recast graph (all default settings)
- Create a empty GameObject at some place on the graph
- Create a second GameObject with a FollowerEntity and provided
Stunner component. (Set the FollowerEntity speed to 1 for easier testing)
- Assign the empty GameObject to the
Target field of Stunner component.
- Enter playmode and see the FollowerEntity move towards object assigned to the
Target field.
- Toggle the
Is Stunned bool to true in the Stunner while the FollowerEntity is moving and see that it stops and the logged Speed value is 0.
- Toggle
Is Stunned back to false and set the Speed Modifier field in Stunner to 1.5.
- Toggle
Is Stunned back to true while the FollowerEntity is moving, and see that it continues to move and the logged Speed stays at 1.
The cutoff value for Speed Modifier before it would keep sliding seemed to change, maybe per-project. In the fresh project it seemd to be closer to 1.15 while in the full project it was around 1.46. I have included a video of it happening as well, and the component I used to repro it.
Again it is possible it is a behavior I am not aware of. Great to know if that is the case or if you are able to repro it as well.
using System;
using System.Collections;
using Pathfinding;
using Pathfinding.ECS;
using Unity.Entities;
using Unity.Transforms;
using UnityEngine;
public class Stunner : MonoBehaviour {
private FollowerEntity _followerEntity;
[SerializeField] private Transform _target;
[SerializeField] private float _speedModifier = 1;
[SerializeField] private bool _isStunned = false;
private void OnEnable() {
_followerEntity = GetComponent<FollowerEntity>();
StartCoroutine(AddCallback());
}
IEnumerator AddCallback()
{
yield return new WaitUntil(() => _followerEntity.entityExists);
_followerEntity.movementOverrides.AddBeforeMovementCallback(BeforeMovement);
Debug.Log("Callback added");
}
private void BeforeMovement(Entity entity, float dt, ref LocalTransform localTransform, ref AgentCylinderShape shape, ref AgentMovementPlane movementPlane, ref DestinationPoint destination, ref MovementState movementState, ref MovementSettings movementSettings, ref MovementControl movementControl, ref ResolvedMovement resolvedMovement) {
var oldSpeed = resolvedMovement.speed;
resolvedMovement.speed *= _speedModifier;
Debug.Log($"Speed: {oldSpeed}, edit: {resolvedMovement.speed}");
}
private void Update() {
if (!_followerEntity.entityExists)
return;
if (_isStunned) {
_followerEntity.isStopped = true;
_followerEntity.destination = Vector3.positiveInfinity;
}
else if (_target != null) {
_followerEntity.isStopped = false;
_followerEntity.destination = _target.position;
}
}
}
These are great repro steps, highly appreciated. I tagged him in this so he’ll get to it when he can!
Any update? I was going to ask if we should use canMove to force the stopping but from the docs is seems like isStopped should be enough.
Nothing yet, Aron’s been pretty busy. I’d recommend you give your idea a try- worst case scenario it doesn’t work and you post that, then others can hopefully see that down the road if they find this post.