《Tactera全息指挥官》作为一款VR版沙盘对战游戏,科技感爆棚。…
主要有以下几个地方值得深入学习和研究:
1.UI界面设计
2.游戏交互方式
经典VR游戏《全息指挥官》临摹-战斗场景分析
经典VR游戏《全息指挥官》临摹-地形创建
经典VR游戏《全息指挥官》临摹-UI搭建
战斗场景中包含移动单位和建筑单位,其中移动单位又包括空中单位和地面单位,移动单位能够自动检测目标并发动攻击,建筑单位能够攻击进入射程的移动单位。可以看出移动单位具有静止、移动和攻击三种状态,建筑单位又静止和攻击两种状态。因此可以利用状态控制机对几中状态进行控制,使得每种状态独立开来,互不影响。例如Move状态检测目标和寻路,攻击状态为发动攻击。
一、整体结构
二、有限状态机FSM
实现对场景中兵种的控制。
有三种状态:
待命(PatrolState)
移动(MoveState)
攻击(AttackState)
状态的切换:
PatrolState->MoveState:有移动目标
PatrolState->AttackState:有攻击目标
MoveState->AttackState:有攻击目标
AttackState->PatrolState:攻击目标变为空
定义的三种状态需要继承状态的基类State,状态有基本的属性和方法。
公有方法:
EnterState()
Action()
Change()
ExitState()
除了公有的基本方法外,继承State基类的每个子类还有自己独有的方法,例如MoveState()中有寻找地图上最短路径的方法。
参数传递
状态的枚举
public enum UnitState{
PatrolState,
MoveState,
AttackState
}
状态基类
public abstract class BaseState {
#region 字段
//状态名字
public UnitState mState;
//状态控制器
protected BaseStateController mCtrl;
//移动对象
protected Transform mTrans;
//事件
protected EventArgs mEvent;
//单位类
protected BaseUnit mUnit;
#endregion
#region 方法
public State(UnitState state, Hashtable ht)
{
this.mState = state;
if (ht.ContainsKey("mUnit"))
this.mUnit = ht["mUnit"] as BaseUnit;
if (ht.ContainsKey("mCtrl"))
this.mCtrl = ht["mCtrl"] as StateController;
if (ht.ContainsKey("mTrans"))
this.mTrans = ht["mTrans"] as Transform;
if (ht.ContainsKey("mEvent"))
this.mEvent = ht["mEvent"] as EventArgs;
}
/// <summary>
/// 状态行为
/// </summary>
public abstract void Action();
/// <summary>
/// 状态切换
/// </summary>
public abstract void Change();
/// <summary>
/// 进入状态的行为
/// </summary>
public virtual void EnterState() { }
/// <summary>
/// 离开状态的行为
/// </summary>
public virtual void ExitState() { }
#endregion
}
状态控制器基类
public class BaseStateController {
#region 字段
//当前状态
public BaseState currentState;
//用字典存储所有状态
public Dictionary<UnitState, BaseState > stateList = new Dictionary<UnitState, BaseState >();
#endregion
#region 方法
public StateController(Hashtable ht = null)
{
}
/// <summary>
/// 添加状态
/// </summary>
/// <param name="state"></param>
public void AddState(BaseState state)
{
stateList.Add(state.mState,state);
if (currentState == null)
currentState = state;
}
/// <summary>
/// 切换状态
/// </summary>
/// <param name="name"></param>
public void ChangeState(UnitState state)
{
if (stateList.ContainsKey(state))
{
currentState.ExitState();
currentState = stateList[state];
currentState.EnterState();
}
}
/// <summary>
/// 实时调用
/// </summary>
public void OnUpdate()
{
currentState.Action();
currentState.Change();
}
#endregion
}
BaseUnit
public class UnitBuildBase : MonoBehaviour {
//生命值
public float mHP;
//当前生命值
public float mCurHp;
//单位名称
public string mName;
//单位阵营
public Camp mCamp;
//寻路节点
public Node mNode;
/// <summary>
/// 受到攻击
/// </summary>
/// <param name="damage"></param>
public virtual void BeAttack(float damage)
{
}
//死亡
public virtual void BeDead()
{
}
}
BaseUnitController
public class BuildUnitCtrl : MonoBehaviour {
//状态控制器
public StateController mCtrl;
//事件参数
public EventArgs mEvent = new EventArgs();
//往状态机中传参
public Hashtable ht = new Hashtable();
public virtual void Init()
{
}
public virtual void Start()
{
}
public virtual void Update()
{
if (mCtrl != null)
mCtrl.OnUpdate();
}
/// <summary>
/// 检测是否有敌方单位进入攻击范围
/// </summary>
/// <param name="other"></param>
public virtual void OnTriggerEnter(Collider other)
{
}
}