82 lines
3.7 KiB
C#
82 lines
3.7 KiB
C#
using UnityEngine;
|
|
|
|
namespace BehaviorDesigner.Runtime.Tasks.Movement
|
|
{
|
|
[TaskDescription("Wander using the Unity NavMesh.")]
|
|
[TaskCategory("Movement")]
|
|
[HelpURL("https://www.opsive.com/support/documentation/behavior-designer-movement-pack/")]
|
|
[TaskIcon("c8e612848487a184f9090d416c932c47", "cc64e7434e679324c8cb39430f19eda8")]
|
|
public class Wander : NavMeshMovement
|
|
{
|
|
[Tooltip("Minimum distance ahead of the current position to look ahead for a destination")]
|
|
[UnityEngine.Serialization.FormerlySerializedAs("minWanderDistance")]
|
|
public SharedFloat m_MinWanderDistance = 20;
|
|
[Tooltip("Maximum distance ahead of the current position to look ahead for a destination")]
|
|
[UnityEngine.Serialization.FormerlySerializedAs("maxWanderDistance")]
|
|
public SharedFloat m_MaxWanderDistance = 20;
|
|
[Tooltip("The maximum number of degrees that the agent can turn when wandering")]
|
|
public SharedFloat m_MaxWanderDegrees = 5;
|
|
[Tooltip("The minimum length of time that the agent should pause at each destination")]
|
|
[UnityEngine.Serialization.FormerlySerializedAs("minPauseDuration")]
|
|
public SharedFloat m_MinPauseDuration = 0;
|
|
[Tooltip("The maximum length of time that the agent should pause at each destination (zero to disable)")]
|
|
[UnityEngine.Serialization.FormerlySerializedAs("maxPauseDuration")]
|
|
public SharedFloat m_MaxPauseDuration = 0;
|
|
[Tooltip("The maximum number of retries per tick (set higher if using a slow tick time)")]
|
|
[UnityEngine.Serialization.FormerlySerializedAs("targetRetries")]
|
|
public SharedInt m_TargetRetries = 1;
|
|
|
|
private float m_PauseTime;
|
|
private float m_DestinationReachTime;
|
|
|
|
// There is no success or fail state with wander - the agent will just keep wandering
|
|
public override TaskStatus OnUpdate()
|
|
{
|
|
if (HasArrived()) {
|
|
// The agent should pause at the destination only if the max pause duration is greater than 0
|
|
if (m_MaxPauseDuration.Value > 0) {
|
|
if (m_DestinationReachTime == -1) {
|
|
m_DestinationReachTime = Time.time;
|
|
m_PauseTime = Random.Range(m_MinPauseDuration.Value, m_MaxPauseDuration.Value);
|
|
} else if (m_DestinationReachTime + m_PauseTime <= Time.time) {
|
|
// Only reset the time if a destination has been set.
|
|
if (TrySetTarget()) {
|
|
m_DestinationReachTime = -1;
|
|
}
|
|
}
|
|
} else {
|
|
TrySetTarget();
|
|
}
|
|
}
|
|
return TaskStatus.Running;
|
|
}
|
|
|
|
private bool TrySetTarget()
|
|
{
|
|
var direction = transform.forward;
|
|
var attempts = m_TargetRetries.Value;
|
|
Vector3 destination;
|
|
while (attempts > 0) {
|
|
direction = Quaternion.Euler(0, Random.Range(-m_MaxWanderDegrees.Value, m_MaxWanderDegrees.Value), 0) * direction;
|
|
destination = transform.position + direction.normalized * Random.Range(m_MinWanderDistance.Value, m_MaxWanderDistance.Value);
|
|
if (SamplePosition(ref destination)) {
|
|
SetDestination(destination);
|
|
return true;
|
|
}
|
|
attempts--;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Reset the public variables
|
|
public override void OnReset()
|
|
{
|
|
m_MinWanderDistance = 20;
|
|
m_MaxWanderDistance = 20;
|
|
m_MaxWanderDegrees = 5;
|
|
m_MinPauseDuration = 0;
|
|
m_MaxPauseDuration = 0;
|
|
m_TargetRetries = 1;
|
|
}
|
|
}
|
|
} |