using BehaviorDesigner.Runtime.Tasks.EnemyAI;
using UnityEngine;
using UnityEngine.AI;
namespace BehaviorDesigner.Runtime.Tasks.Movement
{
[TaskDescription("Wander using the Unity NavMesh.")]
[TaskCategory("YLSJ")]
[HelpURL("http://www.opsive.com/assets/BehaviorDesigner/Movement/documentation.php?id=9")]
[TaskIcon("Assets/Behavior Designer Movement/Editor/Icons/{SkinColor}WanderIcon.png")]
public class ActionAreaWander : NavMeshMovementBase
{
[Tooltip("目标Object")]
public SharedTransform targetObject;
[Tooltip("检测目标的层级")]
public LayerMask objectLayerMask;
[Tooltip("观察角度")]
public SharedFloat viewAngle = 360;
[Tooltip("观察距离")]
public SharedFloat viewDistance = 10;
[Tooltip("最小游荡距离")]
public SharedFloat minWanderDistance = 3;
[Tooltip("最大游荡距离")]
public SharedFloat maxWanderDistance = 7;
[Tooltip("最小游荡持续时间")]
public SharedFloat minWanderDuration = 2;
[Tooltip("最大游荡的持续时间")]
public SharedFloat maxWanderDuration = 5;
[Tooltip("The amount that the agent rotates direction")]
public SharedFloat wanderRate = 2;
[Tooltip("游荡的类型 0静止1随机 2路径点巡逻,配合WanderPoints使用")]
public SharedInt wanderType = 1;
[Tooltip("路径点 当wanderType=2时 使用")]
public SharedTransformList wanderPoints = null;
private int pointIndex = 0;
private Vector3 movePos = Vector3.zero;
private Vector3 livePos = Vector3.zero;
private float curWanderTime = 0;
///
/// 出生最大距离
///
private float liveAlertDistance = 0;
private BehaviorTree behaviorTree = null;
///
/// 是否静止中
///
private bool bIdle = true;
// 是否移动中
private bool bMove = false;
///
/// 路径点顺序/倒叙
///
private bool bPointAdd = true;
///
/// 是否赶往出生点
///
private bool bToLive = false;
private Role role = null;
public override void OnAwake()
{
base.OnAwake();
livePos = transform.position;
behaviorTree = gameObject.GetComponent();
}
public override void OnStart()
{
base.OnStart();
role = GetComponent();
liveAlertDistance = (float)behaviorTree.GetVariable("liveAlertDistance").GetValue();
if (m_NavMeshAgent.component.isOnNavMesh)
{
m_NavMeshAgent.component.isStopped = false;
}
float liveDis = Vector3.Distance(transform.position, livePos);
// 距离出生点超过最大范围 回到出生点
if (liveDis >= liveAlertDistance)
{
bToLive = true;
}
else
{
bToLive = false;
}
curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value);
bIdle = true;
}
// There is no success or fail state with wander - the agent will just keep wandering
public override TaskStatus OnUpdate()
{
if (FindTarget(m_NavMeshAgent.component.transform) != null)
{
return TaskStatus.Success;
}
if (wanderType == null)
{
return TaskStatus.Running;
}
// 移动中
if (bMove)
{
// 到达最小停止距离
if (m_NavMeshAgent.component.isOnNavMesh && m_NavMeshAgent.component.remainingDistance <= m_NavMeshAgent.component.stoppingDistance)
{
bMove = false;
// 静止
bIdle = true;
curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value);
if (bPointAdd)
{
pointIndex++;
}
else
{
pointIndex--;
}
}
}
// 静止中
else if (bIdle)
{
// 当前游荡时间
curWanderTime -= Time.deltaTime;
if (curWanderTime <= 0)
{
bToLive = false;
curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value);
// 游荡类型
switch (wanderType.Value)
{
case 1:
{
SetRandomPos();
}
break;
case 2:
{
SetTargetPos();
}
break;
default:
{
// BOSS一直追人
if (role.roleType == RoleType.Boss)
{
SetRandomPos();
}
else
{
// 随机移动
SetRandomPos();
}
}
break;
}
}
}
return TaskStatus.Running;
}
public override void OnEnd()
{
base.OnEnd();
}
///
/// 设置目标点
///
private void SetTargetPos()
{
if (pointIndex < 0)
{
pointIndex = 1;
bPointAdd = true;
}
if (pointIndex >= wanderPoints.Value.Count)
{
pointIndex = wanderPoints.Value.Count - 2;
bPointAdd = false;
}
if (pointIndex >= 0 && pointIndex < wanderPoints.Value.Count)
{
movePos = wanderPoints.Value[pointIndex].position;
SetDestination(movePos);
bMove = true;
bIdle = false;
}
}
///
/// 设置随机点
///
private void SetRandomPos()
{
int randomVal = Random.Range(0, 100);
// 随机
if (randomVal >= 50)
{
var direction = transform.forward + Random.insideUnitSphere * wanderRate.Value;
movePos = livePos + direction.normalized * Random.Range(minWanderDistance.Value, maxWanderDistance.Value);
SetDestination(movePos);
bMove = true;
bIdle = false;
}
}
public Transform FindTarget(Transform selfTransform)
{
if (bToLive)
{
return null;
}
Transform objectFound = null;
var hitColliders = Physics.OverlapSphere(selfTransform.position, viewDistance.Value, objectLayerMask);
if (hitColliders != null)
{
float minAngle = 360;
for (int i = 0; i < hitColliders.Length; ++i)
{
if (hitColliders[i].gameObject.activeSelf == false)
{
continue;
}
Role role = hitColliders[i].gameObject.GetComponent();
if (role == null || role.isDie)
{
continue;
}
Vector3 v3Dir = hitColliders[i].transform.position - selfTransform.position;
v3Dir.Normalize();
float angle = Vector3.Angle(selfTransform.forward, v3Dir);
if (angle <= viewAngle.Value * 0.5f)
{
if (angle < minAngle)
{
minAngle = angle;
objectFound = hitColliders[i].transform;
}
}
if (role.gameObject.layer == LayerMask.NameToLayer("Player"))
{
// 创建对话气泡框
Role self = this.gameObject.GetComponent();
if (self.bubType == YLBattle.SpawnPoint.BubbleType.Sight && !self.bubEnable)
{
SceneBubbleWindow buCmpt = self.gameObject.AddComponent();
buCmpt.SetContent(self.bubStr);
buCmpt.SetEnableType(self.bubType);
self.bubEnable = true;
}
}
}
}
targetObject.Value = objectFound;
return objectFound;
}
// Reset the public variables
public override void OnReset()
{
wanderRate = 2;
minWanderDistance = 3;
maxWanderDistance = 7;
minWanderDuration = 2;
maxWanderDuration = 5;
}
}
}