using System.Linq; using BITFALL.Guns.States; using UnityEngine; using BITKit; using BITKit.Entities; using UnityEngine.InputSystem; using BITKit.StateMachine; #if UNITY_EDITOR using UnityEditor; #endif namespace BITFALL { public interface IGunState : IState { } [System.Serializable] public abstract class GunState : IGunState { public BITGun root; private IEntityMovement _entityMovement; public bool Enabled { get;set; } public virtual void Initialize() { _entityMovement = root.Entity.Get(); _entityMovement.OnStateChanged += OnMovementStateChanged; } public virtual void OnStateEntry(IState old) { } public virtual void OnStateExit(IState old, IState newState) { } public virtual void OnStateUpdate() { } public virtual void OnMovementStateChanged(IEntityMovementState old, IEntityMovementState newState) { } } [System.Serializable] public class GunStateMachine : MonoStateMachine { } public class BITGun : BITEquipBase { // 常数引用 public const string _Movement = "Movement"; public const string _Run = "Run"; public const string _Sprint = "Sprint"; public const string _Aim = "Aim"; public const string _Interactive = "Interactive"; public const string _Equip = "Equip"; public const string _Fire = "Fire"; public const string _Reload = "Reload"; // 输入系统 [Header(Constant.Header.Input)] public InputActionReference fireAction; public InputActionReference aimAction; public InputActionReference reloadAction; public InputActionGroup actionGroup = new(); // 引用组件 [Header(Constant.Header.Components)] public Renderer[] rendererComponents; public VFXPlayer vfxPlayer; // 引用预制体 [Header(Constant.Header.Prefabs)] public AssetableGun assetable; [Header(Constant.Header.Reference)] // 内部变量burst [Header(Constant.Header.InternalVariables)] public ExpectState expectFiring; public ExpectState expectAiming; internal readonly IntervalUpdate fireInterval = new(0.32f); internal readonly IntervalUpdate burstFireInterval = new(0.1f); internal int burstFireCount; #region 接口实现 public override string AddressablePath => assetable.AdressablePath; #endregion public override void OnAwake() { base.OnAwake(); actionGroup.RegisterCallback(fireAction, OnFire); actionGroup.RegisterCallback(aimAction, OnAim); actionGroup.RegisterCallback(reloadAction, OnReload); entity.Get().OnStateChanged += OnMovementStateChanged; } private void OnReload(InputAction.CallbackContext obj) { TransitionState(); } private void OnMovementStateChanged(IEntityMovementState arg1, IEntityMovementState arg2) { foreach (var x in StateDictionary.Values) { x.OnMovementStateChanged(arg1,arg2); } } public override void OnStart() { base.OnStart(); foreach (var x in rendererComponents) { x.enabled = false; } } public override void Entry() { base.Entry(); animator.animator.enabled = true; actionGroup.allowInput.AddElement(this); foreach (var x in rendererComponents) { x.enabled = true; } expectFiring.Reset(); Enabled = true; fireInterval.Interval = 1f / assetable.FireMode.FireRate; fireInterval.Reset(); if (assetable.FireMode is BurstFireMode burstFireMode) { burstFireInterval.Interval = burstFireMode.BurstFireInterval; burstFireInterval.Reset(); } TransitionState(StateDictionary.First().Value); } public override void Exit() { actionGroup.allowInput.RemoveElement(this); foreach (var x in rendererComponents) { x.enabled = false; } expectFiring.Reset(); animator.animator.enabled = false; } public override void OnUpdate(float deltaTime) { CurrentState?.OnStateUpdate(); if(assetable.FireMode is BurstFireMode && expectFiring.being) { if(burstFireInterval.AllowUpdate) { Fire(); } } } public void Fire() { //如果启用了指针则不开火 if(BITAppForUnity.AllowCursor) { return; } //播放射击动画 animator.Play(BITGun._Fire); //调用BulletManager生成子弹 var _transform = transform; BulletService.Spawn(new SpawnBullet { initiator = entity.Id, pos = _transform.position.Fix(), rot = _transform.rotation, forward = transform.forward.Fix(), initialDamage = 32, }); //播放枪口MuzzleFlash vfxPlayer.Execute(); //开火模式逻辑判断 switch (assetable.FireMode) { case AutoFireMode: break; case SemiFireMode: //如果是半自动开火,则取消射击 expectFiring.Reset(); break; case BurstFireMode burstFireMode: burstFireCount++; expectFiring.being = true; if(burstFireCount > burstFireMode.BurstRound) { burstFireCount = 0; expectFiring.Reset(); } break; } } private void OnFire(InputAction.CallbackContext context) { switch (assetable.FireMode) { case AutoFireMode: case SemiFireMode: expectFiring.shouldBe = context.ReadValueAsButton(); break; case BurstFireMode: if(expectFiring.being is false) expectFiring.shouldBe = context.ReadValueAsButton();//|| context.action.triggered; break; } } private void OnAim(InputAction.CallbackContext context) { expectAiming.shouldBe = context.ReadValueAsButton(); } } #if UNITY_EDITOR [CustomEditor(typeof(BITGun))] public class BITGunInspector:BITInspector{} #endif }