1
This commit is contained in:
@@ -15,7 +15,9 @@
|
||||
"GUID:bea3628e8b592ae47ade218cb9ec98db",
|
||||
"GUID:f822dbf6fdfd4a5469cccaa2e4eed3b6",
|
||||
"GUID:a3de65b07192e7d49bad7b4032d681de",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:f6155d9ae143f3949ac54e8355593d6c",
|
||||
"GUID:21d1eb854b91ade49bc69a263d12bee2"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
@@ -1,13 +1,17 @@
|
||||
using System;
|
||||
using System.Security.Permissions;
|
||||
using System.Timers;
|
||||
using BITFALL.Entities.Player.Movement.States;
|
||||
using BITFALL.Player.Movement;
|
||||
using BITKit;
|
||||
using BITKit.Entities;
|
||||
using BITKit.Entities.Movement;
|
||||
using BITKit.Entities.Physics;
|
||||
using BITKit.Entities.Player;
|
||||
using Lightbug.CharacterControllerPro.Core;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Interactions;
|
||||
using UnityEngine.UIElements;
|
||||
@@ -16,9 +20,8 @@ namespace BITFALL.Entities.Player.Movement
|
||||
{
|
||||
[CustomType(typeof(IEntityMovement))]
|
||||
[CustomType(typeof(IPlayerMovement))]
|
||||
public class PlayerCharacterController : StateBasedPlayerComponent<IEntityMovementState>,IEntityMovement,IServiceRegister,IPlayerMovement
|
||||
public class PlayerCharacterController : StateBasedPlayerComponent<IEntityMovementState>,IEntityMovement,IPlayerMovement
|
||||
{
|
||||
public override Type BaseType => typeof(IEntityMovement);
|
||||
[SerializeField] private CharacterActor actor;
|
||||
[SerializeField] private Vector3 initialCameraPosition = new(0,0.11f,0.27f);
|
||||
[SerializeField] private float initialSpeed;
|
||||
@@ -29,6 +32,8 @@ namespace BITFALL.Entities.Player.Movement
|
||||
private IProvider adsProvider;
|
||||
|
||||
[SerializeField] private LocationAdditive locationAdditive;
|
||||
|
||||
[SerializeField] private Transform fpvPoint;
|
||||
|
||||
public Vector3 ViewCenter { get; set; }
|
||||
public Quaternion ViewRotation { get; set; }
|
||||
@@ -42,32 +47,48 @@ namespace BITFALL.Entities.Player.Movement
|
||||
public Vector2 LookInput{ get; private set; }
|
||||
public ExpectState<bool> ExpectRun;
|
||||
public ExpectState<bool> ExpectJump;
|
||||
public ExpectState<bool> ExpectParachute;
|
||||
public ExpectState<bool> ExpectCrouch;
|
||||
public ExpectState<bool> ExpectSprint;
|
||||
public ExpectState<Vector3> ExpectClimb;
|
||||
public ExpectState<Vector3> CurrentCameraPosition;
|
||||
public OffMeshLink OffMeshLink { get; private set; }
|
||||
|
||||
[Header(Constant.Header.Gameobjects)]
|
||||
[SerializeField] private Transform parachuteModel;
|
||||
|
||||
private readonly ValidHandle allowMovement = new();
|
||||
private readonly ValidHandle allowRun = new();
|
||||
[Inject]
|
||||
private IEntityPhysics physics;
|
||||
[Inject]
|
||||
private IHealth _health;
|
||||
|
||||
private bool isDead;
|
||||
private Vector3 keepVelocity;
|
||||
private readonly DoubleBuffer<Vector3> gravityDamage = new();
|
||||
private readonly DoubleBuffer<float> gravityDamping = new();
|
||||
private Vector3 cacheGravity;
|
||||
|
||||
public override void OnAwake()
|
||||
{
|
||||
_health = entity.Get<IHealth>();
|
||||
base.OnAwake();
|
||||
_health.OnSetAlive += OnSetAlive;
|
||||
physics = entity.Get<IEntityPhysics>();
|
||||
physics.OnSetPhysics += OnSetPhysics;
|
||||
LookInput = MathV.TransientRotationAxis(transform.rotation.eulerAngles);
|
||||
|
||||
parachuteModel.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
foreach (var x in GetComponentsInChildren<Collider>(true))
|
||||
{
|
||||
actor.PhysicsComponent.IgnoreCollision(x.transform,true);
|
||||
}
|
||||
}
|
||||
TransitionState<Walk>();
|
||||
}
|
||||
|
||||
private void OnSetPhysics(bool obj)
|
||||
{
|
||||
if (obj is false) return;
|
||||
@@ -89,6 +110,8 @@ namespace BITFALL.Entities.Player.Movement
|
||||
{
|
||||
isDead = true;
|
||||
}
|
||||
Enabled = true;
|
||||
TransitionState<Walk>();
|
||||
}
|
||||
public void SyncMovement(Vector3 velocity, Vector3 position, Quaternion rotation, bool isGrounded)
|
||||
{
|
||||
@@ -123,6 +146,12 @@ namespace BITFALL.Entities.Player.Movement
|
||||
case PlayerDisableRunCommand disableRunCommand:
|
||||
allowRun.AddDisableElements(disableRunCommand.Lock);
|
||||
break;
|
||||
case PlayerChangeVelocityCommand changeVelocityCommand:
|
||||
actor.Velocity = Vector3.Lerp(actor.Velocity, changeVelocityCommand.Velocity, 5 * Time.deltaTime);
|
||||
break;
|
||||
case PlayerAddGravityDampingCommand addGravityDampingCommand:
|
||||
gravityDamping.Release(addGravityDampingCommand.Damping);
|
||||
break;
|
||||
}
|
||||
OnCommand?.Invoke(command);
|
||||
}
|
||||
@@ -140,6 +169,26 @@ namespace BITFALL.Entities.Player.Movement
|
||||
lookInput.y += raw.x;
|
||||
lookInput.x = Mathf.Clamp(lookInput.x, -80, 80);
|
||||
LookInput = lookInput;
|
||||
|
||||
var rotation = Quaternion.Euler(LookInput);
|
||||
if (LimitViewAngle is not 0)
|
||||
{
|
||||
float angleDifference = Quaternion.Angle(rotation, FpvRotation);
|
||||
|
||||
// 如果角度差大于最大允许角度差,进行限制
|
||||
if (angleDifference > LimitViewAngle)
|
||||
{
|
||||
//将当前旋转限制在最大允许角度差的范围内
|
||||
rotation = Quaternion.Lerp(
|
||||
rotation,
|
||||
Quaternion.RotateTowards(FpvRotation,rotation , LimitViewAngle),
|
||||
5 * Time.deltaTime
|
||||
);
|
||||
//rotation = Quaternion.RotateTowards(FpvRotation, rotation, LimitViewAngle);
|
||||
|
||||
LookInput = MathV.TransientRotationAxis(rotation.eulerAngles);
|
||||
}
|
||||
}
|
||||
|
||||
AngularVelocity = new Vector3
|
||||
(
|
||||
@@ -150,29 +199,70 @@ namespace BITFALL.Entities.Player.Movement
|
||||
public void Jump(InputAction.CallbackContext context)
|
||||
{
|
||||
if (ExpectJump.shouldBe) return;
|
||||
if (context.interaction is not null && context.started is false) return;
|
||||
if (actor.IsGrounded)
|
||||
ExpectJump.shouldBe = true;
|
||||
ExpectCrouch.Reset();
|
||||
if (climbClosePoint.TryGetClosePoint(out var closePoint))
|
||||
if (context is not {interaction:PressInteraction , performed:true}) return;
|
||||
|
||||
switch (CurrentState)
|
||||
{
|
||||
ExpectClimb.shouldBe = closePoint;
|
||||
TransitionState<Climb>();
|
||||
case IPlayerLinkState:
|
||||
ExpectJump.shouldBe = true;
|
||||
break;
|
||||
case IPlayerWalkState:
|
||||
case IPlayerRunState:
|
||||
case IPlayerSprintState:
|
||||
case IPlayerCrouchState:
|
||||
case IPlayerSlideState:
|
||||
foreach (var x in Physics.OverlapSphere(actor.Position, 1, LayerMask.GetMask("Dynamic")))
|
||||
{
|
||||
if (!x.TryGetComponent<OffMeshLink>(out var offMeshLink)) continue;
|
||||
var toTarget = x.transform.position - transform.position;
|
||||
toTarget = Vector3.ProjectOnPlane(toTarget, Vector3.up);
|
||||
|
||||
// 获取正前方的向量
|
||||
var forward = actor.Forward;
|
||||
|
||||
// 计算点积
|
||||
var dotProduct = Vector3.Dot(toTarget.normalized, forward);
|
||||
|
||||
if (dotProduct < 0.8f) continue;
|
||||
|
||||
OffMeshLink = offMeshLink;
|
||||
TransitionState<Link>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (climbClosePoint.TryGetClosePoint(out var closePoint))
|
||||
{
|
||||
ExpectClimb.shouldBe = closePoint;
|
||||
TransitionState<Climb>();
|
||||
return;
|
||||
}
|
||||
switch (actor.IsGrounded)
|
||||
{
|
||||
case true:
|
||||
ExpectJump.shouldBe = true;
|
||||
break;
|
||||
case false when actor.VerticalVelocity.y<=-16f:
|
||||
ExpectParachute.shouldBe = true;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ExpectCrouch.Reset();
|
||||
}
|
||||
public void Run(InputAction.CallbackContext context)
|
||||
{
|
||||
if (allowRun.Allow is false) return;
|
||||
switch (context)
|
||||
{
|
||||
case { interaction: PressInteraction, started: true }:
|
||||
//case { interaction: PressInteraction, started: true }:
|
||||
case { interaction: PressInteraction, performed:true }:
|
||||
if (ExpectRun.shouldBe)
|
||||
ExpectSprint.shouldBe = true;
|
||||
ExpectRun.shouldBe = true;
|
||||
ExpectCrouch.Reset();
|
||||
break;
|
||||
case {interaction:MultiTapInteraction,performed:true}:
|
||||
ExpectSprint.shouldBe = true;
|
||||
ExpectSprint.shouldBe = ExpectRun.shouldBe = true;
|
||||
ExpectCrouch.Reset();
|
||||
break;
|
||||
}
|
||||
@@ -197,6 +287,8 @@ namespace BITFALL.Entities.Player.Movement
|
||||
{
|
||||
CurrentState?.BeforeUpdateMovement(deltaTime);
|
||||
|
||||
UpdateState(deltaTime);
|
||||
|
||||
CurrentState?.AfterUpdateMovement(deltaTime);
|
||||
}
|
||||
|
||||
@@ -204,12 +296,21 @@ namespace BITFALL.Entities.Player.Movement
|
||||
{
|
||||
var currentVelocity = actor.Velocity;
|
||||
var currentRotation = actor.Rotation;
|
||||
CurrentState.OnStateUpdate(deltaTime);
|
||||
|
||||
if (Stamina is not 100 && staminaRecoveryInterval.AllowUpdateWithoutReset)
|
||||
{
|
||||
Stamina+=10 * deltaTime;
|
||||
}
|
||||
|
||||
CurrentState?.UpdateVelocity(ref currentVelocity, deltaTime);
|
||||
CurrentState?.UpdateRotation(ref currentRotation, deltaTime);
|
||||
|
||||
if (gravityDamping.TryGetRelease(out var damping) && currentVelocity.y < 0)
|
||||
{
|
||||
currentVelocity.y = Mathf.Clamp(currentVelocity.y + damping, float.MinValue, 0);
|
||||
}
|
||||
|
||||
if (allowMovement && _health.IsAlive)
|
||||
if (allowMovement && _health.IsAlive && actor.RigidbodyComponent.IsKinematic is false)
|
||||
{
|
||||
actor.Velocity = currentVelocity;
|
||||
actor.Rotation = currentRotation;
|
||||
@@ -220,14 +321,69 @@ namespace BITFALL.Entities.Player.Movement
|
||||
var localVelocity = transform.InverseTransformDirection(Velocity);
|
||||
localVelocity.y = 0;
|
||||
LocomotionBasedVelocity = localVelocity;
|
||||
}
|
||||
|
||||
|
||||
if(actor.IsStable is false && actor.IsGrounded is false)
|
||||
{
|
||||
if (cacheGravity != default && (actor.VerticalVelocity - cacheGravity).sqrMagnitude < 4)
|
||||
{
|
||||
gravityDamage.Release(actor.VerticalVelocity);
|
||||
}
|
||||
cacheGravity = actor.VerticalVelocity;
|
||||
//Debug.Log($"IsGround:{actor.IsGrounded}\tIsStable:{actor.IsStable}\tVelocity:{actor.VerticalVelocity}");
|
||||
}
|
||||
else if (actor.IsStable && gravityDamage.TryGetRelease(out var currentGravity))
|
||||
{
|
||||
cacheGravity = default;
|
||||
var value = currentGravity.y;
|
||||
//Debug.Log($"Vector:{currentVelocity}\tMagnitude:{value}\tGravity:{currentGravity}");
|
||||
//Debug.Log(value);
|
||||
switch (value)
|
||||
{
|
||||
case > 0:
|
||||
break;
|
||||
case < -16:
|
||||
entity.Invoke<DamageMessage>(new DamageMessage()
|
||||
{
|
||||
damage = value < -30 ? int.MaxValue : (int)math.abs(value) * 2 ,
|
||||
damageType = new GravityDamage(),
|
||||
location = new Location()
|
||||
{
|
||||
position = actor.Position,
|
||||
rotation = actor.Rotation
|
||||
},
|
||||
initiator = entity,
|
||||
target = entity,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public override void OnLateUpdate(float deltaTime)
|
||||
{
|
||||
if (allowMovement.Allow is false) return;
|
||||
var additiveTransform = locationAdditive.transform;
|
||||
|
||||
var rotation = Quaternion.Euler(LookInput);
|
||||
|
||||
if (LimitViewAngle is not 0)
|
||||
{
|
||||
float angleDifference = Quaternion.Angle(rotation, FpvRotation);
|
||||
|
||||
// 如果角度差大于最大允许角度差,进行限制
|
||||
if (angleDifference > LimitViewAngle)
|
||||
{
|
||||
// 将当前旋转限制在最大允许角度差的范围内
|
||||
rotation = Quaternion.Lerp(
|
||||
rotation,
|
||||
Quaternion.RotateTowards(FpvRotation,rotation , LimitViewAngle),
|
||||
5 * deltaTime
|
||||
);
|
||||
|
||||
LookInput = MathV.TransientRotationAxis(rotation.eulerAngles);
|
||||
}
|
||||
}
|
||||
|
||||
locationAdditive.SetGlobalRotation(rotation);
|
||||
|
||||
@@ -239,6 +395,27 @@ namespace BITFALL.Entities.Player.Movement
|
||||
|
||||
ViewCenter = additiveTransform.position + additiveTransform.forward;
|
||||
}
|
||||
private float _stamina = 100;
|
||||
public float Stamina
|
||||
{
|
||||
get=>_stamina;
|
||||
set
|
||||
{
|
||||
if (value < _stamina)
|
||||
{
|
||||
staminaRecoveryInterval.Reset();
|
||||
}
|
||||
_stamina = Mathf.Clamp(value, 0, 100);
|
||||
OnStaminaChanged?.Invoke(_stamina);
|
||||
}
|
||||
}
|
||||
private readonly IntervalUpdate staminaRecoveryInterval = new(1);
|
||||
public int LimitViewAngle { get; set; }
|
||||
public event Action<float> OnStaminaChanged;
|
||||
public float3 FpvPosition => fpvPoint.position;
|
||||
public quaternion FpvRotation => fpvPoint.rotation;
|
||||
public float3 FpvLocalPosition =>fpvPoint.localPosition;
|
||||
public quaternion FpvLocalRotation => fpvPoint.localRotation;
|
||||
|
||||
public void AddViewEuler(float2 euler)
|
||||
{
|
||||
@@ -248,6 +425,20 @@ namespace BITFALL.Entities.Player.Movement
|
||||
y = LookInput.y + euler.y
|
||||
};
|
||||
}
|
||||
public event Func<bool> TryOpenParachute;
|
||||
public event Action OnParachuteOpened;
|
||||
public event Action OnParachuteClosed;
|
||||
|
||||
internal void InvokeOpenParachute()
|
||||
{
|
||||
OnParachuteOpened?.Invoke();
|
||||
parachuteModel.gameObject.SetActive(true);
|
||||
}
|
||||
internal void InvokeCloseParachute()
|
||||
{
|
||||
OnParachuteClosed?.Invoke();
|
||||
parachuteModel.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,3 +1,4 @@
|
||||
using BITFALL.Player.Movement;
|
||||
using BITKit.Entities;
|
||||
using BITKit.StateMachine;
|
||||
using Lightbug.CharacterControllerPro.Core;
|
||||
@@ -9,13 +10,16 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
{
|
||||
[SerializeField] protected PlayerCharacterController characterController;
|
||||
[SerializeField] protected CharacterActor actor;
|
||||
private IEntityMovementState entryState;
|
||||
public bool Enabled { get; set; }
|
||||
public virtual void Initialize()
|
||||
{
|
||||
characterController.entity.Inject(this);
|
||||
}
|
||||
|
||||
public virtual void OnStateEntry(IState old)
|
||||
{
|
||||
entryState=old is IPlayerRunState or IPlayerSprintState ? old as IEntityMovementState: null;
|
||||
}
|
||||
|
||||
public virtual void OnStateUpdate(float deltaTime)
|
||||
@@ -44,5 +48,16 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
public virtual void ExecuteCommand<T>(T command)
|
||||
{
|
||||
}
|
||||
protected virtual void Exit()
|
||||
{
|
||||
if (entryState is not null && entryState is IEntityMovementState state)
|
||||
{
|
||||
characterController.TransitionState(state);
|
||||
}
|
||||
else
|
||||
{
|
||||
characterController.TransitionState<Walk>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using BITFALL.Entities.Player.Movement.States;
|
||||
using BITFALL.Player.Movement;
|
||||
using BITKit;
|
||||
using BITKit.StateMachine;
|
||||
using Lightbug.CharacterControllerPro.Core;
|
||||
using UnityEngine;
|
||||
@@ -12,15 +13,25 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
{
|
||||
public abstract class BasicMovement : PlayerCharacterState,IPlayerMovementState
|
||||
{
|
||||
|
||||
[SerializeField] protected Vector3 initialCameraPosition;
|
||||
[SerializeField] protected float initialSpeed = 3f;
|
||||
[SerializeField] protected float initialJumpForce = 5f;
|
||||
[Inject] protected IKnockdown knockdown;
|
||||
|
||||
public override void BeforeUpdateMovement(float deltaTime)
|
||||
{
|
||||
characterController.CurrentCameraPosition.shouldBe = initialCameraPosition;
|
||||
}
|
||||
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
if (knockdown.IsKnockdown is false && characterController.ExpectParachute.shouldBe)
|
||||
{
|
||||
characterController.TransitionState<Parachute>();
|
||||
characterController.ExpectParachute.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateVelocity(ref Vector3 currentVelocity,float deltaTime)
|
||||
{
|
||||
var rotation = Quaternion.Euler(0,characterController.LookInput.y,0);
|
||||
@@ -107,6 +118,7 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
base.AfterUpdateMovement(deltaTime);
|
||||
switch (characterController.ExpectRun.shouldBe,characterController.ExpectCrouch.shouldBe)
|
||||
{
|
||||
case (_,true):
|
||||
@@ -118,6 +130,51 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class Parachute : PlayerCharacterState, IPlayerParachuteState
|
||||
{
|
||||
[SerializeField] private float moveDamping = 3f;
|
||||
[SerializeField] private float damping = 1f;
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
characterController.InvokeOpenParachute();
|
||||
}
|
||||
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
{
|
||||
characterController.InvokeCloseParachute();
|
||||
}
|
||||
|
||||
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
|
||||
{
|
||||
currentRotation = Quaternion.Euler(0,characterController.LookInput.y,0);
|
||||
}
|
||||
|
||||
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
var rotation = Quaternion.Euler(0,characterController.LookInput.y,0);
|
||||
var moveVelocity = rotation * characterController.MovementInput;
|
||||
currentVelocity.y =
|
||||
Mathf.MoveTowards(
|
||||
currentVelocity.y,
|
||||
-8,
|
||||
damping * deltaTime
|
||||
);
|
||||
currentVelocity+= moveVelocity.normalized * (moveDamping * deltaTime);
|
||||
currentVelocity.x = Mathf.Clamp(currentVelocity.x, -moveDamping, moveDamping);
|
||||
currentVelocity.z = Mathf.Clamp(currentVelocity.z, -moveDamping, moveDamping);
|
||||
}
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
if (actor.IsGrounded)
|
||||
{
|
||||
characterController.TransitionState<Walk>();
|
||||
}
|
||||
characterController.ExpectParachute.Reset();
|
||||
characterController.CurrentCameraPosition.shouldBe = characterController.FpvLocalPosition;
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public sealed class Run:BasicMovement,IPlayerRunState
|
||||
{
|
||||
@@ -133,6 +190,7 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
base.AfterUpdateMovement(deltaTime);
|
||||
if (characterController.ExpectSprint.shouldBe)
|
||||
{
|
||||
characterController.TransitionState<Sprint>();
|
||||
@@ -157,9 +215,65 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class Slide : BasicMovement, IPlayerSlideState
|
||||
{
|
||||
[Header(nameof(Slide))]
|
||||
[SerializeField] private float additiveSpeed = 1f;
|
||||
[SerializeField] private float damping = 1;
|
||||
[SerializeField] private float stopSpeed = 0.64f;
|
||||
[SerializeField] private bool alwaysSlide;
|
||||
private bool _addedVelocity;
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
characterController.ExpectCrouch.being = true;
|
||||
characterController.ExpectCrouch.shouldBe = true;
|
||||
_addedVelocity = false;
|
||||
}
|
||||
|
||||
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
if (alwaysSlide && actor.IsGrounded is false)
|
||||
{
|
||||
base.UpdateVelocity(ref currentVelocity, deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_addedVelocity is false)
|
||||
{
|
||||
currentVelocity += currentVelocity.normalized * additiveSpeed;
|
||||
_addedVelocity = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentVelocity = Vector3.Lerp(currentVelocity, Vector3.zero, deltaTime * damping);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
if (characterController.ExpectRun.shouldBe)
|
||||
{
|
||||
characterController.TransitionState<Run>();
|
||||
return;
|
||||
}
|
||||
if (characterController.ExpectCrouch.shouldBe is false || (alwaysSlide is false && actor.IsGrounded is false))
|
||||
{
|
||||
characterController.TransitionState<Walk>();
|
||||
return;
|
||||
}
|
||||
if (actor.Velocity.sqrMagnitude <= stopSpeed)
|
||||
{
|
||||
characterController.TransitionState<Crouch>();
|
||||
}
|
||||
characterController.CurrentCameraPosition.shouldBe = characterController.FpvLocalPosition;
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public sealed class Crouch:BasicMovement,IPlayerCrouchState
|
||||
{
|
||||
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
characterController.ExpectCrouch.being = true;
|
||||
@@ -171,6 +285,7 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
}
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
base.AfterUpdateMovement(deltaTime);
|
||||
if (characterController.ExpectRun.shouldBe)
|
||||
{
|
||||
characterController.TransitionState<Run>();
|
||||
@@ -187,19 +302,33 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
[Serializable]
|
||||
public sealed class Sprint:BasicMovement,IPlayerSprintState
|
||||
{
|
||||
[SerializeField] private int slideCost = 16;
|
||||
[SerializeField] private int staminaCost = 1;
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
characterController.ExpectSprint.being = true;
|
||||
}
|
||||
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
{
|
||||
characterController.ExpectSprint.being = false;
|
||||
}
|
||||
public override void OnStateUpdate(float deltaTime)
|
||||
{
|
||||
characterController.Stamina -= staminaCost * deltaTime;
|
||||
}
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
base.AfterUpdateMovement(deltaTime);
|
||||
switch (characterController.ExpectRun.shouldBe,characterController.ExpectCrouch.shouldBe)
|
||||
{
|
||||
case (_,_) when characterController.Stamina is 0:
|
||||
characterController.ExpectSprint.Reset();
|
||||
characterController.TransitionState<Run>();
|
||||
break;
|
||||
case (_,true) when characterController.IsGrounded && characterController.Stamina >= slideCost:
|
||||
characterController.Stamina -= slideCost;
|
||||
characterController.TransitionState<Slide>();
|
||||
break;
|
||||
case (_,true):
|
||||
characterController.TransitionState<Crouch>();
|
||||
break;
|
||||
@@ -215,4 +344,25 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
characterController.TransitionState<Walk>();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class Knockdown : BasicMovement, IPlayerKnockdownState
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
knockdown.OnKnockdown += OnKnockdown;
|
||||
knockdown.OnRevive += OnRevive;
|
||||
}
|
||||
|
||||
private void OnRevive()
|
||||
{
|
||||
if(Enabled)characterController.TransitionState<Walk>();
|
||||
}
|
||||
|
||||
private void OnKnockdown()
|
||||
{
|
||||
characterController.TransitionState<Knockdown>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,28 +1,46 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Linq;
|
||||
using BITFALL.Player.Movement;
|
||||
using BITKit;
|
||||
using BITKit.Entities;
|
||||
using BITKit.Selection;
|
||||
using BITKit.StateMachine;
|
||||
using JetBrains.Annotations;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
using UnityEngine.Splines;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BITFALL.Entities.Player.Movement.States
|
||||
{
|
||||
[Serializable]
|
||||
public class Climb : PlayerCharacterState,IPlayerClimbState
|
||||
{
|
||||
|
||||
[SerializeField] protected float lerpDelta = 5;
|
||||
private IntervalUpdate cancelInterval = new(0.16f);
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
base.OnStateEntry(old);
|
||||
actor.alwaysNotGrounded = true;
|
||||
actor.ForceNotGrounded();
|
||||
actor.ColliderComponent.enabled = false;
|
||||
cancelInterval.Reset();
|
||||
}
|
||||
public override void OnStateUpdate(float deltaTime)
|
||||
{
|
||||
if (Vector3.Distance(characterController.ExpectClimb.shouldBe, characterController.transform.position) < 0.1f || actor.IsStable)
|
||||
var distance = Vector3.Distance(characterController.ExpectClimb.shouldBe,
|
||||
characterController.transform.position);
|
||||
if (
|
||||
distance<=0.16f
|
||||
|| actor.IsStable
|
||||
|| cancelInterval.AllowUpdate && actor.Velocity.sqrMagnitude<=0.16f
|
||||
)
|
||||
{
|
||||
characterController.TransitionState<Walk>();
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
@@ -37,6 +55,254 @@ namespace BITFALL.Entities.Player.Movement.States
|
||||
{
|
||||
currentVelocity =(characterController.ExpectClimb.shouldBe - characterController.transform.position)*lerpDelta;
|
||||
}
|
||||
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
characterController.CurrentCameraPosition.shouldBe = characterController.FpvLocalPosition;
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public sealed class Link:PlayerCharacterState,IPlayerLinkState
|
||||
{
|
||||
public int LinkArea { get; private set; }
|
||||
private OffMeshLink _offMeshLink;
|
||||
private ISplineContainer _splineContainer;
|
||||
private float progress;
|
||||
private float increment;
|
||||
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
base.OnStateEntry(old);
|
||||
|
||||
characterController.ExpectCrouch.Reset();
|
||||
|
||||
characterController.ExpectJump.Reset();
|
||||
|
||||
actor.ForceNotGrounded();
|
||||
|
||||
actor.RigidbodyComponent.IsKinematic = true;
|
||||
actor.ColliderComponent.enabled = false;
|
||||
|
||||
Init(characterController.OffMeshLink);
|
||||
|
||||
characterController.LimitViewAngle = 45;
|
||||
}
|
||||
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
{
|
||||
base.OnStateExit(old, newState);
|
||||
actor.RigidbodyComponent.IsKinematic = false;
|
||||
actor.ColliderComponent.enabled = true;
|
||||
|
||||
characterController.LimitViewAngle = 0;
|
||||
}
|
||||
|
||||
private void Init(OffMeshLink offMeshLink)
|
||||
{
|
||||
var offsetTransform = offMeshLink.transform;
|
||||
_offMeshLink = offMeshLink;
|
||||
|
||||
offMeshLink.TryGetComponent<ISplineContainer>(out _splineContainer);
|
||||
|
||||
LinkArea = offMeshLink.area;
|
||||
|
||||
if (_splineContainer is not null)
|
||||
{
|
||||
var isStart =
|
||||
Vector3.Distance(
|
||||
actor.Position,
|
||||
offsetTransform.TransformPoint(_splineContainer.Splines[0].Knots.First().Position)
|
||||
) <
|
||||
Vector3.Distance(
|
||||
actor.Position,
|
||||
offsetTransform.TransformPoint(_splineContainer.Splines[0].Knots.Last().Position)
|
||||
);
|
||||
progress = isStart ? 0 : 1;
|
||||
increment = isStart ? 1 : -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
var offset = Mathf.Lerp(offMeshLink.startTransform.position.y,offMeshLink.endTransform.position.y,0.5f);
|
||||
var offsetPos = actor.Position;
|
||||
offsetPos.y = offset;
|
||||
actor.ForceNotGrounded();
|
||||
actor.Position = Vector3.MoveTowards(actor.Position, offsetPos, 0.64f);
|
||||
progress = 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
|
||||
{
|
||||
if (_splineContainer is null)
|
||||
{
|
||||
actor.Rotation = Quaternion.Lerp(
|
||||
actor.Rotation,
|
||||
Quaternion.Inverse(_offMeshLink.transform.rotation),
|
||||
5 * deltaTime
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
actor.ForceNotGrounded();
|
||||
|
||||
if (_offMeshLink is null) return;
|
||||
switch (_splineContainer)
|
||||
{
|
||||
case null:
|
||||
var positionA = _offMeshLink.startTransform.position;
|
||||
var positionB = positionA;
|
||||
positionB.y = _offMeshLink.endTransform.position.y;
|
||||
var positionC = actor.Position + Vector3.up * (characterController.MovementInput.z * deltaTime * 3);
|
||||
|
||||
Vector3 vectorAC = positionC - positionA;
|
||||
Vector3 vectorAB = positionB - positionA;
|
||||
|
||||
Vector3 closestPoint = positionA + Vector3.Project(vectorAC, vectorAB);
|
||||
|
||||
actor.Position = closestPoint;
|
||||
//currentVelocity = Vector3.Lerp(currentVelocity , (closestPoint - actor.Position) , 5 * deltaTime);
|
||||
break;
|
||||
case not null:
|
||||
var trans = _offMeshLink.transform;
|
||||
var pos =trans.position + trans.rotation * _splineContainer.Splines[0].EvaluatePosition(progress +=increment * deltaTime);
|
||||
|
||||
actor.Position =Vector3.Lerp(actor.Position , pos , 8*deltaTime) ;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void OnStateUpdate(float deltaTime)
|
||||
{
|
||||
if (characterController.ExpectJump.shouldBe|| characterController.ExpectCrouch.shouldBe)
|
||||
{
|
||||
Exit();
|
||||
return;
|
||||
}
|
||||
switch (_offMeshLink,_splineContainer)
|
||||
{
|
||||
case (null,null):
|
||||
Exit();
|
||||
break;
|
||||
case (not null,not null):
|
||||
if (progress is > 1.1f or < -0.1f)
|
||||
{
|
||||
Exit();
|
||||
}
|
||||
break;
|
||||
case (not null,null):
|
||||
if (actor.Position.y > _offMeshLink.endTransform.position.y)
|
||||
{
|
||||
Exit();
|
||||
actor.Position = _offMeshLink.endTransform.position;
|
||||
}else if (actor.Position.y < _offMeshLink.startTransform.position.y)
|
||||
{
|
||||
Exit();
|
||||
actor.Position = _offMeshLink.startTransform.position;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
characterController.CurrentCameraPosition.shouldBe = characterController.FpvLocalPosition;
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public sealed class Fixed:PlayerCharacterState,IPlayerFixedState
|
||||
{
|
||||
public object FixedObject=>_fixedPlace;
|
||||
public float3 FixedPosition=>_fixedPlace.FixedPosition;
|
||||
public quaternion FixedRotation=>_fixedPlace.FixedRotation;
|
||||
public float3 FixedLocalPosition => throw new NotImplementedException();
|
||||
public quaternion FixedLocalRotation => throw new NotImplementedException();
|
||||
private IPlayerFixedPlace _fixedPlace;
|
||||
|
||||
[Inject] private ISelector _selector;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_selector.OnActive+=OnSelectorActive;
|
||||
}
|
||||
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
base.OnStateEntry(old);
|
||||
//actor.enabled = false;
|
||||
//actor.RigidbodyComponent.IsKinematic = true;
|
||||
actor.ColliderComponent.enabled = false;
|
||||
actor.PhysicsComponent.enabled = false;
|
||||
actor.alwaysNotGrounded = true;
|
||||
characterController.ExpectCrouch.Reset();
|
||||
characterController.LimitViewAngle = 100;
|
||||
}
|
||||
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
{
|
||||
base.OnStateExit(old, newState);
|
||||
//actor.RigidbodyComponent.IsKinematic = false;
|
||||
actor.ColliderComponent.enabled = true;
|
||||
actor.alwaysNotGrounded = false;
|
||||
actor.PhysicsComponent.enabled = true;
|
||||
//actor.enabled = true;
|
||||
characterController.LimitViewAngle = 0;
|
||||
}
|
||||
public override void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
actor.Position = FixedPosition;
|
||||
}
|
||||
public override void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
|
||||
{
|
||||
currentRotation = FixedRotation;
|
||||
//actor.Rotation = FixedRotation;
|
||||
}
|
||||
public override void AfterUpdateMovement(float deltaTime)
|
||||
{
|
||||
base.AfterUpdateMovement(deltaTime);
|
||||
characterController.CurrentCameraPosition.shouldBe = characterController.FpvLocalPosition;
|
||||
if (characterController.ExpectCrouch.shouldBe && _fixedPlace.Exit(characterController.Entity))
|
||||
{
|
||||
characterController.ExpectCrouch.Reset();
|
||||
Exit();
|
||||
}else if (_fixedPlace is null)
|
||||
{
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
private void OnSelectorActive(ISelectable obj)
|
||||
{
|
||||
if (obj is not MonoBehaviour monoBehaviour ||
|
||||
monoBehaviour.TryGetComponent<IPlayerFixedPlace>(out var fixedPlace) is false) return;
|
||||
if (_fixedPlace?.Exit(characterController.Entity) is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (fixedPlace.Entry(characterController.Entity))
|
||||
{
|
||||
_fixedPlace = fixedPlace;
|
||||
characterController.TransitionState<Fixed>();
|
||||
return;
|
||||
}
|
||||
_fixedPlace = null;
|
||||
}
|
||||
|
||||
public override void OnStateUpdate(float deltaTime)
|
||||
{
|
||||
|
||||
}
|
||||
protected override void Exit()
|
||||
{
|
||||
base.Exit();
|
||||
if (_fixedPlace is not null)
|
||||
{
|
||||
actor.Position = _fixedPlace.ExitPosition;
|
||||
}
|
||||
_fixedPlace = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,9 @@
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:709caf8d7fb6ef24bbba0ab9962a3ad0",
|
||||
"GUID:1235ca61e7f433b408ed5a68767e7123",
|
||||
"GUID:7efac18f239530141802fb139776f333"
|
||||
"GUID:7efac18f239530141802fb139776f333",
|
||||
"GUID:f6155d9ae143f3949ac54e8355593d6c",
|
||||
"GUID:87bea3a21c744b1478660b70494160ba"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using BITFALL.Player.Movement;
|
||||
using BITKit.Entities;
|
||||
using BITKit.StateMachine;
|
||||
using Unity.SharpZipLib.Zip;
|
||||
using UnityEngine;
|
||||
// ReSharper disable UnassignedField.Global
|
||||
|
||||
@@ -13,6 +15,7 @@ namespace BITFALL.Player.Animation.States
|
||||
{
|
||||
[SerializeField] protected PlayerAnimationController animationController;
|
||||
public virtual bool Enabled { get; set; }
|
||||
protected IPlayerAnimationState entryState;
|
||||
public virtual void Initialize()
|
||||
{
|
||||
|
||||
@@ -20,6 +23,7 @@ namespace BITFALL.Player.Animation.States
|
||||
|
||||
public virtual void OnStateEntry(IState old)
|
||||
{
|
||||
entryState = old as IPlayerAnimationState;
|
||||
}
|
||||
|
||||
public virtual void OnStateUpdate(float deltaTime)
|
||||
@@ -33,17 +37,38 @@ namespace BITFALL.Player.Animation.States
|
||||
public virtual void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
{
|
||||
}
|
||||
protected virtual void Exit()
|
||||
{
|
||||
if (Enabled is false) return;
|
||||
switch (entryState)
|
||||
{
|
||||
case IPlayerWalkState:
|
||||
animationController.TransitionState<Walk>();
|
||||
break;
|
||||
case IPlayerCrouchState:
|
||||
animationController.TransitionState<Crouch>();
|
||||
break;
|
||||
case IPlayerSprintState:
|
||||
animationController.TransitionState<Sprint>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public class Walk : PlayerAnimateStates
|
||||
public class Walk : PlayerAnimateStates,IPlayerWalkState
|
||||
{
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
|
||||
animationController.animator.Play(old switch
|
||||
animationController.animator.CrossFade(old switch
|
||||
{
|
||||
IPlayerRunState or IPlayerSprintState=> "Walk.Stop",
|
||||
_=>PlayerAnimationController._Walk
|
||||
IPlayerLinkState { LinkArea: 5 } => "Walk.ExitClimb",
|
||||
_=>BITConstant.Player.Walk
|
||||
},old switch
|
||||
{
|
||||
IPlayerRunState or IPlayerSprintState=> 0.08f,
|
||||
IPlayerSlideState or IPlayerCrouchState => 0.32f,
|
||||
_=>0.16f
|
||||
});
|
||||
}
|
||||
|
||||
@@ -65,36 +90,25 @@ namespace BITFALL.Player.Animation.States
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public class Run : PlayerAnimateStates
|
||||
public class Run : PlayerAnimateStates,IPlayerRunState
|
||||
{
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
animationController.animator.Play(PlayerAnimationController._Run);
|
||||
base.OnStateEntry(old);
|
||||
animationController.animator.Play(BITConstant.Player.Run);
|
||||
}
|
||||
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
{
|
||||
if (Enabled is false) return;
|
||||
switch (newState)
|
||||
{
|
||||
case IPlayerWalkState:
|
||||
animationController.TransitionState<Walk>();
|
||||
break;
|
||||
case IPlayerCrouchState:
|
||||
animationController.TransitionState<Crouch>();
|
||||
break;
|
||||
case IPlayerSprintState:
|
||||
animationController.TransitionState<Sprint>();
|
||||
break;
|
||||
}
|
||||
if(Enabled &&newState is not IPlayerRunState)Exit();
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public class Sprint : PlayerAnimateStates
|
||||
public class Sprint : PlayerAnimateStates,IPlayerSprintState
|
||||
{
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
animationController.animator.Play(PlayerAnimationController._Sprint);
|
||||
animationController.animator.Play(BITConstant.Player.Sprint);
|
||||
}
|
||||
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
@@ -112,11 +126,11 @@ namespace BITFALL.Player.Animation.States
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public class Crouch : PlayerAnimateStates
|
||||
public class Crouch : PlayerAnimateStates,IPlayerCrouchState
|
||||
{
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
animationController.animator.Play(PlayerAnimationController._Crouch);
|
||||
animationController.animator.Play(BITConstant.Player.Crouch);
|
||||
}
|
||||
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
@@ -126,4 +140,134 @@ namespace BITFALL.Player.Animation.States
|
||||
animationController.TransitionState<Walk>();
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Parachute : PlayerAnimateStates
|
||||
{
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
animationController.animator.Play(BITConstant.Player.Parachute);
|
||||
}
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
{
|
||||
if(newState is IPlayerParachuteState)
|
||||
animationController.TransitionState<Parachute>();
|
||||
else if(Enabled && newState is not IPlayerKnockdownState)
|
||||
{
|
||||
animationController.TransitionState<Walk>();
|
||||
}
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public class Slide : PlayerAnimateStates
|
||||
{
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
animationController.animator.Play(BITConstant.Player.Slide);
|
||||
}
|
||||
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
{
|
||||
if(newState is IPlayerSlideState)
|
||||
animationController.TransitionState<Slide>();
|
||||
else if(Enabled && newState is not IPlayerKnockdownState)
|
||||
{
|
||||
animationController.TransitionState<Walk>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Knockdown : PlayerAnimateStates
|
||||
{
|
||||
[SerializeField] private AnimatorOverrideController animatorOverrideController;
|
||||
private RuntimeAnimatorController _initialController;
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
_initialController = animationController.animator.animator.runtimeAnimatorController;
|
||||
}
|
||||
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
animationController.animator.animator.runtimeAnimatorController = animatorOverrideController;
|
||||
animationController.animator.Play(BITConstant.Player.Walk);
|
||||
}
|
||||
|
||||
public override void OnStateExit(IState old, IState newState)
|
||||
{
|
||||
animationController.animator.animator.runtimeAnimatorController = _initialController;
|
||||
}
|
||||
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
{
|
||||
if (newState is IPlayerKnockdownState)
|
||||
{
|
||||
animationController.TransitionState<Knockdown>();
|
||||
}
|
||||
else if(Enabled)
|
||||
{
|
||||
animationController.TransitionState<Walk>();
|
||||
}
|
||||
}
|
||||
}
|
||||
[Serializable]
|
||||
public class Link : PlayerAnimateStates,IPlayerLinkState
|
||||
{
|
||||
public int LinkArea { get; set; }
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
switch (LinkArea)
|
||||
{
|
||||
case 5:
|
||||
animationController.animator.Play(BITConstant.Player.ClimbLadder);
|
||||
break;
|
||||
}
|
||||
//animationController.animator.Play(BITConstant.Player._Run);
|
||||
}
|
||||
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
{
|
||||
if (Enabled)
|
||||
{
|
||||
switch (newState)
|
||||
{
|
||||
case IPlayerWalkState:
|
||||
animationController.TransitionState<Walk>();
|
||||
break;
|
||||
case IPlayerCrouchState:
|
||||
animationController.TransitionState<Crouch>();
|
||||
break;
|
||||
case IPlayerSprintState:
|
||||
animationController.TransitionState<Sprint>();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (newState is IPlayerLinkState linkState)
|
||||
{
|
||||
LinkArea = linkState.LinkArea;
|
||||
animationController.TransitionState<Link>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class Fixed : PlayerAnimateStates
|
||||
{
|
||||
public override void OnStateEntry(IState old)
|
||||
{
|
||||
animationController.animator.Play(BITConstant.Player.Fixed);
|
||||
}
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
{
|
||||
base.OnMovementStateChanged(oldState, newState);
|
||||
if(newState is IPlayerFixedState)
|
||||
animationController.TransitionState<Fixed>();
|
||||
else if(Enabled)
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,10 +14,7 @@ namespace BITFALL.Player.Animation
|
||||
}
|
||||
public class PlayerAnimationController : StateBasedComponent<IPlayerAnimationState>
|
||||
{
|
||||
public const string _Walk = "Walk";
|
||||
public const string _Run = "Run";
|
||||
public const string _Sprint = "Sprint";
|
||||
public const string _Crouch = "Crouch";
|
||||
|
||||
[SerializeField] internal UnityAnimator animator;
|
||||
|
||||
private IEntityMovement _movement;
|
||||
|
@@ -17,7 +17,7 @@ namespace BITFALL.Player.Animation.States
|
||||
}
|
||||
public override void OnMovementStateChanged(IEntityMovementState oldState, IEntityMovementState newState)
|
||||
{
|
||||
if (newState is IPlayerClimbState)
|
||||
if (newState is IPlayerClimbState or IPlayerLinkState { LinkArea: 4 })
|
||||
{
|
||||
animationController.TransitionState<Climb>();
|
||||
}
|
||||
|
@@ -10,7 +10,8 @@
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:ef0bb553b58b90b488bdbe8672e3be0b",
|
||||
"GUID:677cd05ca06c46b4395470200b1acdad",
|
||||
"GUID:30cdc242b1ac6a944a460f4ab0b77b88"
|
||||
"GUID:30cdc242b1ac6a944a460f4ab0b77b88",
|
||||
"GUID:7efac18f239530141802fb139776f333"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
@@ -22,14 +22,22 @@ namespace BITFALL.Player.Survival
|
||||
|
||||
private bool OnUseItem(IBasicItem arg)
|
||||
{
|
||||
switch (arg)
|
||||
var used = false;
|
||||
{
|
||||
case var _ when arg.GetAssetable().TryGetProperty<PlayerEatAddHunger>(out var addHunger) &&
|
||||
_survival.Elements.TryGetAny(x => x is PlayerSurvivalHunger, out var hunger):
|
||||
hunger.Value += addHunger.Value;
|
||||
return true;
|
||||
if (arg.GetAssetable().TryGetProperty<PlayerEatAddHunger>(out var addHunger) &&
|
||||
_survival.Elements.TryGetAny(x => x is PlayerSurvivalHunger, out var element))
|
||||
{
|
||||
element.Value += addHunger.Value;
|
||||
used = true;
|
||||
}
|
||||
if (arg.GetAssetable().TryGetProperty<PlayerEatAddThirst>(out var addThirst) &&
|
||||
_survival.Elements.TryGetAny(x => x is PlayerSurvivalThirst, out element))
|
||||
{
|
||||
element.Value += addThirst.Value;
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return used;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,13 +8,21 @@ using UnityEngine;
|
||||
|
||||
namespace BITFALL.Player.Survival
|
||||
{
|
||||
[Serializable]
|
||||
public struct SurvivalDamage : IDamageType
|
||||
{
|
||||
public IPlayerSurvivalElement element;
|
||||
public string Message;
|
||||
}
|
||||
[CustomType(typeof(IPlayerSurvivalService))]
|
||||
public class PlayerSurvivalService : EntityComponent, IPlayerSurvivalService
|
||||
{
|
||||
public IPlayerSurvivalElement[] Elements { get; set; } = Array.Empty<IPlayerSurvivalElement>();
|
||||
[SerializeReference, SubclassSelector] private IPlayerSurvivalElement[] initialElements = Array.Empty<IPlayerSurvivalElement>();
|
||||
|
||||
private IntervalUpdate _interval = new(1);
|
||||
private readonly IntervalUpdate _interval = new(1);
|
||||
[SerializeReference,SubclassSelector,Inject] private IDamageService _damageService;
|
||||
[Inject]
|
||||
private IHealth _health;
|
||||
public override void OnAwake()
|
||||
{
|
||||
Elements = initialElements;
|
||||
@@ -26,6 +34,18 @@ namespace BITFALL.Player.Survival
|
||||
foreach (var x in Elements)
|
||||
{
|
||||
x.Value -= 1;
|
||||
if (x.Value <= 0)
|
||||
{
|
||||
_damageService.Execute(new DamageMessage()
|
||||
{
|
||||
damageType = new SurvivalDamage()
|
||||
{
|
||||
element = x,
|
||||
},
|
||||
target = entity,
|
||||
damage = 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user