이번에는 Seek, Patrol 부분을 구현해 보았다.
public class Seek : Node
{
private EnemyRobotBT ebt;
private float seekWaitDuration = 3;
private float seekWaitTimer;
private Vector3 seekPosition;
public Seek(BehaviorTree bt) : base(bt)
{
ebt = (EnemyRobotBT)bt;
seekWaitTimer = seekWaitDuration;
}
public override NodeState Evaluate()
{
if (!ebt.ai.seekPointReached) seekPosition = ebt.ai.lastEnemyPosition;
float remainDistance = Vector3.Distance(ebt.ai.navAgent.transform.position, seekPosition);
if (remainDistance <= ebt.ai.navAgent.stoppingDistance * 2)
{
seekWaitTimer -= Time.deltaTime;
if (seekWaitTimer < 0)
{
seekWaitTimer += seekWaitDuration;
seekPosition = CreateRandomPoint();
ebt.ai.seekPointReached = true;
}
}
bool success = ebt.ai.StartMove(seekPosition);
DebugExtension.DebugWireSphere(seekPosition, Color.green, 0.5f);
return success ? NodeState.RUNNING : NodeState.FAILURE;
}
private Vector3 CreateRandomPoint()
{
Vector3 randomPoint = Random.insideUnitSphere * 10 + ebt.ai.lastEnemyPosition;
NavMesh.SamplePosition(randomPoint, out NavMeshHit hit, 10, NavMesh.AllAreas);
return hit.position;
}
}
EnemyAI 가 플레이어를 쫒아오다가 탐지 범위에서 벗어났을 때,
public class Patrol : Node
{
private EnemyRobotBT ebt;
private float patrolWaitDuration = 3;
private float patrolWaitTimer;
private int current = 0;
private int reverse = -1;
public Patrol(BehaviorTree bt) : base(bt)
{
ebt = (EnemyRobotBT)bt;
patrolWaitTimer = patrolWaitDuration;
}
public override NodeState Evaluate()
{
int count = ebt.ai.patrolPoints.transform.childCount;
Vector3 targetPosition = ebt.ai.patrolPoints.transform.GetChild(current).transform.position;
float remainDistance = Vector3.Distance(ebt.ai.navAgent.transform.position, targetPosition);
if (remainDistance <= ebt.ai.navAgent.stoppingDistance)
{
patrolWaitTimer -= Time.deltaTime;
if (patrolWaitTimer < 0)
{
patrolWaitTimer += patrolWaitDuration;
if (current == 0 || current == count - 1) reverse *= -1;
current += reverse;
}
}
bool success = ebt.ai.StartMove(targetPosition);
return success ? NodeState.RUNNING : NodeState.FAILURE;
}
}
지정된 PatrolPoint 들을 순찰한다.
public class IsSeekLevelHigh : Node
{
private EnemyRobotBT ebt;
private float threshold = 60;
public IsSeekLevelHigh(BehaviorTree bt) : base(bt)
{
ebt = (EnemyRobotBT)bt;
}
public override NodeState Evaluate()
{
return ebt.ai.seekLevel.currentLevel > threshold ? NodeState.SUCCESS : NodeState.FAILURE;
}
}
public class Walk : Node
{
private EnemyRobotBT ebt;
public Walk(BehaviorTree bt) : base(bt)
{
ebt = (EnemyRobotBT)bt;
}
public override NodeState Evaluate()
{
ebt.ai.inputHandler.isWalk = true;
ebt.ai.navAgent.speed = ebt.ai.inputHandler.maxSpeed / 3;
return NodeState.SUCCESS;
}
}