武器系统:数据驱动 + 状态机 📅 2026/8/20 15:50:57 一、整体架构设计数据驱动 状态机是武器系统的经典组合方案两者职责分明数据驱动定义武器是什么属性、配置状态机控制武器怎么运行行为逻辑┌─────────────────────────────────────┐ │ 武器实例 (Weapon) │ ├─────────────────┬───────────────────┤ │ 数据层 │ 逻辑层 │ │ (WeaponData) │ (StateMachine) │ └─────────────────┴───────────────────┘二、数据驱动部分1. 武器配置数据结构[CreateAssetMenu(menuNameWeapon/WeaponData)]publicclassWeaponData:ScriptableObject{[Header(基础信息)]publicstringweaponId;publicstringweaponName;publicWeaponTypetype;// 手枪/步枪/霰弹枪...[Header(伤害属性)]publicfloatdamage10f;publicfloatcritMultiplier2f;publicfloatrange100f;[Header(射击参数)]publicfloatfireRate0.1f;// 射击间隔publicFireModefireMode;// 单发/连发/点射publicintburstCount3;// 点射数量[Header(弹药系统)]publicintmagazineSize30;// 弹匣容量publicintmaxAmmo300;// 总备弹publicfloatreloadTime2f;// 换弹时间[Header(后坐力)]publicfloatrecoilVertical1f;publicfloatrecoilHorizontal0.5f;[Header(表现资源)]publicGameObjectmuzzleFlashPrefab;publicAudioClipfireSound;publicAnimationClipreloadAnim;}publicenumFireMode{Single,Auto,Burst}publicenumWeaponType{Pistol,Rifle,Shotgun,Sniper}2. 数据驱动的优势优势说明策划友好数值配置无需改代码Excel/表格导入快速迭代修改属性立即生效无需重编译复用性高同一套逻辑驱动上百种武器热更新数据可独立于代码更新三、状态机部分1. 武器状态定义publicenumWeaponStateType{Idle,// 待机Firing,// 射击中Reloading,// 换弹中Equipping,// 切换/装备Empty// 弹药耗尽}2. 状态转换图┌──────────┐ ┌───→│ Idle │←──────┐ │ └────┬─────┘ │ │ │ 开火 │ 换弹完成 │ ▼ │ │ ┌──────────┐ ┌──────────┐ │ │ Firing │ │Reloading │ │ └────┬─────┘ └────▲─────┘ │ │ 弹匣空 │ R键/自动 │ ▼ │ │ ┌──────────┐ │ └────│ Empty │───────┘ 拾取弹药 └──────────┘3. 状态机基础实现// 状态基类publicabstractclassWeaponState{protectedWeaponweapon;protectedWeaponDatadataweapon.Data;publicWeaponState(Weaponweapon)this.weaponweapon;publicvirtualvoidOnEnter(){}publicvirtualvoidOnUpdate(floatdt){}publicvirtualvoidOnExit(){}// 处理输入返回是否切换状态publicabstractvoidHandleInput(WeaponInputinput);}// 状态机管理器publicclassWeaponStateMachine{privateWeaponStatecurrentState;privateDictionaryWeaponStateType,WeaponStatestates;publicWeaponStateTypeCurrentType{get;privateset;}publicvoidInitialize(Weaponweapon){statesnewDictionaryWeaponStateType,WeaponState{{WeaponStateType.Idle,newIdleState(weapon)},{WeaponStateType.Firing,newFiringState(weapon)},{WeaponStateType.Reloading,newReloadingState(weapon)},{WeaponStateType.Empty,newEmptyState(weapon)},};ChangeState(WeaponStateType.Idle);}publicvoidChangeState(WeaponStateTypetype){currentState?.OnExit();CurrentTypetype;currentStatestates[type];currentState.OnEnter();}publicvoidUpdate(floatdt)currentState?.OnUpdate(dt);publicvoidHandleInput(WeaponInputinput)currentState?.HandleInput(input);}四、具体状态实现示例1. 待机状态publicclassIdleState:WeaponState{publicIdleState(Weaponw):base(w){}publicoverridevoidHandleInput(WeaponInputinput){// 弹匣为空 → 强制换弹或进入Emptyif(weapon.CurrentAmmo0){weapon.StateMachine.ChangeState(WeaponStateType.Empty);return;}if(input.Fire)weapon.StateMachine.ChangeState(WeaponStateType.Firing);elseif(input.Reloadweapon.CanReload())weapon.StateMachine.ChangeState(WeaponStateType.Reloading);}}2. 射击状态核心publicclassFiringState:WeaponState{privatefloatfireTimer;privateintburstShotCount;publicFiringState(Weaponw):base(w){}publicoverridevoidOnEnter(){fireTimer0;burstShotCount0;Fire();// 立即射击第一发}publicoverridevoidOnUpdate(floatdt){fireTimerdt;switch(data.fireMode){caseFireMode.Auto:if(fireTimerdata.fireRateweapon.Input.Fire)Fire();break;caseFireMode.Burst:if(fireTimerdata.fireRateburstShotCountdata.burstCount)Fire();elseif(burstShotCountdata.burstCount)weapon.StateMachine.ChangeState(WeaponStateType.Idle);break;caseFireMode.Single:// 单发射击完成即返回weapon.StateMachine.ChangeState(WeaponStateType.Idle);break;}}privatevoidFire(){if(weapon.CurrentAmmo0){weapon.StateMachine.ChangeState(WeaponStateType.Empty);return;}fireTimer0;burstShotCount;weapon.CurrentAmmo--;// 执行射击逻辑数据驱动weapon.PerformShoot(data.damage,data.range);weapon.ApplyRecoil(data.recoilVertical,data.recoilHorizontal);weapon.PlayFireEffects();// 使用 data 中的特效/音效}publicoverridevoidHandleInput(WeaponInputinput){// Auto模式松开开火键返回Idleif(data.fireModeFireMode.Auto!input.Fire)weapon.StateMachine.ChangeState(WeaponStateType.Idle);}}3. 换弹状态publicclassReloadingState:WeaponState{privatefloatreloadTimer;publicReloadingState(Weaponw):base(w){}publicoverridevoidOnEnter(){reloadTimer0;weapon.PlayReloadAnim(data.reloadAnim);}publicoverridevoidOnUpdate(floatdt){reloadTimerdt;if(reloadTimerdata.reloadTime){weapon.DoReload();// 计算并填充弹药weapon.StateMachine.ChangeState(WeaponStateType.Idle);}}publicoverridevoidHandleInput(WeaponInputinput){// 换弹中通常不响应开火也可实现取消换弹}}五、武器主类整合publicclassWeapon:MonoBehaviour{[SerializeField]privateWeaponDatadata;publicWeaponDataDatadata;publicWeaponStateMachineStateMachine{get;privateset;}publicWeaponInputInput{get;privateset;}publicintCurrentAmmo{get;set;}publicintReserveAmmo{get;set;}voidAwake(){StateMachinenewWeaponStateMachine();StateMachine.Initialize(this);CurrentAmmodata.magazineSize;ReserveAmmodata.maxAmmo;}voidUpdate(){InputGatherInput();StateMachine.HandleInput(Input);StateMachine.Update(Time.deltaTime);}publicboolCanReload()CurrentAmmodata.magazineSizeReserveAmmo0;publicvoidDoReload(){intneeddata.magazineSize-CurrentAmmo;intactualMathf.Min(need,ReserveAmmo);CurrentAmmoactual;ReserveAmmo-actual;}publicvoidPerformShoot(floatdamage,floatrange){/* 射线检测 */}publicvoidApplyRecoil(floatv,floath){/* 后坐力 */}publicvoidPlayFireEffects(){/* 特效音效 */}publicvoidPlayReloadAnim(AnimationClipclip){/* 播放动画 */}privateWeaponInputGatherInput()newWeaponInput{/* ... */};}六、进阶优化建议1. 配置分层WeaponData (基础配置) ├── AttachmentData (配件系统瞄准镜/枪管) ├── UpgradeData (升级系统) └── SkinData (皮肤外观)2. 状态机增强分层状态机主状态射击 子状态瞄准/腰射状态优先级换弹 射击防止状态冲突过渡条件表将转换规则也数据化3. 事件解耦publiceventActionintOnAmmoChanged;publiceventActionOnFire;publiceventActionOnReloadStart;// UI、音效、成就系统订阅事件不直接耦合七、方案总结设计要点实现方式数据与逻辑分离WeaponData 存数值State 存行为一套逻辑通用不同武器仅换 WeaponData状态清晰可控有限状态机管理武器行为流转易扩展新增状态/武器类型成本低易调试状态可视化问题定位快