相关链接:https://blog.csdn.net/lovelion/article/details/8299794
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TemplateMethodDemo:MonoBehaviour
{
void Start()
{
IPeople nor = new NorthPeople();
nor.Eat();
}
}
public abstract class IPeople
{
public void Eat()
{
OrderFoods();
EatSomething();
PayBill();
}
public void OrderFoods() {
Debug.Log("—点单");
}
public abstract void EatSomething();
public void PayBill()
{
Debug.Log("—买单");
}
}
public class NorthPeople : IPeople
{
public override void EatSomething()
{
Debug.Log("我在吃面条");
}
}
public class SouthPeople : IPeople
{
public override void EatSomething()
{
Debug.Log("我在吃米饭");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class IWeapon
{
protected int mAtk;//最大攻击力
protected float mAtkRange;//最大攻击范围
protected int mAtkPlusValue;//暴击
protected GameObject mGameObject;//武器模型
protected ICharacter mOwner;//武器持有者
protected ParticleSystem mParticle;//武器特效
protected LineRenderer mLineRender;//武器射线
protected Light mLight;
protected AudioSource mAudioSource; //音效
protected float mEffectDisplayTime;//特效显示时间
public void Fire(Vector3 targetPos)
{
//显示枪口特效
GunShootEffect();
//显示子弹轨迹特效
GunBulletEffect(targetPos);
//设置特效显示时间
SetDisplayEffectTime();
//播放声音
PlayAudioSources();
}
public void Update()
{
if (mEffectDisplayTime > 0)
{
mEffectDisplayTime -= Time.deltaTime;
if (mEffectDisplayTime <= 0)
{
DisableEffect();
}
}
}
protected abstract void SetDisplayEffectTime();
protected virtual void GunShootEffect()
{
DoGunShootEffect();
}
protected void DoGunShootEffect()
{
mParticle.Stop();
mParticle.Play();
mLight.enabled = true;
}
protected abstract void GunBulletEffect(Vector3 targetPos);
protected void DoGunBulletEffect(Vector3 targetPos, float Width)
{
mLineRender.enabled = true;
mLineRender.startWidth = Width;
mLineRender.endWidth = Width;
mLineRender.SetPosition(0, mGameObject.transform.position);
mLineRender.SetPosition(1, targetPos);
}
protected abstract void PlayAudioSources();
protected void DoPlayAudioSources(string str)
{
string clipName = str;
AudioClip clip = null; //TODO 后面会对资源加载进行管理,先不做改动
mAudioSource.clip = clip;
mAudioSource.Play();
}
//结束特效显示
private void DisableEffect()
{
mLight.enabled = false;
mLineRender.enabled = false;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponGun: IWeapon
{
protected override void GunBulletEffect(Vector3 targetPos)
{
DoGunBulletEffect(targetPos,0.1f);
}
protected override void PlayAudioSources()
{
DoPlayAudioSources("GunShot");
}
protected override void SetDisplayEffectTime()
{
mEffectDisplayTime = 0.2f;
}
}
相关链接http://wiki.unity3d.com/index.php/Finite_State_Machine
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum SoldierTransition
{
NullTransition,
SeeEnemy,
CanAttack,
NoEnemy,
}
public enum SoldierStateID
{
NullState,
Idle,
Chase,
Attack
}
public abstract class ISoldierState
{
protected Dictionary mapDict = new Dictionary();
protected ICharacter mCharacter; //属于哪个角色
protected SoldierFSMSystem mSoldierFSMSystem;
protected SoldierStateID mSoldierStateID;
public SoldierStateID stateID { get { return stateID; } }
public ISoldierState(SoldierFSMSystem fsm, ICharacter c)
{
this.mSoldierFSMSystem = fsm;
mCharacter = c;
}
public void AddTransition(SoldierTransition tran, SoldierStateID id)
{
if (tran == SoldierTransition.NullTransition)
{
Debug.Log("SoldierState Error : tran不能为空"); return;
}
if (id == SoldierStateID.NullState)
{
Debug.Log("SoldierState Error : id不能为空"); return;
}
if (mapDict.ContainsKey(tran))
{
Debug.Log("SoldierState Error :"+tran+"已经添加过了"); return;
}
mapDict.Add(tran, id);
}
public void DelectTransition(SoldierTransition tran, SoldierStateID id)
{
if (tran == SoldierTransition.NullTransition)
{
Debug.Log("SoldierState Error : tran不能为空"); return;
}
if (mapDict.ContainsKey(tran))
{
mapDict.Remove(tran);
return;
}
Debug.Log("SoldierState Error : id was not on the state's transition list");
}
public SoldierStateID GetPutoutStateID(SoldierTransition tran)
{
if (mapDict.ContainsKey(tran))
{
return mapDict[tran];
}
return SoldierStateID.NullState;
}
public virtual void DoBeforeEntering() { }
public virtual void DoBeforeLeaving() { }
///
/// 控制行为
///
public abstract void Act(List targets);
///
/// 此方法决定状态是否应该转换到其列表中的另一个状态
///
/// 要跟随/攻击的目标
public abstract void Reason(List targets);
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoldierFSMSystem
{
private List stateList = new List();
private ISoldierState mCurrentState;
public ISoldierState CurrentState { get { return mCurrentState; } }
public void AddState(ISoldierState state)
{
if (state == null)
{
Debug.Log("要添加的状态为空");
return;
}
if (stateList.Count == 0)
{
stateList.Add(state);
mCurrentState = state;
return;
}
foreach (ISoldierState s in stateList)
{
if (s.stateID == state.stateID)
{
Debug.Log("存在相同的ID");
return;
}
}
stateList.Add(state);
}
public void DelectState(SoldierStateID stateID)
{
if (stateID == SoldierStateID.NullState)
{
Debug.Log("要删除的ID状态为空_"+stateID);
}
foreach (ISoldierState state in stateList)
{
if (state.stateID == stateID)
{
stateList.Remove(state);return;
}
}
Debug.Log("要删除的ID状态不在集合中_" + stateID);
}
public void PerformTransiton(SoldierTransition trans)
{
if (trans == SoldierTransition.NullTransition)
{
Debug.LogWarning("要执行的转换条件为空:" + trans); return;
}
SoldierStateID currentID = CurrentState.GetPutoutStateID(trans);
if (currentID == SoldierStateID.NullState)
{
Debug.LogWarning("在转换条件[" + trans+"]下没有对应的状态"); return;
}
foreach (ISoldierState state in stateList)
{
if (state.stateID == currentID)
{
mCurrentState.DoBeforeLeaving();
mCurrentState = state;
mCurrentState.DoBeforeEntering();
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoldierIdleState : ISoldierState
{
public SoldierIdleState(SoldierFSMSystem fsm, ICharacter c) :base(fsm,c) { mSoldierStateID = SoldierStateID.Idle; }
public override void Act(List targets)
{
mCharacter.SetAnimation("stand");
}
public override void Reason(List targets)
{
if (targets != null && targets.Count > 0)
{
mSoldierFSMSystem.PerformTransiton(SoldierTransition.SeeEnemy);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public abstract class ICharacter
{
protected GameObject mGameObject;//游戏角色
protected NavMeshAgent mNavMeshAgent;
protected AudioSource mAudioSource;
protected ICharacterAttr mCharacterAttri;//角色属性
protected Animation mAnimation;//角色动画
protected IWeapon mWeapon;
public IWeapon Weapon { set { mWeapon = value; } }
public float mAtkRange { get { return mWeapon.AtkRange; } } //武器的攻击距离
public void Attack(ICharacter targetPos)
{
//TODO
mWeapon.Fire(targetPos.GetPosition);
}
///
/// 得到角色位置
///
///
public Vector3 GetPosition
{
get
{
if (mGameObject == null)
{
Debug.LogWarning("mGameObject为空");
return Vector3.zero;
}
return mGameObject.transform.position;
}
}
///
/// 设置角色动画
///
///
public void SetAnimation(string animName)
{
mAnimation.CrossFade(animName);
}
///
/// 追击状态下,移动至目标
///
///
public void MoveToTarget(Vector3 target)
{
mNavMeshAgent.SetDestination(target);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoldierChaseState : ISoldierState
{
public SoldierChaseState(SoldierFSMSystem fsm, ICharacter c) : base(fsm, c) { mSoldierStateID = SoldierStateID.Chase; }
public override void Act(List targets)
{
if (targets.Count > 0 && targets != null)
{
mCharacter.MoveToTarget(targets[0].GetPosition);
}
}
public override void Reason(List targets)
{
//没有敌人时,转换为NoEnemy状态
if (targets.Count == 0 || targets == null)
{
mSoldierFSMSystem.PerformTransiton(SoldierTransition.NoEnemy); return;
}
//当角色和敌人距离小于攻击武器范围时,转换为攻击状态
if (targets.Count > 0 && targets != null)
{
float dist = Vector3.Distance(targets[0].GetPosition, mCharacter.GetPosition);
if (dist <= mCharacter.mAtkRange)
{
mSoldierFSMSystem.PerformTransiton(SoldierTransition.CanAttack);
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoldierAttackState : ISoldierState
{
public SoldierAttackState(SoldierFSMSystem fsm, ICharacter c) : base(fsm, c)
{
mSoldierStateID = SoldierStateID.Attack;
mAttackIntervalTimer = mAttackIntervalTime;
}
private float mAttackIntervalTime = 1;//攻击间隔为一秒
private float mAttackIntervalTimer = 1;//攻击间隔计时器
public override void Act(List targets)
{
if (targets.Count == 0 || targets == null) return;
if (targets != null && targets.Count > 0)
{
mAttackIntervalTimer += Time.deltaTime;
if (mAttackIntervalTimer >= mAttackIntervalTime)
{
mCharacter.Attack(targets[0]);
mAttackIntervalTimer = 0;
}
}
}
public override void Reason(List targets)
{
if (targets == null || targets.Count == 0)
{
mSoldierFSMSystem.PerformTransiton(SoldierTransition.NoEnemy); return;
}
//有敌人时,检测距离,距离小于攻击范围时转换为追击状态
if (targets != null && targets.Count > 0)
{
float dist = Vector3.Distance(targets[0].GetPosition, mCharacter.GetPosition);
if (dist > mCharacter.mAtkRange)
{
mSoldierFSMSystem.PerformTransiton(SoldierTransition.SeeEnemy); return;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ISoldier : ICharacter {
protected SoldierFSMSystem mSoldierFSMSystem;
public ISoldier():base()
{
MakeFSM();
}
public override void UpdateFSMAI(List targets)
{
mSoldierFSMSystem.CurrentState.Act(targets);
mSoldierFSMSystem.CurrentState.Reason(targets);
}
public void MakeFSM()
{
SoldierAttackState attackState = new SoldierAttackState(mSoldierFSMSystem,this);
attackState.AddTransition(SoldierTransition.NoEnemy,SoldierStateID.Idle);
attackState.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase);
SoldierIdleState idleState = new SoldierIdleState(mSoldierFSMSystem, this);
idleState .AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase);
SoldierChaseState chaseState = new SoldierChaseState(mSoldierFSMSystem, this);
chaseState .AddTransition(SoldierTransition.CanAttack, SoldierStateID.Attack);
chaseState .AddTransition(SoldierTransition.NoEnemy, SoldierStateID.Idle);
mSoldierFSMSystem = new SoldierFSMSystem();
mSoldierFSMSystem.AddState(idleState);
mSoldierFSMSystem.AddState(attackState);
mSoldierFSMSystem.AddState(chaseState);
}
}
类似于战士的状态机。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum EnemyTransition
{
CanAttack,
LostSoldier,
NullTransition,
}
public enum EnemyStateID
{
NullStateID,
Chase,
Attack,
}
public abstract class IEnemyState
{
private Dictionary EnemyStateDict = new Dictionary();
protected ICharacter mCharacter;
protected EnemyFSMSystem mEnemyFSMSystem;
protected EnemyStateID mEnemyStateID;
public EnemyStateID EnemyStateID { get { return mEnemyStateID; } }
public IEnemyState(EnemyFSMSystem fsm, ICharacter c)
{
this.mEnemyFSMSystem = fsm;
mCharacter = c;
}
public void AddTransiton(EnemyTransition trans, EnemyStateID id)
{
if (trans == EnemyTransition.NullTransition)
{
Debug.Log("EnemyState Error : tran不能为空"); return;
}
if (id == EnemyStateID.NullStateID)
{
Debug.Log("EnemyState Error : id不能为空"); return;
}
if (EnemyStateDict.ContainsKey(trans))
{
Debug.Log("EnemyState Error :" + trans + "已经添加过了"); return;
}
EnemyStateDict.Add(trans, id);
}
public void DelectTransition(EnemyTransition trans)
{
if (trans == EnemyTransition.NullTransition)
{
Debug.Log("EnemyState Error : tran不能为空"); return;
}
if (EnemyStateDict.ContainsKey(trans))
{
EnemyStateDict.Remove(trans);
}
Debug.Log("EnemyState Error : id was not on the state's transition list");
}
public EnemyStateID GetPutoutID(EnemyTransition trans)
{
if (EnemyStateDict.ContainsKey(trans))
{
return EnemyStateDict[trans];
}
return EnemyStateID.NullStateID;
}
public virtual void DoBeforeEntering() { }
public virtual void DoBeforeLeaving() { }
public abstract void Act(List targets);
public abstract void Reason(List targets);
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyFSMSystem
{
private List mEnemyStatesList = new List();
private IEnemyState mCurrentState;
public IEnemyState CurrentState{ get { return mCurrentState; } }
public void AddState(IEnemyState state)
{
if (state == null)
{
Debug.Log("要添加的状态为空");
return;
}
if (mEnemyStatesList.Count == 0)
{
mEnemyStatesList.Add(state);
mCurrentState = state;
mCurrentState.DoBeforeEntering(); //++
return;
}
foreach (IEnemyState states in mEnemyStatesList)
{
if (states.EnemyStateID == state.EnemyStateID)
{
Debug.Log("存在相同的ID");
return;
}
}
mEnemyStatesList.Add(state);
}
public void DelectState(EnemyStateID stateID)
{
if (stateID == EnemyStateID.NullStateID)
{
Debug.Log("要删除的ID没有对应的状态");
}
foreach (IEnemyState states in mEnemyStatesList)
{
if (states.EnemyStateID == stateID)
{
mEnemyStatesList.Remove(states);
return;
}
}
Debug.Log("要删除的ID状态不在集合中_" + stateID);
}
public void PerformTransition(EnemyTransition trans)
{
if (trans == EnemyTransition.NullTransition)
{
Debug.LogWarning("要执行的转换条件为空:" + trans); return;
}
EnemyStateID currenID = mCurrentState.GetPutoutID(trans);
if (currenID == EnemyStateID.NullStateID)
{
Debug.LogWarning("在转换条件[" + trans + "]下没有对应的状态"); return;
}
foreach (IEnemyState states in mEnemyStatesList)
{
if (states.EnemyStateID == currenID)
{
mCurrentState.DoBeforeLeaving();
mCurrentState = states;
mCurrentState.DoBeforeEntering();
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyAttackState : IEnemyState
{
public EnemyAttackState(EnemyFSMSystem fsm, ICharacter c) : base(fsm, c)
{
mEnemyStateID = EnemyStateID.Attack;
mAttackIntervalTimer = mAttackIntervalTime;
}
private float mAttackIntervalTime = 1;//攻击间隔为一秒
private float mAttackIntervalTimer = 1;//攻击间隔计时器
public override void Act(List targets)
{
if (targets.Count == 0 || targets == null) return;
mAttackIntervalTimer += Time.deltaTime;
if (mAttackIntervalTimer >= mAttackIntervalTime)
{
mCharacter.Attack(targets[0]);
mAttackIntervalTimer = 0;
}
}
public override void Reason(List targets)
{
if (targets == null || targets.Count == 0)
{
mEnemyFSMSystem.PerformTransition(EnemyTransition.LostSoldier); return;
}
else
{
float dist = Vector3.Distance(targets[0].GetPosition, mCharacter.GetPosition);
if (dist > mCharacter.mAtkRange)
{
mEnemyFSMSystem.PerformTransition(EnemyTransition.LostSoldier);
}
}
}
}
重写了DoBeforeEntering(),利用中介者类Gamefacade得到敌人位置(后续开发)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyChaseState : IEnemyState
{
public EnemyChaseState(EnemyFSMSystem fsm, ICharacter c) : base(fsm, c) { mEnemyStateID = EnemyStateID.Chase; }
private Vector3 mTargetPosition;
public override void DoBeforeEntering()
{
mTargetPosition = GameFacade.Instance.GetEnemyTargetPosition();
}
public override void Act(List targets)
{
if (targets != null && targets.Count > 0)
{
mCharacter.MoveToTarget(targets[0].GetPosition);
}
else
{
mCharacter.MoveToTarget(mTargetPosition);
}
}
public override void Reason(List targets)
{
if (targets != null && targets.Count > 0)
{
float dist = Vector3.Distance(targets[0].GetPosition, mCharacter.GetPosition);
if (dist <= mCharacter.mAtkRange)
{
mEnemyFSMSystem.PerformTransition(EnemyTransition.CanAttack);
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IEnemy : ICharacter
{
protected EnemyFSMSystem fsm;
public IEnemy()
{
MakeFSM();
}
public override void UpdateFSMAI(List targets)
{
fsm.CurrentState.Reason(targets);
fsm.CurrentState.Act(targets);
}
public void MakeFSM()
{
fsm = new EnemyFSMSystem();
EnemyChaseState eEnemyChaseState = new EnemyChaseState(fsm, this);
eEnemyChaseState.AddTransiton(EnemyTransition.CanAttack, EnemyStateID.Attack);
EnemyAttackState eEnemyAttackState = new EnemyAttackState(fsm, this);
eEnemyAttackState.AddTransiton(EnemyTransition.LostSoldier, EnemyStateID.Chase);
fsm.AddState(eEnemyChaseState);
fsm.AddState(eEnemyAttackState);
}
}
开发角色管理系统CharacterSystem:
管理所有角色,对其进行Update更新,并将ISoldier和IEnemy的UpdateFSMAI方法提取到ICharacter中,作为抽象方法;ICharacter中加入Update方法对IWeapon的Update()方法进行更新:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 管理当前游戏所有实例化出的敌人和战士的更新
///
public class CharacterSystem : IGameSystem
{
private List EnemyList = new List();
private List SoldierList = new List();
public void AddEnemy(IEnemy enemy)
{
//if (enemy == null) return;
EnemyList.Add(enemy);
}
public void RemoveEnemy(IEnemy enemy)
{
//if (enemy == null) return;
EnemyList.Remove(enemy);
}
public void AddSoldier(ISoldier soldier)
{
//if (enemy == null) return;
SoldierList.Add(soldier);
}
public void RemoveSoldier(ISoldier soldier)
{
//if (enemy == null) return;
SoldierList.Remove(soldier);
}
public override void Update()
{
foreach (ISoldier soldier in SoldierList)
{
soldier.Update();
soldier.UpdateFSMAI(EnemyList);
}
foreach (IEnemy enemy in EnemyList)
{
enemy.Update();
enemy.UpdateFSMAI(SoldierList);
}
}
}
对角色的攻击功能进行开发:
完善ICharacter的Attack方法,写入UnderAttck() - 受到攻击后的方法 - 调用自ICharacterAttri 角色属性接口,
在ICharacterAttri中对收到攻击进行伤害计算 - 包括 暴击、血量等
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public abstract class ICharacter
{
protected GameObject mGameObject;//游戏角色
protected NavMeshAgent mNavMeshAgent;
protected AudioSource mAudioSource;
protected ICharacterAttr mCharacterAttri;//角色属性
protected Animation mAnimation;//角色动画
protected IWeapon mWeapon;
public IWeapon Weapon { set { mWeapon = value; } }
public float mAtkRange { get { return mWeapon.AtkRange; } } //武器的攻击距离
public void Update()
{
mWeapon.Update();
}
public abstract void UpdateFSMAI(List targets);
public void Attack(ICharacter target)
{
mWeapon.Fire(target.GetPosition);
mGameObject.transform.LookAt(target.GetPosition);
mAnimation.Play("attack");
target.UnderAttck((int)mWeapon.Atk+mCharacterAttri.CritValue);
}
///
/// 受到伤害后执行的方法
///
/// 受到的伤害
public virtual void UnderAttck(int damage)
{
mCharacterAttri.TakeDamege(damage);
}
///
/// 得到角色位置
///
///
public Vector3 GetPosition
{
get
{
if (mGameObject == null)
{
Debug.LogWarning("mGameObject为空");
return Vector3.zero;
}
return mGameObject.transform.position;
}
}
///
/// 设置角色动画
///
///
public void SetAnimation(string animName)
{
mAnimation.CrossFade(animName);
}
///
/// 追击状态下,移动至目标
///
///
public void MoveToTarget(Vector3 target)
{
mNavMeshAgent.SetDestination(target);
mAnimation.Play("move");
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ICharacterAttr
{
protected string mName;
protected int mMaxHp;
protected float mMoveSpeed;
protected int mCurrentHP;
protected string mIconSprite; // 资源加载
protected int mLv;
protected float mCritRate;//0-1暴击率
protected int mDmgDescValue; //减少的伤害
private IAttrStrategy mStrategy;
//角色实例化时就决定属性
public ICharacterAttr(IAttrStrategy strategy)
{
mStrategy = strategy;
mDmgDescValue = mStrategy.GetCritDmg(mCritRate);
mCurrentHP = mMaxHp + mStrategy.GetExtraHPValue(mLv);
}
public int CritValue { get { return mStrategy.GetCritDmg(mCritRate); } }
///
/// 被攻击后的处理
///
/// 受到的伤害
public void TakeDamege(int damage)
{
damage -= mDmgDescValue;
if (damage <= 5) damage = 5;
mCurrentHP -= damage;
}
}
重写ICharacter的UnderAttck()方法,处理敌人和战士被攻击的效果:
被攻击的特效 (只有敌人有),死亡的动画、音频 (只有战士有)
Killed()、DoPlaySound()、DoPlayEffect()方法放在ICharacter中,因为战士和敌人都用得到
战士:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class ISoldier : ICharacter
{
protected SoldierFSMSystem mSoldierFSMSystem;
public ISoldier() : base()
{
MakeFSM();
}
public override void UpdateFSMAI(List targets)
{
mSoldierFSMSystem.CurrentState.Act(targets);
mSoldierFSMSystem.CurrentState.Reason(targets);
}
public void MakeFSM()
{
SoldierAttackState attackState = new SoldierAttackState(mSoldierFSMSystem, this);
attackState.AddTransition(SoldierTransition.NoEnemy, SoldierStateID.Idle);
attackState.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase);
SoldierIdleState idleState = new SoldierIdleState(mSoldierFSMSystem, this);
attackState.AddTransition(SoldierTransition.SeeEnemy, SoldierStateID.Chase);
SoldierChaseState chaseState = new SoldierChaseState(mSoldierFSMSystem, this);
attackState.AddTransition(SoldierTransition.CanAttack, SoldierStateID.Attack);
attackState.AddTransition(SoldierTransition.NoEnemy, SoldierStateID.Idle);
mSoldierFSMSystem = new SoldierFSMSystem();
mSoldierFSMSystem.AddState(attackState);
mSoldierFSMSystem.AddState(idleState);
mSoldierFSMSystem.AddState(chaseState);
}
public override void UnderAttck(int damage)
{
base.UnderAttck(damage);
if (mCharacterAttri.CurrentHP <= 0)
{
PlaySound();
PlayEffect();
Killed();
}
}
public abstract void PlaySound();
public abstract void PlayEffect();
}
战士子类 如:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
///
/// 上尉
///
public class SoldierCaptain : ISoldier
{
public override void PlayEffect()
{
DoPlayEffect("CaptainDeadEffect");
}
public override void PlaySound()
{
DoPlaySound("CaptainDeath");
}
}
敌人:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class IEnemy : ICharacter
{
protected EnemyFSMSystem fsm;
public IEnemy()
{
MakeFSM();
}
public override void UpdateFSMAI(List targets)
{
fsm.CurrentState.Reason(targets);
fsm.CurrentState.Act(targets);
}
public void MakeFSM()
{
fsm = new EnemyFSMSystem();
EnemyChaseState eEnemyChaseState = new EnemyChaseState(fsm, this);
eEnemyChaseState.AddTransiton(EnemyTransition.CanAttack, EnemyStateID.Attack);
EnemyAttackState eEnemyAttackState = new EnemyAttackState(fsm, this);
eEnemyAttackState.AddTransiton(EnemyTransition.LostSoldier, EnemyStateID.Chase);
}
public override void UnderAttck(int damage)
{
base.UnderAttck(damage);
PlayEffect();
if (mCharacterAttri.CurrentHP <= 0)
{
Killed();
}
}
//每个Enemy被攻击的特效不同
protected abstract void PlayEffect();
}
敌人子类,如:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyOgre : IEnemy
{
protected override void PlayEffect()
{
DoPlayEffect("OgreHitEffect");
}
}
ICharacter:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public abstract class ICharacter
{
protected GameObject mGameObject;//游戏角色
protected NavMeshAgent mNavMeshAgent;
protected AudioSource mAudioSource;
protected ICharacterAttr mCharacterAttri;//角色属性
protected Animation mAnimation;//角色动画
protected IWeapon mWeapon;
public IWeapon Weapon { set { mWeapon = value; } }
public float mAtkRange { get { return mWeapon.AtkRange; } } //武器的攻击距离
public void Update()
{
mWeapon.Update();
}
public abstract void UpdateFSMAI(List targets);
public void Attack(ICharacter target)
{
mWeapon.Fire(target.GetPosition);
mGameObject.transform.LookAt(target.GetPosition);
mAnimation.Play("attack");
}
///
/// 受到伤害后执行的方法
///
/// 受到的伤害
public virtual void UnderAttck(int damage)
{
//被攻击的特效 (只有敌人有)
//死亡的动画、音频 (只有战士有)
mCharacterAttri.TakeDamege(damage);
}
protected void Killed()
{
//TODO
}
///
/// 得到角色位置
///
///
public Vector3 GetPosition
{
get
{
if (mGameObject == null)
{
Debug.LogWarning("mGameObject为空");
return Vector3.zero;
}
return mGameObject.transform.position;
}
}
///
/// 设置角色动画
///
///
public void SetAnimation(string animName)
{
mAnimation.CrossFade(animName);
}
///
/// 追击状态下,移动至目标
///
///
public void MoveToTarget(Vector3 target)
{
mNavMeshAgent.SetDestination(target);
mAnimation.Play("move");
}
protected void DoPlayEffect(string effectName)
{
//加载特效 TODO
GameObject effectGO;
//控制销毁 TODO
}
protected void DoPlaySound(string clipName)
{
AudioClip clip = null; //TODO 统一进行资源加载
mAudioSource.clip = clip;
mAudioSource.Play();
}
}