using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using ActionGameFramework.Health;
using Core.Health;
using Core.Utilities;
using DG.Tweening;
using KTGMGemClient;
using TMPro.Examples;
using TowerDefense.Affectors;
using TowerDefense.Agents.Data;
using TowerDefense.Economy;
using TowerDefense.Level;
using TowerDefense.Nodes;
using UnityEngine;
using UnityEngine.AI;
namespace TowerDefense.Agents
{
// 预计算移动的方位.
public enum EAgentMovDir
{
Start,
XPositive,
XNegative,
ZPositive,
ZNegative,
End
}
///
/// 每一个Agent发布到场景内时设置的数据
///
public struct AgentSetData
{
public float speed;
public float hp;
}
///
/// An agent will follow a path of nodes
/// NavMeshAgent和AttackAffector是必须得加入的EntityNode.
///
[RequireComponent(typeof(NavMeshAgent)), RequireComponent(typeof(AttackAffector))]
public abstract class Agent : Targetable
{
///
/// A means of keeping track of the agent along its path
///
public enum State
{
///
/// When the agent is on a path that is not blocked
///
OnCompletePath,
///
/// When the agent is on a path is blocked
///
OnPartialPath,
///
/// When the agent has reached the end of a blocked path
///
Attacking,
///
/// For flying agents, when they move over obstacles
///
PushingThrough,
///
/// When the agent has completed their path
///
PathComplete
}
///
/// Event fired when agent reached its final node
///
public event Action destinationReached;
///
/// Position offset for an applied affect
/// 这个主要是用于AgentEffect相关的类,给当前的Agent加相关的效果,移动变慢,加速等等。
///
public Vector3 appliedEffectOffset = Vector3.zero;
///
/// Scale adjustment for an applied affect
/// 加强效果对应的Scale数据
///
public float appliedEffectScale = 1;
///
/// 当前的Agent对应的healthBar.
///
public HealthVisualizer healthBar;
///
/// 如果不为空,则播放当前的particle.
///
public ParticleSystem spawnParticle;
public AgentSetData mAgentData;
//public Textur
///
/// The NavMeshAgent component attached to this
/// 这个,Unity内比较核心的类
///
protected NavMeshAgent m_NavMeshAgent;
///
/// The Current node that the agent must navigate to
///
protected Node m_CurrentNode;
///
/// 修改当前的NavMeshAgent移动模式,修改为纯手动移动
///
protected Node m_NextNode;
///
/// 记录初始化的位置和Node,用于重设当前Agent的位置
///
protected Node initNode;
protected Vector3 initPos;
///
/// Reference to the level manager
///
protected LevelManager m_LevelManager;
protected EndlessLevelManager endlessLevelManager;
///
/// Stores the Destination to the next node so we don't need to get new random positions every time
///
protected Node m_Destination;
///
/// 每次移动从SrcPosition到m_Destination.
///
protected Vector3 m_SrcPosition;
///
/// 每次切换Node,都会重新计算移动方向,用于中间状态时,更快速的计算移动数据。
///
protected EAgentMovDir moveDir;
///
/// 移动速度,暂时从navMeshAgent中获取.
///
protected float fMoveSpeed;
protected float MoveStopTime = 0.0f;
protected ParticleSystem MoveStopEffect = null;
///
/// 距离目标的最终距离.
///
protected float m_DisToDestination;
///
/// 当前Agent的默认Scale数据
///
protected Vector3 mDefaultScale;
///
/// 当前小怪对应的掉落数据
///
protected LootDrop mLootDrop;
///
/// 每一个Node加一个超长距离值
///
protected readonly float NODE_DIS = 1000f;
///
/// 当前Agent的开始Yval,用于标注层级显示.
///
protected float mStartYVal;
protected float mStartZVal;
///
/// 动画器.
///
public Animator ActionAnimator;
protected AnimationClip[] clips;
protected bool bInDeathAct = false;
///
/// 原地罚站
///
///
public bool CanMove { get; set; } = true;
///
/// Gets the attached nav mesh agent velocity
///
public override Vector3 velocity
{
get { return m_NavMeshAgent.velocity; }
}
public bool bInDeathState
{
get { return this.bInDeathAct; }
set { bInDeathAct = value; }
}
///
/// 是否是可再生的怪物类型
///
public bool bRespawn { get; set; }
///
/// The current state of the agent along the path
///
public State state { get; protected set; }
///
/// 当前Agent对应到的兵线ID.
///
public int waveLineID { get; set; }
public NavMeshAgent navMeshAgent
{
get { return this.m_NavMeshAgent; }
}
///
/// 是否显示目标位置信息
///
public bool bShowDebugNode = false;
///
/// 持续寻路,起到寻路成功
///
protected bool nodeMoveUpdate = false;
///
/// 代理的类型
///
public SpawnAgentType AgentType { get; set; } = SpawnAgentType.Normal;
///
/// 无尽模式小怪对应 endless_enemy表中数据
///
public endless_enemy EnemyData { get; set; }
///
/// Accessor to
///
public NavMeshAgent navMeshNavMeshAgent
{
get { return m_NavMeshAgent; }
set { m_NavMeshAgent = value; }
}
public float distanceToDest
{
get { return this.m_DisToDestination; }
}
///
/// The area mask of the attached nav mesh agent
///
public int navMeshMask
{
get { return m_NavMeshAgent.areaMask; }
}
///
/// Gets this agent's original movement speed
///
public float originalMovementSpeed { get; protected set; }
///
/// 小怪的动作状态
///
public AgentActionState ActionState { get; protected set; }
private string paramName = "AgentActionState";
///
/// 更新怪物的移动速度。
///
///
public void SetMoveSpeedScale(float fscale)
{
fMoveSpeed = fMoveSpeed * fscale;
}
///
/// 动态设置Agent的血量数据.
///
/// 设置当前小怪的血量.
/// 设置当前小怪的移动速度
/// 设置当前小怪的金币掉落数据
public void SetAgentData(float health, float moveSpeed = -1, int coinDrop = 0)
{
this.configuration.maxHealth = health;
this.configuration.startingHealth = health;
this.configuration.SetMaxHealth(health);
this.configuration.Init();
this.configuration.SetHealth(health);
// 只有在速度大于零的情况下才会设置.
if (moveSpeed > 0)
fMoveSpeed = moveSpeed;
// 金币掉落大于零.
if (coinDrop > 0)
mLootDrop.lootDropped = coinDrop;
mAgentData.speed = fMoveSpeed;
mAgentData.hp = this.configuration.maxHealth;
//
mStartYVal = this.transform.position.y;
mStartZVal = this.transform.position.z;
// 确保设置成默认白色纹理:
this.SetTargetableMatColor(Color.white, true);
speedSlowRate = 0.0f;
poisonHurt = 0;
poisonAttid = 0;
poisonTimes = 0;
timeToPoisonHurt = 0;
bShieldBreak = false;
CanMove = true;
/*// 如果对应的粒子不为空,则播放
if( spawnParticle)
{
ParticleSystem tpar = Instantiate(spawnParticle);
tpar.transform.localScale = new Vector3(1.5f, 1.5f, 1.5f);
tpar.transform.position = this.transform.position;
tpar.Simulate(0.0f);
tpar.Play();
}*/
// if (healthBar)
// healthBar.bOpponent = opponentAgent;
}
///
/// Checks if the path is blocked
///
///
/// The status of the agent's path
///
protected virtual bool isPathBlocked
{
get { return m_NavMeshAgent.pathStatus == NavMeshPathStatus.PathPartial; }
}
///
/// Is the Agent close enough to its destination?
///
protected virtual bool isAtDestination
{
get { return navMeshNavMeshAgent.remainingDistance <= navMeshNavMeshAgent.stoppingDistance; }
}
///
/// 改变m_NextNode,因为要切换基地
///
///
public void ChangeNextNode(Node node)
{
m_NextNode = node;
}
///
/// Sets the node to navigate to
///
/// The node that the agent will navigate to
public virtual void SetNode(Node node, int lineid)
{
if (lineid >= 0)
waveLineID = lineid;
// 设置为空的时候,是为了不再每一帧更新Agent的位置信息
if (node == null)
{
m_CurrentNode = null;
m_NextNode = null;
return;
}
if (m_CurrentNode == null)
{
initNode = node;
}
m_CurrentNode = node;
// 需要设置移动的目标Node.
m_NextNode = m_CurrentNode.GetNextNode();
this.MoveToNode();
}
///
/// 处理Agent的锁定Buf,播放特效,设置速度为零,并时间到达后重设数据。
///
///
protected virtual void SetAgentStopBuff(buffinfo binfo)
{
MoveStopTime = binfo.last / 1000;
if (!isFrost)
{
isFrost = true;
if (FrostParticle != null)
FrostParticle.Play();
}
}
///
/// 设置当前Agent对应的各种技能属性ID.
///
///
public void SetAgentBuffEffect(int buffid)
{
buffinfo bufdata = JsonDataCenter.GetBuffFromId(buffid);
if (bufdata == null) return;
if (bufdata.buff_func[0] == 3)
{
SetAgentStopBuff(bufdata);
}
else
return;
}
public override bool isAgent()
{
return true;
}
///
/// Stops the navMeshAgent and attempts to return to pool
///
public override void Remove()
{
// 统一管理器内删除当前的Agent:
AgentInsManager.instance.removeAgent(this);
EventCenter.Ins.BroadCast((int)KTGMGemClient.EventType.EndlessAgentDead, this);
base.Remove();
if (m_LevelManager) m_LevelManager.DecrementNumberOfEnemies();
else endlessLevelManager.DecrementNumberOfEnemies();
if (m_NavMeshAgent.enabled)
{
m_NavMeshAgent.isStopped = true;
}
m_NavMeshAgent.enabled = false;
// 必须要重置数据,不然会有一系列的小Bug.
this.m_CurrentNode = null;
m_NextNode = null;
this.liveID = this.liveID + 1;
speedSlowRate = 0.0f;
poisonHurt = 0;
poisonAttid = 0;
poisonTimes = 0;
timeToPoisonHurt = 0;
isFrost = false;
bShieldBreak = false;
bInDeathAct = false;
ChangeState(AgentActionState.Move);
configuration.ClearShieldWall();
StopFrostParticle();
//this.SetTargetableMatColor(Color.white);
// 删除当前停止特效和状态.
if (MoveStopTime > 0)
MoveStopTime = 0.0f;
// 停止DoTween动画.
this.transform.DOKill();
Poolable.TryPool(gameObject);
}
private void StopFrostParticle()
{
if (FrostParticle != null)
FrostParticle.Stop();
}
///
/// Setup all the necessary parameters for this agent from configuration data
///
public virtual void Initialize()
{
ResetPositionData();
LazyLoad();
configuration.SetHealth(configuration.maxHealth);
state = isPathBlocked ? State.OnPartialPath : State.OnCompletePath;
// River TEST CODE TO DELETE: 测试成功之后,是需要删除navMeshAgent组件的,根本不需要
m_NavMeshAgent.enabled = false;
if (m_LevelManager) m_LevelManager.IncrementNumberOfEnemies();
else endlessLevelManager.IncrementNumberOfEnemies();
//
// 设置一个DOTween队列,让场景内刷出来的Agent有一个变大淡出的效果,此时是无敌效果加持.
this.configuration.bInvincible = true;
mDefaultScale = this.transform.localScale;
Sequence agentTweenSeq = DOTween.Sequence();
var ss = mDefaultScale * 0.3f;
this.transform.localScale = this.transform.localScale * 0.3f;
Tweener agScale = this.transform.DOScale(mDefaultScale, 0.3f);
agentTweenSeq.Append(agScale);
agentTweenSeq.AppendCallback(beDamageStart);
this.nodeMoveUpdate = false;
// 获取移动速度
fMoveSpeed = this.m_NavMeshAgent.speed / 2.0f;
}
protected void beDamageStart()
{
this.configuration.bInvincible = false;
}
///
/// 把当前的Agent拉到起始位置
///
public void ResetAgentToInitialPos()
{
if (!this.initNode) return;
Vector3 initPos = this.initNode.GetRandomPointInNodeArea();
transform.position = initPos;
ResetPositionData();
this.SetNode(initNode, -1);
// 更新AgentMgr,确保不再攻击回到原点的Agent.
AgentInsManager.instance.updateInsMgrPos(this.opponentAgent);
}
///
/// 执行重设到开始位置的Agent特效,需要执行一系列的动作.
///
public void execAgentPosResetAction()
{
// 无敌状态不增加当前的效果:
if (configuration.bInvincible) return;
// 只有处于非PosEffect状态才可以有这个状态.
var posResetEff = this.GetComponent();
if (posResetEff == null)
{
posResetEff = this.gameObject.AddComponent();
// 初始化当前的PosResetEffect
posResetEff.Initialize(3, AgentInsManager.instance.posResetFx);
}
}
///
/// 预处理当前的Agent最大或最小可以到达的ZValue.
///
protected void PreProcessZValue()
{
if (!m_CurrentNode) return;
Node nextNode = m_CurrentNode.GetNextNode();
if (!nextNode) return;
/* if (m_CurrentNode.transform.position.z > nextNode.transform.position.z)
this.m_PositiveZ = false;
else
this.m_PositiveZ = true;
m_ZMaxValue = nextNode.transform.position.z;
Node thirdNode = nextNode.GetNextNode();
if (!thirdNode) return;
if (thirdNode.transform.position.x > nextNode.transform.position.x)
this.m_PositiveX = true;
else
{
this.m_PositiveX = false;
}
m_XMaxValue = thirdNode.transform.position.x;*/
}
///
/// Finds the next node in the path
///
public virtual void MoveToNextNode(Node currentlyEnteredNode)
{
// Don't do anything if the calling node is the same as the m_CurrentNode
if (m_NextNode != currentlyEnteredNode)
{
return;
}
if (m_NextNode == null)
{
Debug.LogError("Cannot find current node");
return;
}
Node nextNode = m_NextNode.GetNextNode();
if (nextNode == null)
{
if (m_NavMeshAgent.enabled)
{
m_NavMeshAgent.isStopped = true;
}
// 清空当前的Node和NextNode.
m_CurrentNode = null;
HandleDestinationReached();
m_NextNode = null;
return;
}
Debug.Assert(nextNode != m_CurrentNode);
SetNode(m_NextNode, -1);
}
///
/// Moves the agent to a position in the
/// 预计算开始位置,结束位置,以及移动方向。
///
public virtual void MoveToNode()
{
if ((!m_CurrentNode) || (!m_NextNode))
{
if (!m_CurrentNode)
Debug.Log("当前的Node值为空.");
else
Debug.Log("NextNode的值为空.");
return;
}
m_Destination = m_NextNode;
m_SrcPosition = m_CurrentNode.transform.position;
//
// 预处理,确定移动方向.
if (m_Destination.transform.position.x == m_SrcPosition.x)
{
if (m_Destination.transform.position.z > m_SrcPosition.z)
moveDir = EAgentMovDir.ZPositive;
else
moveDir = EAgentMovDir.ZNegative;
}
else
{
if (m_Destination.transform.position.z != m_SrcPosition.z)
{
Debug.Log("目标位置和开始位置的Z值不相等:" + m_Destination.transform.position.x + "," + m_Destination.transform.position.z + "," +
m_SrcPosition.x + "," + m_SrcPosition.z);
}
if (m_Destination.transform.position.x > m_SrcPosition.x)
moveDir = EAgentMovDir.XPositive;
else
moveDir = EAgentMovDir.XNegative;
}
}
///
/// The logic for what happens when the destination is reached
///
public virtual void HandleDestinationReached()
{
state = State.PathComplete;
if (destinationReached != null)
{
destinationReached(m_NextNode);
}
}
///
/// Lazy Load, if necesaary and ensure the NavMeshAgent is disabled
///
protected override void Awake()
{
//Debug.Log("哪里生成的?");
base.Awake();
LazyLoad();
m_NavMeshAgent.enabled = false;
MoveStopTime = 0.0f;
}
///
/// 根据帧间的时间,来更新Agent的位置信息,其它信息直接删除.
/// 1:
///
///
protected void updateAgentPos(float deltaTime)
{
if ((!m_CurrentNode) || (!m_NextNode))
return;
// 是否处于停止状态.
if (MoveStopTime > 0)
{
MoveStopTime -= Time.deltaTime;
if (MoveStopTime <= 0)
{
StopFrostParticle();
MoveStopTime = 0;
}
else
return;
}
if (this.fMoveSpeed == 0)
{
Debug.Log("当前的移动为零:" + fMoveSpeed);
return;
}
float finalSpeed = fMoveSpeed * (1 - speedSlowRate);
if (speedSlowRate > 0 && !isSlowDown)
{
isSlowDown = true;
if (SlowDownParticle != null)
SlowDownParticle.Play();
}
else if (speedSlowRate == 0 && isSlowDown)
{
isSlowDown = false;
if (SlowDownParticle != null)
{
SlowDownParticle.Stop();
SlowDownParticle.Clear();
}
}
Vector3 curPos = m_NavMeshAgent.transform.position;
bool swithNode = false;
switch (moveDir)
{
case EAgentMovDir.ZPositive:
{
curPos.z += (deltaTime * finalSpeed);
if (curPos.z >= m_Destination.transform.position.z)
{
curPos.z = m_Destination.transform.position.z;
swithNode = true;
}
break;
}
case EAgentMovDir.ZNegative:
{
curPos.z -= (deltaTime * finalSpeed);
if (curPos.z <= m_Destination.transform.position.z)
{
curPos.z = m_Destination.transform.position.z;
swithNode = true;
}
break;
}
case EAgentMovDir.XPositive:
{
curPos.x += (deltaTime * finalSpeed);
if (curPos.x >= m_Destination.transform.position.x)
{
curPos.x = m_Destination.transform.position.x;
swithNode = true;
}
break;
}
case EAgentMovDir.XNegative:
{
curPos.x -= (deltaTime * finalSpeed);
if (curPos.x <= m_Destination.transform.position.x)
{
curPos.x = m_Destination.transform.position.x;
swithNode = true;
}
break;
}
}
// 根据是否到达一个结点来进行不同的处理
if (swithNode)
{
this.MoveToNextNode(m_NextNode);
}
else
{
// Y值插值.
float lerpVal = (curPos.z - mStartZVal) / (m_Destination.transform.position.z - mStartZVal);
if (!this.opponentAgent)
// curPos.y = mStartYVal + lerpVal * 60f;
curPos.y = mStartYVal;
m_NavMeshAgent.transform.position = curPos;
}
return;
}
///
/// 更新动作信息.
///
///
protected void UpdateAction()
{
if (ActionAnimator == null) return;
AnimatorStateInfo stateInfo = ActionAnimator.GetCurrentAnimatorStateInfo(0);
switch (ActionState)
{
case AgentActionState.Move:
break;
case AgentActionState.GetHit:
if (stateInfo.normalizedTime >= 1f)
ChangeState(AgentActionState.Move);
break;
case AgentActionState.Attack:
if (stateInfo.normalizedTime >= 1f)
{
if (isDead)
{
AgentInsManager.instance.removeAgent(this);
Remove();
}
}
break;
case AgentActionState.Death:
if (stateInfo.normalizedTime >= 1f)
Remove();
break;
}
}
private void ChangeState(AgentActionState state)
{
if (state == ActionState) return;
ActionState = state;
if (ActionAnimator != null)
ActionAnimator.SetInteger(paramName, (int)state);
}
///
/// 检查自身血量
///
private void CheckHealth()
{
if (this.healthVal <= 0.1)
{
Die();
//Debug.Log("删除多余的攻击Agent.");
}
}
private void Die()
{
// 统一管理器内删除当前的Agent:
AgentInsManager.instance.removeAgent(this);
this.Remove();
}
///
/// Updates the agent in its different states,
/// Reset destination when path is stale
/// River: 更新的时候,加入离最终目标的距离数据.
///
protected virtual void LateUpdate()
{
this.UpdateAction();
HandleShieldWall();
// 处理死亡状态了,不必再移动:
if (bInDeathAct || !CanMove) return;
m_Destination = initNode.GetNextNode();
updateAgentPos(Time.deltaTime);
// 计算离目标的距离,非最终距离,只用于比较大小
this.m_DisToDestination = this.GetDisToDestination();
// 计算中毒相关.
if ((poisonTimes > 0) && (poisonHurt > 0))
updatePoison(Time.deltaTime);
}
protected virtual void Update()
{
}
///
/// 处理魔法护盾血量值
///
protected void HandleShieldWall()
{
if (configuration.IsExistShieldWall)
{
if (configuration.ShieldWallCurrentHealth <= 0.00001f)
configuration.IsExistShieldWall = false;
else if (configuration.ShieldWallEffectiveTime > 0.00001f)
{
if (configuration.ShieldWallRemainTime <= 0.00001f)
configuration.IsExistShieldWall = false;
else
configuration.ShieldWallRemainTime -= Time.deltaTime;
}
}
}
///
/// 限制当前Agent的移动位置,让Agent的移动看起来更帅一些
///
protected void restrictAgentPos()
{
/* // 设置最大的Z值,确保按路线移动
Vector3 pos = m_NavMeshAgent.transform.position;
if (this.m_PositiveZ)
{
if (pos.z > m_ZMaxValue)
{
pos.z = m_ZMaxValue;
m_NavMeshAgent.transform.position = pos;
}
}
else
{
if (pos.z < m_ZMaxValue)
{
pos.z = m_ZMaxValue;
m_NavMeshAgent.transform.position = pos;
}
}
// 设置X值的限制,确保按路线移动
if(this.m_PositiveX)
{
if( pos.x > m_XMaxValue)
{
pos.x = m_XMaxValue;
m_NavMeshAgent.transform.position = pos;
}
}
else
{
if( pos.x < m_XMaxValue)
{
pos.x = m_XMaxValue;
m_NavMeshAgent.transform.position = pos;
}
}*/
}
///
/// Set the NavMeshAgent's destination
///
/// The position to navigate to
protected virtual bool NavigateTo(Vector3 nextPoint)
{
// River mod: 完全自己控制移动 ,不需要navMeshAgent.
return true;
/*
LazyLoad();
bool res = false;
if (m_NavMeshAgent.isOnNavMesh)
{
nextPoint.y += 0.1f;
res = m_NavMeshAgent.SetDestination(nextPoint);
}
return res;*/
}
///
/// 计算当前的Agent距离目标的最终距离,不是真实距离,是比较大小的数值.
///
///
protected float GetDisToDestination()
{
if (!m_CurrentNode) return 0;
float tmpDis = 0;
Node tmpNode = m_CurrentNode.GetNextNode();
while (tmpNode.GetNextNode() != null)
{
tmpDis += NODE_DIS;
tmpNode = tmpNode.GetNextNode();
}
Vector3 tpos = this.position;
tpos.y = mStartYVal;
tmpDis += Vector3.Distance(tpos, this.m_Destination.transform.position);
return tmpDis;
}
protected ChangeMat changeMat;
///
/// This is a lazy way of caching several components utilised by the Agent
///
protected virtual void LazyLoad()
{
if (m_NavMeshAgent == null)
{
m_NavMeshAgent = GetComponent();
mLootDrop = GetComponent();
originalMovementSpeed = m_NavMeshAgent.speed;
}
if (m_LevelManager == null)
{
m_LevelManager = LevelManager.instance;
}
if (!endlessLevelManager)
endlessLevelManager = EndlessLevelManager.instance;
}
///
/// 播放受击动画.
///
public void PlayOnHit()
{
ChangeState(AgentActionState.GetHit);
}
///
/// 播放受击动画,直接从头开始播放
///
public void PlayOnHitImmediately()
{
ChangeState(AgentActionState.GetHit);
if (ActionAnimator)
{
ActionAnimator.Play("GetHit", 0, 0);
ActionAnimator.Update(0);
}
}
///
/// 播放火技能打击动画
///
public void PlayFireSkillHit()
{
if (FireSkillParticle != null)
FireSkillParticle.Play();
}
public void PlayAttack()
{
AudioSourceManager.Ins.Play(AudioEnum.AttackTower);
ChangeState(AgentActionState.Attack);
}
public override void PlayDeath()
{
if (isPoison)
{
isPoison = false;
// 移除Agent身上的中毒特效,并播放一个中毒效果消失的特效
if (PoisonParticle != null)
{
PoisonParticle.Stop();
PoisonParticle.Clear();
if (PoisonEndParticle != null)
PoisonEndParticle.Play();
}
}
if (isSlowDown)
{
isSlowDown = false;
if (SlowDownParticle != null)
{
SlowDownParticle.Stop();
SlowDownParticle.Clear();
}
}
ChangeState(AgentActionState.Death);
// 统一管理器内删除当前的Agent:
AgentInsManager.instance.removeAgent(this);
bInDeathAct = true;
}
///
/// Move along the path, change to
///
protected virtual void OnCompletePathUpdate()
{
if (isPathBlocked)
{
state = State.OnPartialPath;
}
}
///
/// Peforms the relevant path update
///
protected abstract void PathUpdate();
///
/// The behaviour for when the agent has been blocked
///
protected abstract void OnPartialPathUpdate();
#if UNITY_EDITOR
///
/// Draw the agent's path
///
protected virtual void OnDrawGizmosSelected()
{
if (m_NavMeshAgent != null)
{
Vector3[] pathPoints = m_NavMeshAgent.path.corners;
int count = pathPoints.Length;
for (int i = 0; i < count - 1; i++)
{
Vector3 from = pathPoints[i];
Vector3 to = pathPoints[i + 1];
Gizmos.DrawLine(from, to);
}
Gizmos.DrawWireSphere(m_NavMeshAgent.destination, 0.2f);
}
}
#endif
}
}