Hi again and sorry for the late response. I’ll try to provide as much info as possible.
I’m using Behavior Designer by Opsive, and in its most basic node I’m reading the steering direction of the FollowerEntity to manually set the movement through the joysticks as if a player was moving it.
if (_destinationSetter.target == null && m_Target.Value != null)
{
_destinationSetter.target = m_Target.Value.transform;
}
var direction = (_agent.steeringTarget - transform.position).normalized;
if (_agent.reachedDestination || _agent.reachedEndOfPath || _agent.isTraversingOffMeshLink || direction == Vector3.zero)
{
_controller.SetDirectionAndRotation(Vector3.zero);
return TaskStatus.Success;
}
CheckMoveSpeed();
if (_blockToWalkSpeed)
{
direction.x = Mathf.Clamp(direction.x, -_controller.m_playerKinematicModel.RunningInputThreshold, _controller.m_playerKinematicModel.RunningInputThreshold);
direction.z = Mathf.Clamp(direction.z, -_controller.m_playerKinematicModel.RunningInputThreshold, _controller.m_playerKinematicModel.RunningInputThreshold);
}
_controller.SetDirectionAndRotation(direction);
return TaskStatus.Running;
As soon as the AI starts to move through the link, I send an event to the Behavior Tree with relevant information, such as which platform is jumping towards (for analyzing its state to prepare for the jump) or where the link ends.
[SerializeField]
private GameObject _platform;
private InputController _controller;
void OnEnable() => GetComponent<NodeLink2>().onTraverseOffMeshLink = this;
void OnDisable() => GetComponent<NodeLink2>().onTraverseOffMeshLink = null;
public IOffMeshLinkStateMachine GetOffMeshLinkStateMachine(AgentOffMeshLinkTraversalContext context)
{
_controller = context.gameObject.GetComponent<AIController>();
_controller.SetDirection(Vector3.zero);
context.gameObject.GetComponent<BehaviorDesigner.Runtime.BehaviorTree>().SendEvent<object, object, object>("Link", context.link.relativeStart, context.link.relativeEnd, context.link.link.tag.value);
context.gameObject.GetComponent<BehaviorDesigner.Runtime.BehaviorTree>().SetVariableValue("movingPlatform", _platform);
return this;
}
IEnumerable IOffMeshLinkStateMachine.OnTraverseOffMeshLink(AgentOffMeshLinkTraversalContext ctx)
{
yield return null;
}
The Behavior Tree then will check through the tag which kind of movement the AI wants to do and, in this case since it’s jumping to a platform, it will wait for the platform to be close and idle (we’re now not reading the steering target, simply setting the direction of the inputs to 0), it will then jump to the platform and finish the sequence, starting again from the top for the node that reads the steering target.
public override TaskStatus OnUpdate()
{
if (!_controller.isActiveAndEnabled)
{
return TaskStatus.Inactive;
}
if (m_stopWhenClose.Value)
{
var position = new Vector3(transform.position.x, 0, transform.position.z);
// _stopPoint will be the position of the platform, ignoring its Y axis.
float distance = Vector3.Distance(position, _stopPoint);
if (distance <= m_stopDistance.Value)
{
_controller.SetDirection(Vector3.zero);
}
}
if (_controller.m_KinematicCharacterMotor.GroundingStatus.IsStableOnGround)
{
if (m_stopWhenClose.Value)
{
_controller.SetDirection(Vector3.zero);
}
return TaskStatus.Success;
}
return TaskStatus.Running;
}
When the agent lands and we once again read it’s steering target it directs the controller back towards the beginning of the link, even though it is already on the platform and it should use the second link to get to its target, which would restart the same logic again (wait for the platform to stop, jump to the end of the link, and start back to move close to your target). Through setting breakpoints it seems that the second link does not start, so I’m unsure if I’m doing something wrong here.
Thanks for your help and once again sorry for taking a bit on providing more info!