add sniper
This commit is contained in:
@@ -7,6 +7,7 @@ using BITKit.Animations;
|
||||
using BITKit.StateMachine;
|
||||
using System.Linq;
|
||||
using System.Security.Permissions;
|
||||
using AYellowpaper.SerializedCollections;
|
||||
using BITFALL;
|
||||
using BITFALL.Entities.Equipment;
|
||||
using BITFALL.Player.Equip;
|
||||
@@ -23,6 +24,9 @@ namespace BITKit.Entities
|
||||
[Header(Constant.Header.Settings)]
|
||||
[SerializeField] protected AssetableItem item;
|
||||
|
||||
[Header(Constant.Header.Property)]
|
||||
[SerializeField] public SerializedDictionary<string,AnimationProperty> animationProperties;
|
||||
|
||||
[Header(Constant.Header.Components)]
|
||||
[SerializeField] public UnityAnimator animator;
|
||||
[SerializeField] protected EntityVFXPlayer vfxPlayer;
|
||||
@@ -36,6 +40,8 @@ namespace BITKit.Entities
|
||||
public Entities.IEntity Entity { get; set; }
|
||||
public Entity UnityEntity=>Entity as Entity;
|
||||
public IBasicItem Item { get; set; }
|
||||
|
||||
public IDictionary<string,float> AnimationProperties => animationProperties.ToDictionary(x=>x.Key,x=>x.Value.Value);
|
||||
|
||||
public readonly InputActionGroup inputActionGroup = new()
|
||||
{
|
||||
@@ -49,6 +55,9 @@ namespace BITKit.Entities
|
||||
|
||||
public virtual void Entry()
|
||||
{
|
||||
if (animator)
|
||||
animator.enabled = true;
|
||||
|
||||
AllowRendering.AddElement(this);
|
||||
inputActionGroup.allowInput.AddElement(this);
|
||||
|
||||
@@ -79,6 +88,7 @@ namespace BITKit.Entities
|
||||
|
||||
inputActionGroup.allowInput.RemoveElement(this);
|
||||
}
|
||||
|
||||
public virtual UniTask ExitAsync()
|
||||
{
|
||||
AllowRendering.RemoveElement(this);
|
||||
@@ -87,16 +97,17 @@ namespace BITKit.Entities
|
||||
cameraTransform.localPosition = default;
|
||||
cameraTransform.localRotation = _initialCameraRotation;
|
||||
}
|
||||
|
||||
if (animator)
|
||||
animator.enabled = false;
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
public virtual void OnAwake()
|
||||
{
|
||||
AllowRendering.AddListener(x => renderers.ForEach(y =>
|
||||
{
|
||||
y.enabled = x;
|
||||
animator.enabled = x;
|
||||
}));
|
||||
AllowRendering.AddListener(x => renderers.ForEach(y => { y.enabled = x; }));
|
||||
if (animator)
|
||||
animator.enabled = false;
|
||||
AllowRendering.Invoke();
|
||||
if (cameraTransform is not null)
|
||||
_initialCameraRotation = cameraTransform.localRotation;
|
||||
@@ -152,13 +163,16 @@ namespace BITKit.Entities
|
||||
public class EntityEquipment : EntityBehavior,IEquipService,IEntityEquipment
|
||||
{
|
||||
public IOptional<float> Zoom { get; } = new Optional<float>(){Value = 1};
|
||||
|
||||
public float InitialFov;
|
||||
public float Stable { get; set; }
|
||||
public bool AllowAttack { get; set; }
|
||||
public bool AllowScope { get; set; }
|
||||
|
||||
[SerializeField] private CinemachineVirtualCamera virtualCamera;
|
||||
|
||||
[SerializeField] private Optional<int> overrideIndex;
|
||||
|
||||
[SerializeField] private AnimationCurve zoomCurve;
|
||||
|
||||
public event Action<IBasicItem> OnEquip;
|
||||
public event Action<IBasicItem> OnUnEquip;
|
||||
public event Action<string> OnEquipAddressable;
|
||||
@@ -230,10 +244,7 @@ namespace BITKit.Entities
|
||||
|
||||
if (virtualCamera is not null)
|
||||
{
|
||||
var current = virtualCamera.m_Lens.FieldOfView;
|
||||
current= Mathf.Lerp(current,Zoom.Allow ? InitialFov / Zoom.Value : PlayerConfig.Singleton.Fov , deltaTime * 5);
|
||||
current = Mathf.Clamp(current, 10, PlayerConfig.Singleton.Fov);
|
||||
virtualCamera.m_Lens.FieldOfView = current;
|
||||
virtualCamera.m_Lens.FieldOfView =zoomCurve.Evaluate(Zoom.Allow?Zoom.Value:0);
|
||||
}
|
||||
|
||||
if (overrideIndex.Allow && (_health?.IsAlive ?? true))
|
||||
|
@@ -51,13 +51,15 @@ namespace BITKit.Entities
|
||||
}
|
||||
private void Melee(int _damage)
|
||||
{
|
||||
var forward = Transform.forward;
|
||||
meleeService.Melee(new MeleeCommand()
|
||||
{
|
||||
PlayerId = Entity.Id,
|
||||
Position = Transform.position + Vector3.up,
|
||||
Force = Transform.forward * 128,
|
||||
Force = forward * 128,
|
||||
Range = 1.6f,
|
||||
Damage = _damage,
|
||||
Forward = forward
|
||||
});
|
||||
unityAnimator.Play("Attack");
|
||||
//entity.Invoke(Constant.Animation.Play, "Melee");
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using BITFALL.Guns.States;
|
||||
using BITFALL.Player.Equip;
|
||||
using BITFALL.Player.Movement;
|
||||
using UnityEngine;
|
||||
using BITKit;
|
||||
@@ -78,9 +79,6 @@ namespace BITFALL.Guns
|
||||
|
||||
// 引用预制体
|
||||
[Header(Constant.Header.Prefabs)]
|
||||
[SerializeField] internal AssetableGun assetable;
|
||||
[Header(Constant.Header.Reference)]
|
||||
|
||||
// 内部变量burst
|
||||
[Header(Constant.Header.InternalVariables)]
|
||||
public ExpectState<bool> expectFiring;
|
||||
@@ -94,12 +92,16 @@ namespace BITFALL.Guns
|
||||
private IPlayerMovement _playerMovement;
|
||||
[Inject]
|
||||
private IHealth _health;
|
||||
|
||||
[Inject] private IEquipService _equipService;
|
||||
private static readonly int IsGrounded = Animator.StringToHash("IsGrounded");
|
||||
private AssetableGun _gun=>item as AssetableGun;
|
||||
private bool isHolstered;
|
||||
|
||||
public bool RequireBolt { get; set; }
|
||||
|
||||
#region 接口实现
|
||||
public override string AddressablePath => assetable.AddressablePath;
|
||||
public override string AddressablePath => _gun.AddressablePath;
|
||||
#endregion
|
||||
|
||||
public override void OnAwake()
|
||||
@@ -166,10 +168,10 @@ namespace BITFALL.Guns
|
||||
expectFiring.Reset();
|
||||
Enabled = true;
|
||||
|
||||
fireInterval.Interval = 1f / assetable.FireMode.FireRate;
|
||||
fireInterval.Interval = 1f / _gun.FireMode.FireRate;
|
||||
fireInterval.Reset();
|
||||
|
||||
if (assetable.FireMode is BurstFireMode burstFireMode)
|
||||
if (_gun.FireMode is BurstFireMode burstFireMode)
|
||||
{
|
||||
burstFireInterval.Interval = burstFireMode.BurstFireInterval;
|
||||
burstFireInterval.Reset();
|
||||
@@ -183,6 +185,9 @@ namespace BITFALL.Guns
|
||||
public override async UniTask ExitAsync()
|
||||
{
|
||||
TransitionState<Holster>();
|
||||
|
||||
_equipService.AllowAttack = false;
|
||||
|
||||
inputActionGroup.allowInput.RemoveElement(this);
|
||||
expectFiring.Reset();
|
||||
|
||||
@@ -193,11 +198,17 @@ namespace BITFALL.Guns
|
||||
while (_health.IsAlive && isHolstered is false)
|
||||
{
|
||||
destroyCancellationToken.ThrowIfCancellationRequested();
|
||||
_equipService.Zoom.Value = Mathf.MoveTowards(_equipService.Zoom.Value,0,Time.deltaTime);
|
||||
await UniTask.NextFrame();
|
||||
}
|
||||
|
||||
_equipService.Zoom.Allow = false;
|
||||
|
||||
destroyCancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
_equipService.Stable = 1;
|
||||
|
||||
|
||||
await base.ExitAsync();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -208,7 +219,7 @@ namespace BITFALL.Guns
|
||||
public override void OnUpdate(float deltaTime)
|
||||
{
|
||||
UpdateState(deltaTime);
|
||||
switch (assetable.FireMode)
|
||||
switch (_gun.FireMode)
|
||||
{
|
||||
case AutoFireMode:
|
||||
break;
|
||||
@@ -218,7 +229,13 @@ namespace BITFALL.Guns
|
||||
expectFiring.shouldBe = fireAction.action.WasPressedThisFrame();
|
||||
if(burstFireInterval.AllowUpdate)
|
||||
{
|
||||
Fire();
|
||||
switch (AnimationProperties.TryGetValue(BITConstant.Player.AllowFire, out var allowFire))
|
||||
{
|
||||
case false:
|
||||
case true when allowFire >0.9f:
|
||||
Fire();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -229,6 +246,25 @@ namespace BITFALL.Guns
|
||||
recoilSpring.Update(deltaTime,default);
|
||||
|
||||
locationAdditive.AddEuler(recoilSpring.value);
|
||||
|
||||
if(AnimationProperties.TryGetValue(BITConstant.Player.Aim, out var _aim))
|
||||
{
|
||||
_equipService.Zoom.Allow = CurrentState is Aim;
|
||||
_equipService.Zoom.Value =Mathf.Lerp(0,_gun.InitialAimZoom, _aim);
|
||||
_equipService.AllowScope = _aim > 0.86f && _gun.IsScopeAim;
|
||||
}
|
||||
|
||||
if (AnimationProperties.TryGetValue(BITConstant.Player.Stable, out var stable))
|
||||
{
|
||||
_equipService.Stable = stable;
|
||||
}
|
||||
|
||||
if(AnimationProperties.TryGetValue(BITConstant.Player.AllowFire, out var _allowFire))
|
||||
{
|
||||
_equipService.AllowAttack = _allowFire > 0.9f;
|
||||
}
|
||||
|
||||
AllowRendering.SetDisableElements(64564,_equipService.AllowScope);
|
||||
}
|
||||
|
||||
public override void AnimationEvent(string eventName)
|
||||
@@ -250,6 +286,7 @@ namespace BITFALL.Guns
|
||||
}
|
||||
public void Fire()
|
||||
{
|
||||
if (RequireBolt) return;
|
||||
//如果启用了指针则不开火
|
||||
if(BITAppForUnity.AllowCursor)
|
||||
{
|
||||
@@ -273,7 +310,7 @@ namespace BITFALL.Guns
|
||||
});
|
||||
|
||||
//开火模式逻辑判断
|
||||
switch (assetable.FireMode)
|
||||
switch (_gun.FireMode)
|
||||
{
|
||||
case AutoFireMode:
|
||||
break;
|
||||
@@ -291,7 +328,7 @@ namespace BITFALL.Guns
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (assetable.TryGetProperty<IRecoil>(out var _recoil))
|
||||
if (_gun.TryGetProperty<IRecoil>(out var _recoil))
|
||||
{
|
||||
var _newRecoil = new Vector3
|
||||
{
|
||||
@@ -302,11 +339,15 @@ namespace BITFALL.Guns
|
||||
recoilSpring.value = _newRecoil;
|
||||
_playerMovement.AddViewEuler(new float2(_newRecoil.x,_newRecoil.y));
|
||||
}
|
||||
|
||||
|
||||
if (_gun.FireMode is SemiFireMode {RequireBoltAction:true})
|
||||
{
|
||||
RequireBolt = true;
|
||||
}
|
||||
}
|
||||
private void OnFire(InputAction.CallbackContext context)
|
||||
{
|
||||
switch (assetable.FireMode)
|
||||
switch (_gun.FireMode)
|
||||
{
|
||||
case AutoFireMode :
|
||||
switch (context)
|
||||
|
@@ -7,6 +7,7 @@ using BITKit.Selection;
|
||||
using UnityEngine.InputSystem;
|
||||
using BITKit.StateMachine;
|
||||
using UnityEngine;
|
||||
// ReSharper disable UnassignedField.Local
|
||||
|
||||
namespace BITFALL.Guns.States
|
||||
{
|
||||
@@ -19,6 +20,8 @@ namespace BITFALL.Guns.States
|
||||
{
|
||||
[SerializeField] private ExpectState<bool> _expectRun;
|
||||
[Inject] protected ISelector _selector;
|
||||
private float elapsedTime;
|
||||
private bool boltActionImmediately;
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
switch (old)
|
||||
@@ -31,14 +34,17 @@ namespace BITFALL.Guns.States
|
||||
break;
|
||||
}
|
||||
_selector.OnActive += OnActive;
|
||||
boltActionImmediately = root.RequireBolt;
|
||||
}
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
{
|
||||
elapsedTime = 0;
|
||||
base.OnStateExit(old, newState);
|
||||
_selector.OnActive -= OnActive;
|
||||
}
|
||||
public override void OnStateUpdate(float deltaTime)
|
||||
{
|
||||
elapsedTime += deltaTime;
|
||||
if (root.animator[0].stateName is not BITConstant.Player.Movement) return;
|
||||
if (root.expectFiring.shouldBe && root.fireInterval.AllowUpdate)
|
||||
{
|
||||
@@ -50,6 +56,9 @@ namespace BITFALL.Guns.States
|
||||
}else if (_expectRun)
|
||||
{
|
||||
root.TransitionState<Run>();
|
||||
}else if (root.RequireBolt && elapsedTime > 0.5f || boltActionImmediately)
|
||||
{
|
||||
root.TransitionState<Reload>();
|
||||
}
|
||||
}
|
||||
public void OnActive(ISelectable selectable)
|
||||
@@ -146,8 +155,6 @@ namespace BITFALL.Guns.States
|
||||
[System.Serializable]
|
||||
public sealed class Aim : GunState
|
||||
{
|
||||
[Inject]
|
||||
private IEquipService _equipService;
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
switch (old)
|
||||
@@ -160,7 +167,6 @@ namespace BITFALL.Guns.States
|
||||
root.animator.CrossFade(BITConstant.Player.Aim, 0.16f);
|
||||
break;
|
||||
}
|
||||
_equipService.Zoom.Allow = true;
|
||||
_entityMovement.ExecuteCommand<PlayerCancelRunCommand>();
|
||||
}
|
||||
|
||||
@@ -183,13 +189,6 @@ namespace BITFALL.Guns.States
|
||||
{
|
||||
root.TransitionState<Movement>();
|
||||
}
|
||||
_equipService.Zoom.Value = root.aimAction.action.ReadValue<float>();
|
||||
}
|
||||
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
{
|
||||
base.OnStateExit(old, newState);
|
||||
_equipService.Zoom.Allow = false;
|
||||
}
|
||||
|
||||
public override void OnMovementStateChanged(IEntityMovementState old, IEntityMovementState newState)
|
||||
@@ -260,8 +259,16 @@ namespace BITFALL.Guns.States
|
||||
base.OnStateEntry(old);
|
||||
|
||||
_entityMovement.ExecuteCommand<PlayerCancelRunCommand>();
|
||||
|
||||
root.UnityEntity.Invoke(Constant.Animation.Play, BITConstant.Player.Reload);
|
||||
|
||||
if (root.RequireBolt)
|
||||
{
|
||||
root.UnityEntity.Invoke(Constant.Animation.Play, BITConstant.Player.BoltAction);
|
||||
}
|
||||
else
|
||||
{
|
||||
root.UnityEntity.Invoke(Constant.Animation.Play, BITConstant.Player.Reload);
|
||||
}
|
||||
|
||||
}
|
||||
public override void OnMovementStateChanged(IEntityMovementState old, IEntityMovementState newState)
|
||||
{
|
||||
@@ -271,8 +278,13 @@ namespace BITFALL.Guns.States
|
||||
root.TransitionState<Movement>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
{
|
||||
root.RequireBolt = false;
|
||||
base.OnStateExit(old, newState);
|
||||
}
|
||||
}
|
||||
[System.Serializable]
|
||||
public sealed class Melee : GunState
|
||||
{
|
||||
|
@@ -50,6 +50,8 @@ namespace BITFALL.Guns
|
||||
[System.Serializable]
|
||||
public record SemiFireMode : FireMode
|
||||
{
|
||||
[SerializeField] private bool requireBoltAction;
|
||||
public bool RequireBoltAction => requireBoltAction;
|
||||
}
|
||||
/// <summary>
|
||||
/// 爆炸射击模式 BurstRound为爆炸开火时一次发射的子弹数量
|
||||
@@ -63,26 +65,20 @@ namespace BITFALL.Guns
|
||||
public int BurstRound=> brustRound;
|
||||
public float BurstFireInterval => burstFireInterval;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资产化武器配置
|
||||
/// </summary>
|
||||
|
||||
[System.Serializable]
|
||||
public record ArrowFireMode : FireMode
|
||||
{
|
||||
|
||||
}
|
||||
public class AssetableGun : AssetableEquip
|
||||
{
|
||||
[Header(nameof(AssetableGun))]
|
||||
[SerializeReference, SubclassSelector] protected IFireMode fireMode;
|
||||
[SerializeReference, SubclassSelector] protected IFireMode fireMode = new AutoFireMode();
|
||||
[SerializeField] private int initialDamage;
|
||||
[SerializeField] private int initialBulletForce;
|
||||
[SerializeField] private int initialBulletSpeed = 128;
|
||||
[SerializeField] private int initialAimZoom = 1;
|
||||
[SerializeField] private bool isScopeAim;
|
||||
public IFireMode FireMode => fireMode;
|
||||
public int InitialBulletForce => initialBulletForce;
|
||||
public int InitialDamage => initialDamage;
|
||||
public int InitialBulletSpeed => initialBulletSpeed;
|
||||
public int InitialAimZoom => initialAimZoom;
|
||||
public bool IsScopeAim => isScopeAim;
|
||||
}
|
||||
}
|
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using BITKit;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Cysharp.Threading.Tasks.Triggers;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
|
||||
@@ -31,6 +33,20 @@ namespace BITFALL.Props
|
||||
if (root is not null && root.gameObject.isStatic is false)
|
||||
{
|
||||
instance.SetParentConstraint(root);
|
||||
var destroyToken = root.gameObject.GetCancellationTokenOnDestroy();
|
||||
destroyToken.Register(() =>
|
||||
{
|
||||
if (!instance) return;
|
||||
if (instance.TryGetComponent<ParentConstraint>(out var constraint))
|
||||
{
|
||||
Destroy(constraint);
|
||||
}
|
||||
|
||||
if (instance.TryGetComponent<Rigidbody>(out var instanceRigidbody))
|
||||
{
|
||||
instanceRigidbody.isKinematic = false;
|
||||
}
|
||||
});
|
||||
if (_rigidbody is not null)
|
||||
{
|
||||
//_rigidbody.isKinematic = true;
|
||||
|
@@ -19,6 +19,7 @@ namespace BITFALL.Props
|
||||
private void Start()
|
||||
{
|
||||
initialEulerAngles = transform.localEulerAngles;
|
||||
spring.value = initialEulerAngles;
|
||||
}
|
||||
private void FixedUpdate()
|
||||
{
|
||||
|
@@ -30,6 +30,7 @@ namespace BITFALL.UX
|
||||
[SerializeField] private UXLabel seleableLabel;
|
||||
[SerializeField] private UXImage crosshairImage;
|
||||
[SerializeField] private UXImage crosshairParentImage;
|
||||
[SerializeField] private UXImage scopeImage;
|
||||
[SerializeField] private UXLabel playerNameLabel;
|
||||
[SerializeField] private UXImage playerAvatarImage;
|
||||
[SerializeField] private UXElement playerInfo;
|
||||
@@ -139,8 +140,17 @@ namespace BITFALL.UX
|
||||
lerpHealthBar.SetDirect(_currentHealthLerp,_health.HealthPoint.ToString());
|
||||
|
||||
staminaBar.Set(_playerMovement.Stamina * 0.01f);
|
||||
|
||||
|
||||
staminaBar.visualElement.parent.SetActive(_playerMovement.Stamina is not 100);
|
||||
|
||||
crosshairImage.visualElement.SetActive(_equipService.AllowAttack);
|
||||
|
||||
scopeImage.SetActive(_equipService.AllowScope);
|
||||
|
||||
crosshairImage.visualElement.transform.scale =
|
||||
Vector3.one *
|
||||
Mathf.Lerp(1.25f, 1, _equipService.Stable);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user