Second commit
This commit is contained in:
commit
36840f3ad4
999 files changed
+61364
No files matched your search
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.Infrastructure.Camera.CameraStates;
|
||||
using Code.Infrastructure.Generators;
|
||||
using Code.Infrastructure.Input;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using R3;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Code.Game.Gameplay.Player
|
||||
{
|
||||
[State(typeof(CameraMode),typeof(CameraStateMachineContext), ManualInherit = true)]
|
||||
public partial class CleanerCameraState : BaseCameraState
|
||||
{
|
||||
public void SetTarget(Transform target)
|
||||
{
|
||||
_target = target;
|
||||
Context.cameraLoadedData.Camera.transform.position = _target.position;
|
||||
Context.cameraLoadedData.Camera.transform.rotation = _target.rotation;
|
||||
}
|
||||
|
||||
private IDisposable _disposable;
|
||||
public void SetPlayer(PlayerMovementController playerMovementController)
|
||||
{
|
||||
_disposable = playerMovementController.IsSliding.Subscribe(SlideToggle);
|
||||
}
|
||||
|
||||
private void SlideToggle(bool isSliding) => _isSliding = isSliding;
|
||||
|
||||
private Transform _target;
|
||||
private Vector2 _mouseDelta;
|
||||
private Vector2 _rotation = Vector2.zero;
|
||||
|
||||
private float _sensitivityX = 0.1f;
|
||||
private float _sensitivityY = 0.1f;
|
||||
private float _slideStupidity = 1f;
|
||||
private bool _isSliding;
|
||||
|
||||
public CleanerCameraState(CameraStateMachineContext context) : base(context)
|
||||
{
|
||||
}
|
||||
|
||||
private void LookCancelled(InputAction.CallbackContext obj) => _mouseDelta = Vector2.zero;
|
||||
private void LookPerformed(InputAction.CallbackContext obj) => _mouseDelta = obj.ReadValue<Vector2>();
|
||||
|
||||
public override CameraMode MyState => CameraMode.Cleaner;
|
||||
|
||||
public override UniTask EnterState()
|
||||
{
|
||||
Context.InputService.BindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Watchment, LookPerformed);
|
||||
Context.InputService.BindActionCancelled((int)ActionMappings.Cleaning, (int)CleaningActions.Watchment, LookCancelled);
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
public override UniTask ExitState()
|
||||
{
|
||||
Context.InputService.UnbindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Watchment, LookPerformed);
|
||||
Context.InputService.UnbindActionCancelled((int)ActionMappings.Cleaning, (int)CleaningActions.Watchment, LookCancelled);
|
||||
_disposable.Dispose();
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
}
|
||||
|
||||
public override void LateUpdate()
|
||||
{
|
||||
if (_target is null) return;
|
||||
|
||||
var camTransform = Context.cameraLoadedData.Camera.transform;
|
||||
|
||||
camTransform.position = _target.position;
|
||||
|
||||
var mouseDeltaX = _mouseDelta.x * _sensitivityX;
|
||||
var mouseDeltaY = _mouseDelta.y * _sensitivityY;
|
||||
|
||||
if (_isSliding)
|
||||
{
|
||||
mouseDeltaX = Mathf.Clamp(mouseDeltaX, -_slideStupidity, _slideStupidity);
|
||||
mouseDeltaY = Mathf.Clamp(mouseDeltaY, -_slideStupidity, _slideStupidity);
|
||||
}
|
||||
|
||||
_rotation.x += mouseDeltaX;
|
||||
_rotation.y -= mouseDeltaY;
|
||||
|
||||
_rotation.y = Mathf.Clamp(_rotation.y, -90f, 90f);
|
||||
|
||||
camTransform.localRotation = Quaternion.Euler(_rotation.y, _rotation.x, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e592628c3fe45bf9659d1050680c296
|
||||
timeCreated: 1785846388
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9b8ea0290514b809c83dd30d68391ca
|
||||
timeCreated: 1785846388
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Code.Infrastructure.Utils;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Reflex.Attributes;
|
||||
using Reflex.Core;
|
||||
using Reflex.Injectors;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Game.Gameplay.Player.Factory
|
||||
{
|
||||
public interface IPlayerFactory
|
||||
{
|
||||
UniTask<GameObject> CreatePlayer();
|
||||
void InjectPlayer(Container container);
|
||||
}
|
||||
|
||||
public class PlayerFactory : IDisposable, IPlayerFactory
|
||||
{
|
||||
private readonly SingleConfig<PlayerFactorySettings> _config;
|
||||
|
||||
private GameObject _playerInstance;
|
||||
|
||||
public PlayerFactory(SingleConfig<PlayerFactorySettings> config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
public async UniTask<GameObject> CreatePlayer()
|
||||
{
|
||||
_playerInstance ??= await Addressables.InstantiateAsync(_config.Config.Player).ToUniTask();
|
||||
|
||||
return _playerInstance;
|
||||
}
|
||||
|
||||
public void InjectPlayer(Container container)
|
||||
{
|
||||
GameObjectInjector.InjectRecursive(_playerInstance, container);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Addressables.ReleaseInstance(_playerInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdc8848de9734ba3bb1c3e3ec81145e6
|
||||
timeCreated: 1778956904
|
||||
@@ -0,0 +1,13 @@
|
||||
using Code.Infrastructure.Generators;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace Code.Game.Gameplay.Player.Factory
|
||||
{
|
||||
[Config("Configs/Gameplay/PlayerFactory")]
|
||||
[CreateAssetMenu(fileName = "PlayerFactorySettings", menuName = "Configs/Gameplay/PlayerFactory")]
|
||||
public class PlayerFactorySettings : ScriptableObject
|
||||
{
|
||||
public AssetReference Player;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c312323c8dc049b2b7e7330f54b09aad
|
||||
timeCreated: 1785871572
|
||||
@@ -0,0 +1,13 @@
|
||||
using Code.Infrastructure.Camera;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Game.Gameplay.Player
|
||||
{
|
||||
public class PlayerCameraTarget : MonoBehaviour
|
||||
{
|
||||
[Inject]
|
||||
private void Construct(CameraStateMachine cameraStateMachine) =>
|
||||
((CleanerCameraState)cameraStateMachine.CurrentBaseState).SetTarget(transform);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c579fd0c46544b26b3dd27ecdf36fc37
|
||||
timeCreated: 1785846388
|
||||
@@ -0,0 +1,96 @@
|
||||
using Code.Game.Gameplay.Player;
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.Infrastructure.Input;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Code.Game.Cleaning.Player
|
||||
{
|
||||
public class PlayerControlsProvider : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private PlayerMovementController playerMovementController;
|
||||
|
||||
private IInputService _inputService;
|
||||
|
||||
private Vector2 _movementInput;
|
||||
private bool _jumpDown;
|
||||
private bool _crouchDown;
|
||||
private bool _walkOn;
|
||||
private Transform _cameraTransform;
|
||||
|
||||
[Inject]
|
||||
private void Construct(IInputService inputService, CameraStateMachine cameraStateMachine)
|
||||
{
|
||||
_cameraTransform = cameraStateMachine.Camera.transform;
|
||||
_inputService = inputService;
|
||||
|
||||
_inputService.BindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Movement,
|
||||
MovementPerformed);
|
||||
_inputService.BindActionCancelled((int)ActionMappings.Cleaning, (int)CleaningActions.Movement,
|
||||
MovementCancelled);
|
||||
|
||||
_inputService.BindActionPerformed((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Jump, JumpPerformed);
|
||||
_inputService.BindActionCancelled((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Jump, JumpCancelled);
|
||||
|
||||
_inputService.BindActionPerformed((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Walk, WalkPerformed);
|
||||
|
||||
_inputService.BindActionPerformed((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Crouch, CrouchPerformed);
|
||||
_inputService.BindActionCancelled((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Crouch, CrouchCancelled);
|
||||
}
|
||||
|
||||
private void CrouchPerformed(InputAction.CallbackContext obj) => _crouchDown = true;
|
||||
private void CrouchCancelled(InputAction.CallbackContext obj) => _crouchDown = false;
|
||||
|
||||
private void WalkPerformed(InputAction.CallbackContext obj) => _walkOn = !_walkOn;
|
||||
private void JumpCancelled(InputAction.CallbackContext obj) => _jumpDown = false;
|
||||
private void JumpPerformed(InputAction.CallbackContext obj) => _jumpDown = true;
|
||||
|
||||
private void MovementCancelled(InputAction.CallbackContext obj) => _movementInput = Vector2.zero;
|
||||
private void MovementPerformed(InputAction.CallbackContext obj) => _movementInput = obj.ReadValue<Vector2>();
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!_cameraTransform) return;
|
||||
|
||||
var inputs = new PlayerCharacterInputs()
|
||||
{
|
||||
MoveAxisForward = _movementInput.y,
|
||||
MoveAxisRight = _movementInput.x,
|
||||
CameraRotation = _cameraTransform.rotation,
|
||||
JumpDown = _jumpDown,
|
||||
CrouchDown = _crouchDown,
|
||||
CrouchUp = !_crouchDown,
|
||||
WalkOn = _walkOn
|
||||
};
|
||||
|
||||
playerMovementController.SetInputs(ref inputs);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_inputService.UnbindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Movement,
|
||||
MovementPerformed);
|
||||
_inputService.UnbindActionCancelled((int)ActionMappings.Cleaning, (int)CleaningActions.Movement,
|
||||
MovementCancelled);
|
||||
|
||||
_inputService.UnbindActionPerformed((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Jump, JumpPerformed);
|
||||
_inputService.UnbindActionCancelled((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Jump, JumpCancelled);
|
||||
|
||||
_inputService.UnbindActionPerformed((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Walk, WalkPerformed);
|
||||
|
||||
_inputService.UnbindActionPerformed((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Crouch, CrouchPerformed);
|
||||
_inputService.UnbindActionCancelled((int)ActionMappings.Cleaning,
|
||||
(int)CleaningActions.Crouch, CrouchCancelled);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75c0d109df244d6ebf8c0eb976553c6a
|
||||
timeCreated: 1785846388
|
||||
@@ -0,0 +1,114 @@
|
||||
using Code.D.Cleaning;
|
||||
using Code.D.Player;
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.Infrastructure.Input;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using R3;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Code.Game.Gameplay.Player
|
||||
{
|
||||
public class PlayerDetailMaskDrawer : MonoBehaviour
|
||||
{
|
||||
private IInputService _inputService;
|
||||
private Transform _cameraTransform;
|
||||
|
||||
private bool _cleaning, _cleaningUnder;
|
||||
|
||||
private LayerMask _layerMask;
|
||||
private TagHandle _surfaceTag;
|
||||
|
||||
private CleanableSurface _lastCleaned;
|
||||
[SerializeField] private float cleaningDistance = 5f;
|
||||
[SerializeField] private PlayerEquipment playerEquipment;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_surfaceTag = TagHandle.GetExistingTag("CleanableSurface");
|
||||
_layerMask = LayerMask.GetMask("Cleanable");
|
||||
|
||||
GetComponent<PlayerMovementController>().IsSliding.Subscribe(SlideToggle).AddTo(destroyCancellationToken);
|
||||
}
|
||||
|
||||
[Inject]
|
||||
private void Construct(IInputService inputService, CameraStateMachine cameraStateMachine)
|
||||
{
|
||||
_cameraTransform = cameraStateMachine.Camera.transform;
|
||||
_inputService = inputService;
|
||||
|
||||
_inputService.BindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Clean, DrawPerformed);
|
||||
_inputService.BindActionCancelled((int)ActionMappings.Cleaning, (int)CleaningActions.Clean, DrawCancelled);
|
||||
}
|
||||
|
||||
private void SlideToggle(bool isSliding) => _cleaningUnder = isSliding;
|
||||
|
||||
private void DrawPerformed(InputAction.CallbackContext obj) => _cleaning = true;
|
||||
|
||||
private void DrawCancelled(InputAction.CallbackContext obj) => _cleaning = false;
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (_cleaning) CleanInFront();
|
||||
if (_cleaningUnder) CleanUnder();
|
||||
}
|
||||
|
||||
private void CleanUnder()
|
||||
{
|
||||
if (!Physics.Raycast(
|
||||
_cameraTransform.position,
|
||||
-transform.up,
|
||||
out var info,
|
||||
5f,
|
||||
layerMask: _layerMask)) return;
|
||||
|
||||
if (info.collider.CompareTag(_surfaceTag))
|
||||
CleanSurface(info);
|
||||
}
|
||||
|
||||
private void CleanInFront()
|
||||
{
|
||||
if (!Physics.Raycast(
|
||||
_cameraTransform.position,
|
||||
_cameraTransform.forward,
|
||||
out var info,
|
||||
cleaningDistance,
|
||||
layerMask: _layerMask)) return;
|
||||
|
||||
if (info.collider.CompareTag(_surfaceTag))
|
||||
CleanSurface(info);
|
||||
else
|
||||
CleanAsset(info);
|
||||
}
|
||||
|
||||
private void CleanAsset(RaycastHit info)
|
||||
{
|
||||
var cleanable = info.collider.GetComponent<CleanableAsset>();
|
||||
|
||||
cleanable.Clean();
|
||||
}
|
||||
|
||||
private void CleanSurface(RaycastHit info)
|
||||
{
|
||||
CleanableSurface cleanable;
|
||||
if (_lastCleaned is not null && info.collider.GetEntityId() == _lastCleaned.GetEntityId())
|
||||
cleanable = _lastCleaned;
|
||||
else
|
||||
{
|
||||
cleanable = info.collider.GetComponent<CleanableSurface>();
|
||||
_lastCleaned = cleanable;
|
||||
}
|
||||
|
||||
cleanable.Clean(info, playerEquipment.CurrentTool.Use(), _cameraTransform);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_inputService.UnbindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Clean,
|
||||
DrawPerformed);
|
||||
_inputService.UnbindActionCancelled((int)ActionMappings.Cleaning, (int)CleaningActions.Clean,
|
||||
DrawCancelled);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1606bdb9e6840f5960df117e5298061
|
||||
timeCreated: 1785923251
|
||||
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Code.D.Cleaning.CleanTools;
|
||||
using R3;
|
||||
using Reflex.Attributes;
|
||||
using Unity.Burst;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.D.Player
|
||||
{
|
||||
public class PlayerEquipment : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Texture2D tryapkaBrushTexture;
|
||||
public CleanTool CurrentTool { get; private set; }
|
||||
private Dictionary<CleanToolType, CleanTool> _cleanTools = new();
|
||||
public ReactiveProperty<CleanToolType> CurrentToolType { get; } = new();
|
||||
|
||||
private IDisposable _dirtinessDisposable;
|
||||
|
||||
[Inject]
|
||||
private void Construct(List<CleanTool> cleanTools)
|
||||
{
|
||||
foreach (var cleanTool in cleanTools) _cleanTools.Add(cleanTool.ToolType, cleanTool);
|
||||
|
||||
var firstTool = _cleanTools.First();
|
||||
CurrentToolType.Value = firstTool.Key;
|
||||
CurrentTool = firstTool.Value;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
//CurrentTool = new Tryapka(0.0001f, 0.005f, tryapkaBrushTexture);
|
||||
//
|
||||
// DisposableBuilder builder = new DisposableBuilder();
|
||||
// // Я безумец, здесь подписаться на все сразу
|
||||
// builder.Add(CurrentTool.CurrentDirtiness.Subscribe(x => CurrentToolDirtiness.Value =
|
||||
// new ToolDirtinessData
|
||||
// {
|
||||
// Dirtiness = x,
|
||||
// ToolType = CleanToolType.Tryapka
|
||||
// }
|
||||
// ));
|
||||
//
|
||||
// _dirtinessDisposable = builder.Build();
|
||||
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_dirtinessDisposable?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolDirtinessData : IEquatable<ToolDirtinessData>
|
||||
{
|
||||
public float Dirtiness;
|
||||
public CleanToolType ToolType;
|
||||
|
||||
public bool Equals(ToolDirtinessData other)
|
||||
{
|
||||
return Mathf.Approximately(Dirtiness, other.Dirtiness) && ToolType == other.ToolType;
|
||||
}
|
||||
|
||||
[BurstDiscard]
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ToolDirtinessData other && Equals(other);
|
||||
}
|
||||
|
||||
[BurstDiscard]
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Dirtiness, ToolType);
|
||||
}
|
||||
|
||||
public static bool operator ==(ToolDirtinessData left, ToolDirtinessData right) => left.Equals(right);
|
||||
public static bool operator !=(ToolDirtinessData left, ToolDirtinessData right) => !left.Equals(right);
|
||||
}
|
||||
|
||||
public struct ToolDirtyData : IEquatable<ToolDirtyData>
|
||||
{
|
||||
public CleanToolType ToolType;
|
||||
|
||||
public bool Equals(ToolDirtyData other)
|
||||
{
|
||||
return ToolType == other.ToolType;
|
||||
}
|
||||
|
||||
[BurstDiscard]
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is ToolDirtyData other && Equals(other);
|
||||
}
|
||||
|
||||
[BurstDiscard]
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ToolType.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(ToolDirtyData left, ToolDirtyData right) => left.Equals(right);
|
||||
public static bool operator !=(ToolDirtyData left, ToolDirtyData right) => !left.Equals(right);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba4e659f17b147db992374aab735ed4c
|
||||
timeCreated: 1785940207
|
||||
@@ -0,0 +1,64 @@
|
||||
using Code.D.Cleaning.CleanTools;
|
||||
using Code.Infrastructure.Camera;
|
||||
using Code.Infrastructure.Input;
|
||||
using Reflex.Attributes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace Code.D.Player
|
||||
{
|
||||
public class PlayerInteractor : MonoBehaviour
|
||||
{
|
||||
private IInputService _inputService;
|
||||
private LayerMask _cleanToolInteractableMask;
|
||||
private Transform _cameraTransform;
|
||||
private CleanToolInteractable _lastCleanToolInteractable;
|
||||
|
||||
[SerializeField] private float interactionDistance = 5f;
|
||||
[SerializeField] private PlayerEquipment playerEquipment;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_cleanToolInteractableMask = LayerMask.GetMask("CleanToolInteractable");
|
||||
}
|
||||
|
||||
[Inject]
|
||||
private void Construct(IInputService inputService, CameraStateMachine cameraStateMachine)
|
||||
{
|
||||
_cameraTransform = cameraStateMachine.Camera.transform;
|
||||
|
||||
_inputService = inputService;
|
||||
inputService.BindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Interact, TryInteract);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_inputService.UnbindActionPerformed((int)ActionMappings.Cleaning, (int)CleaningActions.Interact,
|
||||
TryInteract);
|
||||
}
|
||||
|
||||
private void TryInteract(InputAction.CallbackContext obj)
|
||||
{
|
||||
if (!Physics.Raycast(
|
||||
_cameraTransform.position,
|
||||
_cameraTransform.forward,
|
||||
out var info,
|
||||
interactionDistance,
|
||||
layerMask: _cleanToolInteractableMask)) return;
|
||||
|
||||
CleanToolInteractable interactable;
|
||||
if (_lastCleanToolInteractable is not null &&
|
||||
info.collider.GetEntityId() == _lastCleanToolInteractable.GetEntityId())
|
||||
{
|
||||
interactable = _lastCleanToolInteractable;
|
||||
}
|
||||
else
|
||||
{
|
||||
interactable = info.collider.gameObject.GetComponent<CleanToolInteractable>();
|
||||
_lastCleanToolInteractable = interactable;
|
||||
}
|
||||
|
||||
interactable.Use(playerEquipment.CurrentTool);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 997fa523ddda4b1ea3f4b0b1e1e7864a
|
||||
timeCreated: 1785939712
|
||||
@@ -0,0 +1,644 @@
|
||||
using System.Collections.Generic;
|
||||
using Alchemy.Inspector;
|
||||
using KinematicCharacterController;
|
||||
using LitMotion;
|
||||
using LitMotion.Extensions;
|
||||
using R3;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Code.Game.Gameplay.Player
|
||||
{
|
||||
public enum CharacterState
|
||||
{
|
||||
Default,
|
||||
Sliding
|
||||
}
|
||||
|
||||
public enum OrientationMethod
|
||||
{
|
||||
TowardsCamera,
|
||||
TowardsMovement,
|
||||
}
|
||||
|
||||
public struct PlayerCharacterInputs
|
||||
{
|
||||
public float MoveAxisForward;
|
||||
public float MoveAxisRight;
|
||||
public Quaternion CameraRotation;
|
||||
public bool JumpDown;
|
||||
public bool CrouchDown;
|
||||
public bool CrouchUp;
|
||||
public bool WalkOn;
|
||||
}
|
||||
|
||||
public struct AICharacterInputs
|
||||
{
|
||||
public Vector3 MoveVector;
|
||||
public Quaternion Look;
|
||||
}
|
||||
|
||||
public enum BonusOrientationMethod
|
||||
{
|
||||
None,
|
||||
TowardsGravity,
|
||||
TowardsGroundSlopeAndGravity,
|
||||
}
|
||||
|
||||
public class PlayerMovementController : MonoBehaviour, ICharacterController
|
||||
{
|
||||
public KinematicCharacterMotor Motor;
|
||||
|
||||
[TabGroup("Stable Movement")] public float MaxStableMoveSpeed = 10f;
|
||||
[TabGroup("Stable Movement")] public float SprintingModifier = 2f;
|
||||
[TabGroup("Stable Movement")] public float StableMovementSharpness = 15f;
|
||||
[TabGroup("Stable Movement")] public float OrientationSharpness = 10f;
|
||||
[TabGroup("Stable Movement")] public OrientationMethod OrientationMethod = OrientationMethod.TowardsCamera;
|
||||
|
||||
[TabGroup("Sliding")] public AnimationCurve SlideSpeedMultiplierCurve;
|
||||
[TabGroup("Sliding")] public float SlideSpeedCurveStep = 0.1f;
|
||||
[TabGroup("Sliding")] public float MaxCrouchMoveSpeed = 5f;
|
||||
[TabGroup("Sliding")] public float InCrouchTime = 1f;
|
||||
[TabGroup("Sliding")] public float OutCrouchTime = 1f;
|
||||
[TabGroup("Sliding")] public float SlideStupidity = 0.1f;
|
||||
|
||||
[TabGroup("Air Movement")] public float MaxAirMoveSpeed = 15f;
|
||||
[TabGroup("Air Movement")] public float AirAccelerationSpeed = 15f;
|
||||
[TabGroup("Air Movement")] public float Drag = 0.1f;
|
||||
|
||||
[TabGroup("Jumping")] public bool AllowJumpingWhenSliding = false;
|
||||
[TabGroup("Jumping")] public float JumpUpSpeed = 10f;
|
||||
[TabGroup("Jumping")] public float JumpScalableForwardSpeed = 10f;
|
||||
[TabGroup("Jumping")] public float JumpPreGroundingGraceTime = 0f;
|
||||
[TabGroup("Jumping")] public float JumpPostGroundingGraceTime = 0f;
|
||||
[TabGroup("Jumping")] public BonusOrientationMethod BonusOrientationMethod = BonusOrientationMethod.None;
|
||||
[TabGroup("Jumping")] public float BonusOrientationSharpness = 10f;
|
||||
[TabGroup("Jumping")] public float BonusOrientationGravitySharpness;
|
||||
[TabGroup("Jumping")] public Vector3 Gravity = new Vector3(0, -30f, 0);
|
||||
|
||||
[TabGroup("Misc")] public List<Collider> IgnoredColliders = new List<Collider>();
|
||||
[TabGroup("Misc")] public Transform cameraTransform;
|
||||
[TabGroup("Misc")] public float CrouchedCapsuleHeight = 1f;
|
||||
public CharacterState CurrentCharacterState { get; private set; }
|
||||
public Vector3 CurrentVelocity => Motor.Velocity;
|
||||
public Quaternion CurrentRotation => Motor.TransientRotation;
|
||||
|
||||
private Collider[] _probedColliders = new Collider[8];
|
||||
private RaycastHit[] _probedHits = new RaycastHit[8];
|
||||
private Vector3 _moveInputVector;
|
||||
private Vector3 _lookInputVector;
|
||||
private bool _jumpRequested = false;
|
||||
private bool _jumpConsumed = false;
|
||||
private bool _jumpedThisFrame = false;
|
||||
private float _timeSinceJumpRequested = Mathf.Infinity;
|
||||
private float _timeSinceLastAbleToJump = 0f;
|
||||
private Vector3 _internalVelocityAdd = Vector3.zero;
|
||||
private bool _shouldBeCrouching = false;
|
||||
private bool _isCrouching = false;
|
||||
public ReactiveProperty<bool> IsSliding { get; } = new();
|
||||
private bool _isSliding = false;
|
||||
private float _slideCurveProgress;
|
||||
private bool _isSlideEnded = false;
|
||||
private bool _isSprinting = false;
|
||||
|
||||
private Vector3 lastInnerNormal = Vector3.zero;
|
||||
private Vector3 lastOuterNormal = Vector3.zero;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Handle initial state
|
||||
TransitionToState(CharacterState.Default);
|
||||
|
||||
// Assign the characterController to the motor
|
||||
Motor.CharacterController = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles movement state transitions and enter/exit callbacks
|
||||
/// </summary>
|
||||
public void TransitionToState(CharacterState newState)
|
||||
{
|
||||
CharacterState tmpInitialState = CurrentCharacterState;
|
||||
OnStateExit(tmpInitialState, newState);
|
||||
CurrentCharacterState = newState;
|
||||
OnStateEnter(newState, tmpInitialState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event when entering a state
|
||||
/// </summary>
|
||||
public void OnStateEnter(CharacterState state, CharacterState fromState)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event when exiting a state
|
||||
/// </summary>
|
||||
public void OnStateExit(CharacterState state, CharacterState toState)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called every frame by ExamplePlayer in order to tell the character what its inputs are
|
||||
/// </summary>
|
||||
public void SetInputs(ref PlayerCharacterInputs inputs)
|
||||
{
|
||||
// Clamp input
|
||||
Vector3 moveInputVector =
|
||||
Vector3.ClampMagnitude(new Vector3(inputs.MoveAxisRight, 0f, inputs.MoveAxisForward), 1f);
|
||||
|
||||
// Calculate camera direction and rotation on the character plane
|
||||
Vector3 cameraPlanarDirection =
|
||||
Vector3.ProjectOnPlane(inputs.CameraRotation * Vector3.forward, Motor.CharacterUp).normalized;
|
||||
if (cameraPlanarDirection.sqrMagnitude == 0f)
|
||||
{
|
||||
cameraPlanarDirection = Vector3.ProjectOnPlane(inputs.CameraRotation * Vector3.up, Motor.CharacterUp)
|
||||
.normalized;
|
||||
}
|
||||
|
||||
Quaternion cameraPlanarRotation = Quaternion.LookRotation(cameraPlanarDirection, Motor.CharacterUp);
|
||||
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
if (_isSliding)
|
||||
{
|
||||
moveInputVector.x *= SlideStupidity;
|
||||
}
|
||||
// Move and look inputs
|
||||
_moveInputVector = cameraPlanarRotation * moveInputVector;
|
||||
|
||||
switch (OrientationMethod)
|
||||
{
|
||||
case OrientationMethod.TowardsCamera:
|
||||
_lookInputVector = cameraPlanarDirection;
|
||||
break;
|
||||
case OrientationMethod.TowardsMovement:
|
||||
_lookInputVector = _moveInputVector.normalized;
|
||||
break;
|
||||
}
|
||||
|
||||
// Jumping input
|
||||
if (inputs.JumpDown)
|
||||
{
|
||||
_timeSinceJumpRequested = 0f;
|
||||
_jumpRequested = true;
|
||||
}
|
||||
|
||||
_isSprinting = !inputs.WalkOn;
|
||||
|
||||
// Crouching input
|
||||
if (inputs.CrouchDown)
|
||||
{
|
||||
_shouldBeCrouching = true;
|
||||
|
||||
if (!_isCrouching)
|
||||
{
|
||||
if(_isSprinting && !_isSlideEnded)
|
||||
{
|
||||
_isSliding = true;
|
||||
IsSliding.Value = true;
|
||||
}
|
||||
else _isSlideEnded = true;
|
||||
|
||||
_isCrouching = true;
|
||||
Motor.SetCapsuleDimensions(0.5f, CrouchedCapsuleHeight, CrouchedCapsuleHeight * 0.5f);
|
||||
|
||||
if(_crouchTransition.IsPlaying()) _crouchTransition.Cancel();
|
||||
|
||||
_crouchTransition = LMotion.Create(cameraTransform.localPosition.y, 0.85f, InCrouchTime)
|
||||
.WithEase(Ease.InOutQuad)
|
||||
.BindToLocalPositionY(cameraTransform);
|
||||
}
|
||||
|
||||
}
|
||||
else if (inputs.CrouchUp)
|
||||
{
|
||||
_shouldBeCrouching = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called every frame by the AI script in order to tell the character what its inputs are
|
||||
/// </summary>
|
||||
public void SetInputs(ref AICharacterInputs inputs)
|
||||
{
|
||||
// _moveInputVector = inputs.MoveVector;
|
||||
// _lookInputVector = inputs.Look;
|
||||
var cameraPlanarDirection =
|
||||
Vector3.ProjectOnPlane(inputs.Look * Vector3.forward, Motor.CharacterUp).normalized;
|
||||
|
||||
if (cameraPlanarDirection.sqrMagnitude == 0f)
|
||||
{
|
||||
cameraPlanarDirection = Vector3.ProjectOnPlane(inputs.Look * Vector3.up, Motor.CharacterUp)
|
||||
.normalized;
|
||||
}
|
||||
|
||||
//var cameraPlanarRotation = Quaternion.LookRotation(cameraPlanarDirection, Motor.CharacterUp);
|
||||
|
||||
_moveInputVector = inputs.MoveVector; // cameraPlanarRotation *
|
||||
_lookInputVector = cameraPlanarDirection;
|
||||
}
|
||||
|
||||
private Quaternion _tmpTransientRot;
|
||||
private MotionHandle _crouchTransition;
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is called before the character begins its movement update
|
||||
/// </summary>
|
||||
public void BeforeCharacterUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is where you tell your character what its rotation should be right now.
|
||||
/// This is the ONLY place where you should set the character's rotation
|
||||
/// </summary>
|
||||
public void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
|
||||
{
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
if (_lookInputVector.sqrMagnitude > 0f && OrientationSharpness > 0f)
|
||||
{
|
||||
// Smoothly interpolate from current to target look direction
|
||||
|
||||
Vector3 smoothedLookInputDirection = Vector3.Slerp(Motor.CharacterForward, _lookInputVector,
|
||||
1 - Mathf.Exp(-OrientationSharpness * deltaTime)).normalized;
|
||||
|
||||
// Set the current rotation (which will be used by the KinematicCharacterMotor)
|
||||
currentRotation = Quaternion.LookRotation(smoothedLookInputDirection, Motor.CharacterUp);
|
||||
}
|
||||
|
||||
Vector3 currentUp = (currentRotation * Vector3.up);
|
||||
if (BonusOrientationMethod == BonusOrientationMethod.TowardsGravity)
|
||||
{
|
||||
// Rotate from current up to invert gravity
|
||||
Vector3 smoothedGravityDir = Vector3.Slerp(currentUp, -Gravity.normalized,
|
||||
1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime));
|
||||
currentRotation = Quaternion.FromToRotation(currentUp, smoothedGravityDir) * currentRotation;
|
||||
}
|
||||
else if (BonusOrientationMethod == BonusOrientationMethod.TowardsGroundSlopeAndGravity)
|
||||
{
|
||||
if (Motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
Vector3 initialCharacterBottomHemiCenter =
|
||||
Motor.TransientPosition + (currentUp * Motor.Capsule.radius);
|
||||
|
||||
Vector3 smoothedGroundNormal = Vector3.Slerp(Motor.CharacterUp,
|
||||
Motor.GroundingStatus.GroundNormal,
|
||||
1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime));
|
||||
currentRotation = Quaternion.FromToRotation(currentUp, smoothedGroundNormal) *
|
||||
currentRotation;
|
||||
|
||||
// Move the position to create a rotation around the bottom hemi center instead of around the pivot
|
||||
Motor.SetTransientPosition(initialCharacterBottomHemiCenter +
|
||||
(currentRotation * Vector3.down * Motor.Capsule.radius));
|
||||
}
|
||||
else
|
||||
{
|
||||
BonusOrientationGravitySharpness = 0.01f;
|
||||
Vector3 smoothedGravityDir = Vector3.Slerp(currentUp, Motor.Velocity.normalized,
|
||||
1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime *
|
||||
BonusOrientationGravitySharpness));
|
||||
// Vector3 smoothedGravityDir = Vector3.Slerp(currentUp, -Gravity.normalized,
|
||||
// 1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime * BonusOrientationGravitySharpness));
|
||||
currentRotation = Quaternion.FromToRotation(currentUp, smoothedGravityDir) *
|
||||
currentRotation;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector3 smoothedGravityDir = Vector3.Slerp(currentUp, Vector3.up,
|
||||
1 - Mathf.Exp(-BonusOrientationSharpness * deltaTime));
|
||||
currentRotation = Quaternion.FromToRotation(currentUp, smoothedGravityDir) * currentRotation;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is where you tell your character what its velocity should be right now.
|
||||
/// This is the ONLY place where you can set the character's velocity
|
||||
/// </summary>
|
||||
public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
// Ground movement
|
||||
if (Motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
float currentVelocityMagnitude = currentVelocity.magnitude;
|
||||
|
||||
Vector3 effectiveGroundNormal = Motor.GroundingStatus.GroundNormal;
|
||||
|
||||
// Reorient velocity on slope
|
||||
currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, effectiveGroundNormal) *
|
||||
currentVelocityMagnitude;
|
||||
|
||||
// Calculate target velocity
|
||||
Vector3 inputRight = Vector3.Cross(_moveInputVector, Motor.CharacterUp);
|
||||
|
||||
Vector3 reorientedInput = Vector3.Cross(effectiveGroundNormal, inputRight).normalized *
|
||||
_moveInputVector.magnitude;
|
||||
|
||||
Vector3 targetMovementVelocity;
|
||||
|
||||
switch (_isCrouching)
|
||||
{
|
||||
case true when _isSliding && !_isSlideEnded:
|
||||
{
|
||||
_slideCurveProgress += deltaTime;
|
||||
|
||||
var slideMultiplier = SlideSpeedMultiplierCurve
|
||||
.Evaluate(_slideCurveProgress * SlideSpeedCurveStep);
|
||||
targetMovementVelocity = reorientedInput * (MaxStableMoveSpeed * slideMultiplier);
|
||||
|
||||
if (_slideCurveProgress >= 1f) _isSlideEnded = true;
|
||||
break;
|
||||
}
|
||||
case true:
|
||||
targetMovementVelocity = reorientedInput * MaxCrouchMoveSpeed;
|
||||
break;
|
||||
default:
|
||||
targetMovementVelocity = reorientedInput * MaxStableMoveSpeed;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_isSprinting) targetMovementVelocity *= SprintingModifier;
|
||||
|
||||
// Smooth movement Velocity
|
||||
currentVelocity = Vector3.Lerp(currentVelocity, targetMovementVelocity,
|
||||
1f - Mathf.Exp(-StableMovementSharpness * deltaTime));
|
||||
}
|
||||
// Air movement
|
||||
else
|
||||
{
|
||||
// Add move input
|
||||
if (_moveInputVector.sqrMagnitude > 0f)
|
||||
{
|
||||
Vector3 addedVelocity = _moveInputVector * (AirAccelerationSpeed * deltaTime);
|
||||
|
||||
Vector3 currentVelocityOnInputsPlane =
|
||||
Vector3.ProjectOnPlane(currentVelocity, Motor.CharacterUp);
|
||||
|
||||
// Limit air velocity from inputs
|
||||
if (currentVelocityOnInputsPlane.magnitude < MaxAirMoveSpeed)
|
||||
{
|
||||
// clamp addedVel to make total vel not exceed max vel on inputs plane
|
||||
Vector3 newTotal = Vector3.ClampMagnitude(currentVelocityOnInputsPlane + addedVelocity,
|
||||
MaxAirMoveSpeed);
|
||||
addedVelocity = newTotal - currentVelocityOnInputsPlane;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure added vel doesn't go in the direction of the already-exceeding velocity
|
||||
if (Vector3.Dot(currentVelocityOnInputsPlane, addedVelocity) > 0f)
|
||||
{
|
||||
addedVelocity = Vector3.ProjectOnPlane(addedVelocity,
|
||||
currentVelocityOnInputsPlane.normalized);
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent air-climbing sloped walls
|
||||
if (Motor.GroundingStatus.FoundAnyGround)
|
||||
{
|
||||
if (Vector3.Dot(currentVelocity + addedVelocity, addedVelocity) > 0f)
|
||||
{
|
||||
Vector3 perpenticularObstructionNormal = Vector3
|
||||
.Cross(Vector3.Cross(Motor.CharacterUp, Motor.GroundingStatus.GroundNormal),
|
||||
Motor.CharacterUp).normalized;
|
||||
addedVelocity =
|
||||
Vector3.ProjectOnPlane(addedVelocity, perpenticularObstructionNormal);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply added velocity
|
||||
currentVelocity += addedVelocity;
|
||||
}
|
||||
|
||||
// Gravity
|
||||
currentVelocity += Gravity * deltaTime;
|
||||
|
||||
// Drag
|
||||
currentVelocity *= (1f / (1f + (Drag * deltaTime)));
|
||||
}
|
||||
|
||||
// Handle jumping
|
||||
_jumpedThisFrame = false;
|
||||
_timeSinceJumpRequested += deltaTime;
|
||||
if (_jumpRequested)
|
||||
{
|
||||
// See if we actually are allowed to jump
|
||||
if (!_jumpConsumed &&
|
||||
((AllowJumpingWhenSliding
|
||||
? Motor.GroundingStatus.FoundAnyGround
|
||||
: Motor.GroundingStatus.IsStableOnGround) ||
|
||||
_timeSinceLastAbleToJump <= JumpPostGroundingGraceTime))
|
||||
{
|
||||
// Calculate jump direction before ungrounding
|
||||
Vector3 jumpDirection = Motor.CharacterUp;
|
||||
if (Motor.GroundingStatus.FoundAnyGround && !Motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
jumpDirection = Motor.GroundingStatus.GroundNormal;
|
||||
}
|
||||
|
||||
// Makes the character skip ground probing/snapping on its next update.
|
||||
// If this line weren't here, the character would remain snapped to the ground when trying to jump. Try commenting this line out and see.
|
||||
Motor.ForceUnground();
|
||||
|
||||
// Add to the return velocity and reset jump state
|
||||
currentVelocity += (jumpDirection * JumpUpSpeed) -
|
||||
Vector3.Project(currentVelocity, Motor.CharacterUp);
|
||||
currentVelocity += (_moveInputVector * JumpScalableForwardSpeed);
|
||||
_jumpRequested = false;
|
||||
_jumpConsumed = true;
|
||||
_jumpedThisFrame = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Take into account additive velocity
|
||||
if (_internalVelocityAdd.sqrMagnitude > 0f)
|
||||
{
|
||||
currentVelocity += _internalVelocityAdd;
|
||||
_internalVelocityAdd = Vector3.zero;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is called after the character has finished its movement update
|
||||
/// </summary>
|
||||
public void AfterCharacterUpdate(float deltaTime)
|
||||
{
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
// Handle jump-related values
|
||||
{
|
||||
// Handle jumping pre-ground grace period
|
||||
if (_jumpRequested && _timeSinceJumpRequested > JumpPreGroundingGraceTime)
|
||||
{
|
||||
_jumpRequested = false;
|
||||
}
|
||||
|
||||
if (AllowJumpingWhenSliding
|
||||
? Motor.GroundingStatus.FoundAnyGround
|
||||
: Motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
// If we're on a ground surface, reset jumping values
|
||||
if (!_jumpedThisFrame)
|
||||
{
|
||||
_jumpConsumed = false;
|
||||
}
|
||||
|
||||
_timeSinceLastAbleToJump = 0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep track of time since we were last able to jump (for grace period)
|
||||
_timeSinceLastAbleToJump += deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (_isSliding && _isSlideEnded)
|
||||
{
|
||||
_isSliding = false;
|
||||
IsSliding.Value = false;
|
||||
}
|
||||
// Handle uncrouching
|
||||
if (_isCrouching && !_shouldBeCrouching)
|
||||
{
|
||||
// Do an overlap test with the character's standing height to see if there are any obstructions
|
||||
Motor.SetCapsuleDimensions(0.5f, 2f, 1f);
|
||||
if (Motor.CharacterOverlap(
|
||||
Motor.TransientPosition,
|
||||
Motor.TransientRotation,
|
||||
_probedColliders,
|
||||
Motor.CollidableLayers,
|
||||
QueryTriggerInteraction.Ignore) > 0)
|
||||
{
|
||||
// If obstructions, just stick to crouching dimensions
|
||||
Motor.SetCapsuleDimensions(0.5f, CrouchedCapsuleHeight, CrouchedCapsuleHeight * 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no obstructions, uncrouch
|
||||
if(_crouchTransition.IsPlaying()) _crouchTransition.Cancel();
|
||||
|
||||
_crouchTransition = LMotion.Create(cameraTransform.localPosition.y, 1.71f, OutCrouchTime)
|
||||
.WithEase(Ease.InOutQuad)
|
||||
.BindToLocalPositionY(cameraTransform);
|
||||
|
||||
_isCrouching = false;
|
||||
_isSliding = false;
|
||||
IsSliding.Value = false;
|
||||
_isSlideEnded = false;
|
||||
_slideCurveProgress = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void PostGroundingUpdate(float deltaTime)
|
||||
{
|
||||
// Handle landing and leaving ground
|
||||
if (Motor.GroundingStatus.IsStableOnGround && !Motor.LastGroundingStatus.IsStableOnGround)
|
||||
{
|
||||
OnLanded();
|
||||
}
|
||||
else if (!Motor.GroundingStatus.IsStableOnGround && Motor.LastGroundingStatus.IsStableOnGround)
|
||||
{
|
||||
OnLeaveStableGround();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsColliderValidForCollisions(Collider coll)
|
||||
{
|
||||
if (IgnoredColliders.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IgnoredColliders.Contains(coll))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnGroundHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddVelocity(Vector3 velocity)
|
||||
{
|
||||
switch (CurrentCharacterState)
|
||||
{
|
||||
case CharacterState.Default:
|
||||
{
|
||||
_internalVelocityAdd += velocity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint,
|
||||
Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
protected void OnLanded()
|
||||
{
|
||||
}
|
||||
|
||||
protected void OnLeaveStableGround()
|
||||
{
|
||||
}
|
||||
|
||||
public void OnDiscreteCollisionDetected(Collider hitCollider)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45d9830d22b54832ade96a92f599643a
|
||||
timeCreated: 1785846388
|
||||
Reference in new issue
Block a user