云计算百科
云计算领域专业知识百科平台

游戏技能编辑器之状态机的设计与实现

状态机系统概述

在游戏开发中,状态机是控制角色行为逻辑的核心系统。本文基于提供的代码,分析技能编辑器中状态机系统的设计与实现,特别是如何通过状态机管理复杂的技能逻辑。

状态机核心组件

1. 状态基类设计 (FSMStateBase)

状态基类是所有具体状态的父类,定义了状态的基本行为:

class FSMStateBase {
public:
virtual void enter(); // 进入状态
virtual void update(uint32 dwElapsed); // 更新状态
virtual void exit(); // 退出状态
virtual void refreshState() {}; // 刷新状态

protected:
CUnit *m_pUnit; // 关联的游戏单位
std::string m_strPresentationName; // 当前状态的表现名称
};

2. 状态机模板 (Fsm)

状态机模板类负责管理状态注册和状态切换:

template<typename classname, typename statetype, typename EVTID, typename PARAM>
class Fsm {
public:
void SetState(statetype state) {
// 退出当前状态
if (m_stateFunc.find(m_state) != m_stateFunc.end()) {
m_stateFunc[m_state].pBase->exit();
}

// 进入新状态
m_last_state = m_state;
m_state = state;

if (m_stateFunc.find(m_state) != m_stateFunc.end()) {
m_stateFunc[m_state].pBase->enter();
}
}

void RegisterStateFunc(statetype state, FSMStateBase* cls) {
m_stateFunc[state].pBase = cls;
}

void Update(float diff) {
if (m_stateFunc.find(m_state) != m_stateFunc.end()) {
m_stateFunc[m_state].pBase->update(diff);
}
}

private:
statetype m_state; // 当前状态
statetype m_last_state; // 上一个状态
MapStateFunc m_stateFunc; // 状态映射表
};

具体状态实现

1. 待机状态 (FSMStateStandBy)

void FSMStateStandBy::enter() {
Base::enter();
ref_ptr<CPresentationAction> p = m_pUnit->playStandbyPresentation();
if (p) {
Base::setPresentation(p->GetName());
}
}

void FSMStateStandBy::update(uint32 dwElapsed) {
Base::update(dwElapsed);
this->updateStandby(dwElapsed);
}

2. 移动状态 (FSMStateMove)

void FSMStateMove::enter() {
Base::enter();
ref_ptr<CPresentationAction> p = m_pUnit->playMovePresentation();
if (p) {
Base::setPresentation(p->GetName());
}
}

void FSMStateMove::update(uint32 dwElapsed) {
Base::update(dwElapsed);
this->updateMove(dwElapsed);
}

3. 受击状态 (FSMStateHitted)

void FSMStateHitted::enter() {
Base::enter();
ref_ptr<CPresentationAction> p = m_pUnit->playHittedPresentation();
if (p) {
Base::setPresentation(p->GetName());
}

// 特殊受击类型处理
switch (mHittedType) {
case zhuge_chuifeng:
zhugeChuifengAction.readyToMove();
break;
}
}

void FSMStateHitted::update(uint32 dwElapsed) {
Base::update(dwElapsed);

// 处理特殊受击类型的位移
switch (mHittedType) {
case zhuge_chuifeng:
zhugeChuifengAction.move(dwElapsed);
break;
}
}

4. 技能状态 (FSMStateSkill)

void FSMStateSkill::enter() {
Base::enter();

// 获取技能数据
S_SKILL *skillData = getData();

// 播放技能表现
ref_ptr<CPresentationAction> pa = gSPConditonMgr->getPresentationBySkillData(skillData);
if (pa) {
Base::setPresentation(pa->GetName());

// 注册回调
pa->OnStopSignal.notify(this, &FSMStateBase::OnStop);
pa->OnFrameEventSignal.notify(this, &FSMStateBase::OnFrame);

// 设置技能数据
pa->SetUserData("SKILL_DATA", Any(skillData));
}
}

void FSMStateSkill::exit() {
// 清理技能相关状态
if (m_pUnit->isStatusById(IgnoreRTSRelation)) {
m_pUnit->delStatusById(IgnoreRTSRelation);
}

Base::exit();
}

状态转换机制

1. 状态切换流程

2. 事件驱动的状态转换

// 注册事件处理
void RegisterEvt(statetype state, EVTID evt, classname* cls,
statetype(classname::*f)(statetype, EVTID, PARAM))
{
EvtProc& proc = m_mapTrans[state][evt];
proc.notifyFunc.cls = cls;
proc.notifyFunc.imp = f;
}

// 事件分发
void DispatchEvent(EVTID evt, PARAM pms) {
// 查找当前状态的事件处理
auto itS = m_mapTrans.find(m_state);
if (itS != m_mapTrans.end()) {
auto itE = itS->second.find(evt);
if (itE != itS->second.end()) {
// 执行事件处理函数并切换状态
SetState((itE->second.notifyFunc.cls->*itE->second.notifyFunc.imp)
(m_state, evt, pms));
return;
}
}
}

 

技能编辑器集成

1. 状态机在编辑器中的可视化

在技能编辑器中,状态机可以直观地展示:

[状态机视图] | 当前状态: 技能状态 (STATE_SKILL_1) | |————————————| | 可转换状态:                        | |   – 待机状态 (STATE_STANDBY)       | |   – 移动状态 (STATE_MOVE)          | |   – 受击状态 (STATE_HITTED)        | |   – 死亡状态 (STATE_DEAD)          | |                                    | | 事件列表:                          | |   [动画事件] 帧事件(100): 触发伤害 | |   [动画事件] 结束事件: 返回待机    |

2. 状态与技能时间轴的关联

在技能编辑器中,状态切换可以与时间轴上的关键帧关联:

{
"tracks": [
{
"type": "State",
"keyframes": [
{"time": 0.0, "state": "STATE_SKILL_1"},
{"time": 2.5, "state": "STATE_STANDBY"}
]
}
]
}

3. 状态机调试功能

技能编辑器提供状态机调试工具:

  • 状态切换历史记录

  • 当前状态变量查看

  • 事件触发模拟

  • 断点调试功能

高级特性实现

1. 状态过渡机制

void FSMStateMove::enter() {
// 检查是否可以进入过渡状态
if (m_pUnit->canEnterTransitionToMove(m_pUnit->getLastFsmPrt())) {
m_pUnit->setFsmState(STATE_TRANSITION_MOVE);
return;
}

// 否则进入普通移动状态
Base::enter();
}

2. 动画事件驱动状态切换

void RegisterAniEvt(statetype state, EVENT_ANI_E aniEvent,
statetype retState)
{
AniEvtProc& proc = m_mapAniTrans[state][aniEvent];
proc.retState = retState;
}

void DispatchAniEvent(EVENT_ANI_E evt, CPresentationAction* anim, int param) {
auto itS = m_mapAniTrans.find(m_state);
if (itS != m_mapAniTrans.end()) {
auto itE = itS->second.find(evt);
if (itE != itS->second.end()) {
SetState(itE->second.retState); // 切换到新状态
}
}
}

3. 状态特定的资源管理

void FSMStateDead::enter() {
// 根据角色类型加载不同的死亡表现
if (m_pUnit->isStatusById(Ghost)) {
m_pUnit->doPressentation("ghost_dead");
} else {
m_pUnit->doPressentation("enter_dead");
m_pUnit->doPressentation("enter_dead_effect");
}
}

性能优化策略

1. 状态对象池

class StatePool {
public:
FSMStateBase* Acquire(StateType type) {
if (pool[type].empty()) {
return CreateState(type);
}
auto state = pool[type].back();
pool[type].pop_back();
return state->Reset();
}

void Release(FSMStateBase* state) {
pool[state->GetType()].push_back(state);
}

private:
std::map<StateType, std::vector<FSMStateBase*>> pool;
};

2. 状态切换优化

// 避免不必要的状态切换
void SetState(statetype newState) {
if (m_state == newState) {
// 仅刷新状态,不执行完整切换
if (m_stateFunc.find(m_state) != m_stateFunc.end()) {
m_stateFunc[m_state].pBase->refreshState();
}
return;
}
// 执行完整状态切换…
}

3. 基于状态的LOD优化

void FSMStateBase::update(uint32 dwElapsed) {
// 根据距离相机的距离调整更新频率
float distance = Camera::Main()->DistanceTo(m_pUnit->Position);
if (distance > LOD_DISTANCE) {
// 低细节更新,每3帧更新一次
if (frameCount % 3 == 0) {
UpdateLOD(dwElapsed * 3);
}
} else {
// 全细节更新
UpdateFull(dwElapsed);
}
frameCount++;
}

总结

本文详细分析了技能编辑器中状态机系统的设计与实现,核心要点包括:

  • 分层状态架构:

    • 基础状态机模板提供核心状态管理功能

    • 具体状态实现游戏逻辑(待机、移动、技能等)

    • 状态过渡机制实现平滑切换

  • 事件驱动设计:

    • 支持普通事件和动画事件驱动状态转换

    • 灵活的事件注册和分发机制

    • 时间轴关键帧与状态绑定

  • 编辑器集成:

    • 可视化状态机编辑

    • 状态与技能表现关联

    • 实时调试和模拟功能

  • 性能优化:

    • 状态对象池减少内存分配

    • LOD策略按需更新

    • 避免冗余状态切换

  • 这种状态机设计为技能编辑器提供了强大的逻辑控制能力,使设计师能够创建复杂的技能行为,同时保持代码的可维护性和运行时性能。

    最佳实践建议:在技能编辑器中实现状态机时,重点考虑:

  • 状态划分的粒度 – 不宜过细也不宜过粗

  • 状态转换的可视化调试支持

  • 与时间轴编辑器的深度集成

  • 状态机的版本兼容性和序列化方案

  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » 游戏技能编辑器之状态机的设计与实现
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!