BITFALL/Assets/Artists/Scripts/Equip/BITGun.cs

214 lines
6.6 KiB
C#
Raw Normal View History

2023-06-08 14:09:50 +08:00
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BITKit;
using BITKit.Entities;
using UnityEngine.UIElements;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Interactions;
using BITKit.Animations;
using BITKit.StateMachine;
using Net.Client;
using Unity.Mathematics;
using UnityEngine.VFX;
using System.Diagnostics;
using BITFALL.Guns;
namespace BITFALL
{
public interface IGunState : IState { }
[System.Serializable]
public abstract class GunState : IGunState
{
public BITGun root;
public virtual void Initialize()
{
}
public virtual void OnStateEnter(IState old)
{
}
public virtual void OnStateExit(IState old, IState newState)
{
}
public virtual void OnStateUpdate()
{
}
public virtual void OnMovementCallback(IMovementCallback callback) { }
}
[System.Serializable]
public class GunStateMachine : MonoStateMachine<GunState> { }
public class BITGun : BITEquipBase<GunState>
{
// 常数引用
public const string _Movement = "Movement";
public const string _Run = "Run";
public const string _Aim = "Aim";
public const string _Interactive = "Interactive";
public const string _Equip = "Equip";
public const string _Fire = "Fire";
// 输入系统
[Header(Constant.Header.Input)]
public InputActionReference fireAction;
public InputActionReference aimAction;
public InputActionGroup actionGroup = new();
// 状态机
[Header(Constant.Header.State)]
public GunStateMachine stateMachine;
// 引用组件
[Header(Constant.Header.Components)]
public Renderer[] rendererComponents;
public VFXPlayer vfxPlayer;
// 引用预制体
[Header(Constant.Header.Prefabs)]
public AssetableGun assetable;
[Header(Constant.Header.Reference)]
// 内部变量
[Header(Constant.Header.InternalVariables)]
public ExpectState<bool> isFiring;
public ExpectState<bool> isAiming;
internal IntervalUpdate fireUpdater = new(0.32f);
internal IntervalUpdate brustFireUpdater = new(0.1f);
internal int burstFireCount;
#region
public override string AddressablePath => assetable.AdressablePath;
#endregion
public override void Entry()
{
animator.animator.enabled = true;
actionGroup.allowInput.SetElements(this, true);
foreach (var x in rendererComponents)
{
x.enabled = true;
}
isFiring.Reset();
stateMachine.StateMachine.TransitionState(stateMachine.states[0]);
entity.AddListener<IMovementCallback>(OnMovementCallback);
fireUpdater.updateInterval = 1f / assetable.FireMode.FireRate;
fireUpdater.Reset();
if(assetable.FireMode is BurstFireMode burstFireMode)
{
brustFireUpdater.updateInterval = burstFireMode.BurstFireInterval;
brustFireUpdater.Reset();
}
}
public override void Exit()
{
actionGroup.allowInput.SetElements(this, false);
foreach (var x in rendererComponents)
{
x.enabled = false;
}
isFiring.Reset();
animator.animator.enabled = false;
entity.RemoveListener<IMovementCallback>(OnMovementCallback);
}
public override void OnAwake()
{
actionGroup.RegisterCallback(fireAction, OnFire);
actionGroup.RegisterCallback(aimAction, OnAim);
stateMachine.OnStart();
}
public override void OnStart()
{
base.OnStart();
foreach (var x in rendererComponents)
{
x.enabled = false;
}
}
public override void OnUpdate(float deltaTime)
{
stateMachine?.CurrentState?.OnStateUpdate();
if(assetable.FireMode is BurstFireMode && isFiring.being)
{
if(brustFireUpdater)
{
Fire();
}
}
}
public void Fire()
{
//如果启用了指针则不开火
if(BITAppForUnity.AllowCursor)
{
return;
}
//播放射击动画
animator.Play(BITGun._Fire);
//调用IMovementCancenAction接口取消奔跑或冲刺
Entity.Invoke<IMovementCancelAction>(new CancelRunOrSprint());
//调用BulletManager生成子弹
BulletService.Spawn(new()
{
initiator = entity.Id,
pos = transform.position.Fix(),
rot = transform.rotation,
forward = transform.forward.Fix(),
//pos=transform.position,
//rot=transform.rotation,
});
//播放枪口MuzzleFlash
vfxPlayer.Excute();
//开火模式逻辑判断
switch (assetable.FireMode)
{
case AutoFireMode:
break;
case SemiFireMode:
//如果是半自动开火,则取消射击
isFiring.Reset();
break;
case BurstFireMode burstFireMode:
burstFireCount++;
isFiring.being = true;
if(burstFireCount > burstFireMode.BurstRound)
{
burstFireCount = 0;
isFiring.Reset();
}
break;
}
}
void OnFire(InputAction.CallbackContext context)
{
switch (assetable.FireMode)
{
case AutoFireMode:
case SemiFireMode:
isFiring.shouldBe = context.ReadValueAsButton();
break;
case BurstFireMode:
if(isFiring.being is false)
isFiring.shouldBe = context.ReadValueAsButton();//|| context.action.triggered;
break;
}
}
void OnAim(InputAction.CallbackContext context)
{
isAiming.shouldBe = context.ReadValueAsButton();
}
void OnMovementCallback(IMovementCallback callback)
{
stateMachine?.CurrentState?.OnMovementCallback(callback);
}
}
}