diff options
| author | SmallFox <2806143047@qq.com> | 2026-05-31 17:42:01 +0800 |
|---|---|---|
| committer | SmallFox <2806143047@qq.com> | 2026-05-31 17:42:01 +0800 |
| commit | ff1e4698f877ead17ee723ff465f26fad58cd0a0 (patch) | |
| tree | 14a97ffbf7e360c8676ba81037d582b9c0aaaec6 /Assets/Scripts | |
| parent | dca6ed8a79a1b4df00720a02f5ae96b2ec9e7283 (diff) | |
合并最新分支,重构Roll,增加了Step_Back,有点手感问题后面调
Diffstat (limited to 'Assets/Scripts')
| -rw-r--r-- | Assets/Scripts/AnimatorHandler.cs | 31 | ||||
| -rw-r--r-- | Assets/Scripts/CameraHandler.cs | 16 | ||||
| -rw-r--r-- | Assets/Scripts/InputHandler.cs | 18 | ||||
| -rw-r--r-- | Assets/Scripts/InputSystem/PlayerControls.cs | 100 | ||||
| -rw-r--r-- | Assets/Scripts/InputSystem/PlayerControls.inputactions | 39 | ||||
| -rw-r--r-- | Assets/Scripts/PlayerLocomotion.cs | 112 | ||||
| -rw-r--r-- | Assets/Scripts/PlayerManager.cs | 17 | ||||
| -rw-r--r-- | Assets/Scripts/ResetIsInteracting.cs | 15 | ||||
| -rw-r--r-- | Assets/Scripts/ResetIsInteracting.cs.meta | 11 |
9 files changed, 277 insertions, 82 deletions
diff --git a/Assets/Scripts/AnimatorHandler.cs b/Assets/Scripts/AnimatorHandler.cs index 16f0f67..775ffc4 100644 --- a/Assets/Scripts/AnimatorHandler.cs +++ b/Assets/Scripts/AnimatorHandler.cs @@ -13,11 +13,12 @@ namespace DS { [Header("绑定")] public Transform rootMotionRotation; // 将模型旋转绑定到 RootMotion - public InputHandler inputHandler; - + + [Header("组件引用")] public PlayerLocomotion playerLocomotion; // 玩家移动控制器引用,用于传递根运动数据 public Animator animator; // 动画器组件引用 + public InputHandler inputHandler; [Header("动画参数哈希")] private int _vertical; // "Vertical" 动画参数的哈希值,用于高效设置动画参数 @@ -26,6 +27,8 @@ namespace DS [Header("旋转状态")] public bool canRotate; // 是否允许角色旋转,在动画事件中控制 + + /// <summary> /// 初始化函数 - 获取 Animator 组件并计算动画参数的哈希值。 @@ -35,6 +38,8 @@ namespace DS { // 获取当前 GameObject 上的 Animator 组件 animator = GetComponent<Animator>(); + inputHandler = GetComponentInParent<InputHandler>(); + playerLocomotion = GetComponentInParent<PlayerLocomotion>(); // 使用 Animator.StringToHash 将字符串参数名转换为整数哈希值 // 这样在 SetFloat 时使用哈希值比使用字符串更高效 @@ -117,6 +122,14 @@ namespace DS animator.SetFloat(_horizontal, h, 0.1f, Time.deltaTime); } + public void PlayerTargetAnimation(string targetAnim, bool isInteractions) + { + Debug.Log($"尝试播放动画: {targetAnim}"); + animator.applyRootMotion = isInteractions; + animator.SetBool("isInteracting",isInteractions); + animator.CrossFade(targetAnim,0.2f); + } + /// <summary> /// 触发动画的翻滚 /// </summary> @@ -157,6 +170,20 @@ namespace DS // 将根运动数据传递给 PlayerLocomotion 组件 // PlayerLocomotion 会将这些位移应用到角色控制器上 playerLocomotion.rootMotion = rootMotion; + + if (inputHandler.isInteracting == false) + { + return; + } + + //更改刚体速度方案 + // float delta = Time.deltaTime; + // playerLocomotion.rigidbody.drag = 0; + // Vector3 deltaPosition = animator.deltaPosition; + // deltaPosition.y = 0; + // Vector3 velocity = deltaPosition / delta; + // playerLocomotion.rigidbody.velocity = velocity; + } /// <summary> diff --git a/Assets/Scripts/CameraHandler.cs b/Assets/Scripts/CameraHandler.cs index a1cd569..0e4a5e9 100644 --- a/Assets/Scripts/CameraHandler.cs +++ b/Assets/Scripts/CameraHandler.cs @@ -2,6 +2,7 @@ using System; using System.Collections; using System.Collections.Generic; using Unity.Mathematics; +using UnityEditor; using UnityEngine; namespace DS @@ -154,7 +155,6 @@ namespace DS // 计算从枢轴指向摄像机的方向向量 Vector3 direction = cameraTransform.position - cameraPivotTransform.position; direction.Normalize(); - // 从枢轴位置沿 direction 方向进行 SphereCast 检测 // 检测距离为 _targetPosition 的绝对值 if (Physics.SphereCast( @@ -167,10 +167,19 @@ namespace DS { // 计算枢轴到碰撞点的实际距离 float dis = Vector3.Distance(cameraPivotTransform.position, hit.point); - // 摄像机应位于碰撞点前方 cameraCollisionOffSet 处 - _targetPosition = -(dis - cameraCollisionOffSet); + + float newPos = -(dis - cameraCollisionOffSet); + _targetPosition = Mathf.Clamp(newPos, _defaultPosition, -minimumCollisionOffSet); + + // // 摄像机应位于碰撞点前方 cameraCollisionOffSet 处 + // _targetPosition = -(dis - cameraCollisionOffSet); + } else + { + // 无碰撞时,确保相机回到默认位置,但也要限制一下,防止超出 + _targetPosition = Mathf.Clamp(_defaultPosition, _defaultPosition, -minimumCollisionOffSet); } + // 如果计算出的目标距离绝对值太小,强制使用最小值防止视觉异常 if (Mathf.Abs(_targetPosition) < minimumCollisionOffSet) { @@ -186,5 +195,6 @@ namespace DS // 应用位置 cameraTransform.localPosition = _cameraTransformPosition; } + } } diff --git a/Assets/Scripts/InputHandler.cs b/Assets/Scripts/InputHandler.cs index 9d2ab72..e1c70d0 100644 --- a/Assets/Scripts/InputHandler.cs +++ b/Assets/Scripts/InputHandler.cs @@ -28,6 +28,10 @@ namespace DS [Tooltip("鼠标或右摇杆的垂直移动增量")] public float mouseY; + public bool b_Input; + public bool rollFlag; + public bool isInteracting; + [Header("其他操作输入")] [Tooltip("翻滚是否触发")] public bool rollTriggered; @@ -81,9 +85,6 @@ namespace DS _inputActions.PlayerMovement.Camera.performed += ctx => _cameraInput = ctx.ReadValue<Vector2>(); - // 增加翻滚行为 - _inputActions.PlayerMovement.Roll.performed += - ctx => rollTriggered = ctx.ReadValueAsButton(); } // 启用输入动作监听 @@ -107,6 +108,7 @@ namespace DS public void TickInput(float delta) { MoveInput(delta); + HandleRollInput(delta); } // ===== 私有输入处理逻辑 ===== @@ -128,5 +130,15 @@ namespace DS mouseX = _cameraInput.x; mouseY = _cameraInput.y; } + + private void HandleRollInput(float delta) + { + b_Input = _inputActions.PlayerActions.Roll.phase == UnityEngine.InputSystem.InputActionPhase.Performed; + Debug.Log(b_Input); + if (b_Input) + { + rollFlag = true; + } + } } } diff --git a/Assets/Scripts/InputSystem/PlayerControls.cs b/Assets/Scripts/InputSystem/PlayerControls.cs index c77acf2..128521d 100644 --- a/Assets/Scripts/InputSystem/PlayerControls.cs +++ b/Assets/Scripts/InputSystem/PlayerControls.cs @@ -44,15 +44,6 @@ public partial class @PlayerControls: IInputActionCollection2, IDisposable ""processors"": """", ""interactions"": """", ""initialStateCheck"": true - }, - { - ""name"": ""Roll"", - ""type"": ""Button"", - ""id"": ""5e423815-95ec-43c1-9718-224f86c8f24e"", - ""expectedControlType"": ""Button"", - ""processors"": """", - ""interactions"": """", - ""initialStateCheck"": false } ], ""bindings"": [ @@ -132,10 +123,38 @@ public partial class @PlayerControls: IInputActionCollection2, IDisposable ""action"": ""Camera"", ""isComposite"": false, ""isPartOfComposite"": false + } + ] + }, + { + ""name"": ""Player Actions"", + ""id"": ""e698248c-d44d-4c32-9308-df1fb8952042"", + ""actions"": [ + { + ""name"": ""Roll"", + ""type"": ""Button"", + ""id"": ""b5381d00-a598-472a-96b6-e7a5ed618a96"", + ""expectedControlType"": ""Button"", + ""processors"": """", + ""interactions"": """", + ""initialStateCheck"": false + } + ], + ""bindings"": [ + { + ""name"": """", + ""id"": ""8af511c9-0a47-4f49-b1e0-a98500b70c9d"", + ""path"": ""<Gamepad>/buttonEast"", + ""interactions"": """", + ""processors"": """", + ""groups"": """", + ""action"": ""Roll"", + ""isComposite"": false, + ""isPartOfComposite"": false }, { ""name"": """", - ""id"": ""4690e573-c6d7-4c20-bbee-ba5d11ca8a18"", + ""id"": ""a76c6730-3d6e-4609-a3fb-450fe20ef6e2"", ""path"": ""<Keyboard>/space"", ""interactions"": """", ""processors"": """", @@ -153,7 +172,9 @@ public partial class @PlayerControls: IInputActionCollection2, IDisposable m_PlayerMovement = asset.FindActionMap("Player Movement", throwIfNotFound: true); m_PlayerMovement_Movement = m_PlayerMovement.FindAction("Movement", throwIfNotFound: true); m_PlayerMovement_Camera = m_PlayerMovement.FindAction("Camera", throwIfNotFound: true); - m_PlayerMovement_Roll = m_PlayerMovement.FindAction("Roll", throwIfNotFound: true); + // Player Actions + m_PlayerActions = asset.FindActionMap("Player Actions", throwIfNotFound: true); + m_PlayerActions_Roll = m_PlayerActions.FindAction("Roll", throwIfNotFound: true); } public void Dispose() @@ -217,14 +238,12 @@ public partial class @PlayerControls: IInputActionCollection2, IDisposable private List<IPlayerMovementActions> m_PlayerMovementActionsCallbackInterfaces = new List<IPlayerMovementActions>(); private readonly InputAction m_PlayerMovement_Movement; private readonly InputAction m_PlayerMovement_Camera; - private readonly InputAction m_PlayerMovement_Roll; public struct PlayerMovementActions { private @PlayerControls m_Wrapper; public PlayerMovementActions(@PlayerControls wrapper) { m_Wrapper = wrapper; } public InputAction @Movement => m_Wrapper.m_PlayerMovement_Movement; public InputAction @Camera => m_Wrapper.m_PlayerMovement_Camera; - public InputAction @Roll => m_Wrapper.m_PlayerMovement_Roll; public InputActionMap Get() { return m_Wrapper.m_PlayerMovement; } public void Enable() { Get().Enable(); } public void Disable() { Get().Disable(); } @@ -240,9 +259,6 @@ public partial class @PlayerControls: IInputActionCollection2, IDisposable @Camera.started += instance.OnCamera; @Camera.performed += instance.OnCamera; @Camera.canceled += instance.OnCamera; - @Roll.started += instance.OnRoll; - @Roll.performed += instance.OnRoll; - @Roll.canceled += instance.OnRoll; } private void UnregisterCallbacks(IPlayerMovementActions instance) @@ -253,9 +269,6 @@ public partial class @PlayerControls: IInputActionCollection2, IDisposable @Camera.started -= instance.OnCamera; @Camera.performed -= instance.OnCamera; @Camera.canceled -= instance.OnCamera; - @Roll.started -= instance.OnRoll; - @Roll.performed -= instance.OnRoll; - @Roll.canceled -= instance.OnRoll; } public void RemoveCallbacks(IPlayerMovementActions instance) @@ -273,10 +286,59 @@ public partial class @PlayerControls: IInputActionCollection2, IDisposable } } public PlayerMovementActions @PlayerMovement => new PlayerMovementActions(this); + + // Player Actions + private readonly InputActionMap m_PlayerActions; + private List<IPlayerActionsActions> m_PlayerActionsActionsCallbackInterfaces = new List<IPlayerActionsActions>(); + private readonly InputAction m_PlayerActions_Roll; + public struct PlayerActionsActions + { + private @PlayerControls m_Wrapper; + public PlayerActionsActions(@PlayerControls wrapper) { m_Wrapper = wrapper; } + public InputAction @Roll => m_Wrapper.m_PlayerActions_Roll; + public InputActionMap Get() { return m_Wrapper.m_PlayerActions; } + public void Enable() { Get().Enable(); } + public void Disable() { Get().Disable(); } + public bool enabled => Get().enabled; + public static implicit operator InputActionMap(PlayerActionsActions set) { return set.Get(); } + public void AddCallbacks(IPlayerActionsActions instance) + { + if (instance == null || m_Wrapper.m_PlayerActionsActionsCallbackInterfaces.Contains(instance)) return; + m_Wrapper.m_PlayerActionsActionsCallbackInterfaces.Add(instance); + @Roll.started += instance.OnRoll; + @Roll.performed += instance.OnRoll; + @Roll.canceled += instance.OnRoll; + } + + private void UnregisterCallbacks(IPlayerActionsActions instance) + { + @Roll.started -= instance.OnRoll; + @Roll.performed -= instance.OnRoll; + @Roll.canceled -= instance.OnRoll; + } + + public void RemoveCallbacks(IPlayerActionsActions instance) + { + if (m_Wrapper.m_PlayerActionsActionsCallbackInterfaces.Remove(instance)) + UnregisterCallbacks(instance); + } + + public void SetCallbacks(IPlayerActionsActions instance) + { + foreach (var item in m_Wrapper.m_PlayerActionsActionsCallbackInterfaces) + UnregisterCallbacks(item); + m_Wrapper.m_PlayerActionsActionsCallbackInterfaces.Clear(); + AddCallbacks(instance); + } + } + public PlayerActionsActions @PlayerActions => new PlayerActionsActions(this); public interface IPlayerMovementActions { void OnMovement(InputAction.CallbackContext context); void OnCamera(InputAction.CallbackContext context); + } + public interface IPlayerActionsActions + { void OnRoll(InputAction.CallbackContext context); } } diff --git a/Assets/Scripts/InputSystem/PlayerControls.inputactions b/Assets/Scripts/InputSystem/PlayerControls.inputactions index f3edee9..0878606 100644 --- a/Assets/Scripts/InputSystem/PlayerControls.inputactions +++ b/Assets/Scripts/InputSystem/PlayerControls.inputactions @@ -22,15 +22,6 @@ "processors": "", "interactions": "", "initialStateCheck": true - }, - { - "name": "Roll", - "type": "Button", - "id": "5e423815-95ec-43c1-9718-224f86c8f24e", - "expectedControlType": "Button", - "processors": "", - "interactions": "", - "initialStateCheck": false } ], "bindings": [ @@ -110,10 +101,38 @@ "action": "Camera", "isComposite": false, "isPartOfComposite": false + } + ] + }, + { + "name": "Player Actions", + "id": "e698248c-d44d-4c32-9308-df1fb8952042", + "actions": [ + { + "name": "Roll", + "type": "Button", + "id": "b5381d00-a598-472a-96b6-e7a5ed618a96", + "expectedControlType": "Button", + "processors": "", + "interactions": "", + "initialStateCheck": false + } + ], + "bindings": [ + { + "name": "", + "id": "8af511c9-0a47-4f49-b1e0-a98500b70c9d", + "path": "<Gamepad>/buttonEast", + "interactions": "", + "processors": "", + "groups": "", + "action": "Roll", + "isComposite": false, + "isPartOfComposite": false }, { "name": "", - "id": "4690e573-c6d7-4c20-bbee-ba5d11ca8a18", + "id": "a76c6730-3d6e-4609-a3fb-450fe20ef6e2", "path": "<Keyboard>/space", "interactions": "", "processors": "", diff --git a/Assets/Scripts/PlayerLocomotion.cs b/Assets/Scripts/PlayerLocomotion.cs index 5203432..5952325 100644 --- a/Assets/Scripts/PlayerLocomotion.cs +++ b/Assets/Scripts/PlayerLocomotion.cs @@ -110,7 +110,9 @@ namespace DS // ============================================================ private void Update() { - UpdateCharacterMovement(); + float delta = Time.deltaTime; // 获取帧时间 + UpdateCharacterMovement(delta); + HandleRollingAndSpringting(delta); } // ============================================================ @@ -121,14 +123,56 @@ namespace DS // 当前未在此处处理逻辑 // 若需要基于物理的移动,可将 rigidbody.velocity 赋值移到这里 } + + // ============================================================ + // 移动与旋转相关方法 + // ============================================================ + #region Movement + /// <summary> + /// 处理角色旋转逻辑。 + /// 根据输入方向和摄像机朝向,平滑旋转角色面向移动方向。 + /// </summary> + /// <param name="delta">帧时间(秒)</param> + private void HandleRotation(float delta) + { + Vector3 targetDir = Vector3.zero; // 目标朝向向量 + // 注意:当前未使用 moveOverride,保留备用 + float moveOverride = _inputHandler.moveAmount; + + // ---------------------------------------------------------- + // 1. 根据输入计算目标朝向 + // ---------------------------------------------------------- + // 目标朝向 = 摄像机正方向 * 垂直输入 + 摄像机右方向 * 水平输入 + targetDir = _cameraObject.forward * _inputHandler.vertical; + targetDir += _cameraObject.right * _inputHandler.horizontal; + + // 归一化并置平 Y 轴 + targetDir.Normalize(); + targetDir.y = 0; + + // 如果没有输入(目标方向为零向量),则保持当前面向不变 + if (targetDir == Vector3.zero) + { + targetDir = myTransform.forward; + } + + // ---------------------------------------------------------- + // 2. 通过 Slerp 平滑旋转至目标方向 + // ---------------------------------------------------------- + float rs = rotationSpeed; // 旋转速度 + Quaternion tr = Quaternion.LookRotation(targetDir); // 目标旋转四元数 + // 使用球形插值(Slerp)实现平滑旋转 + Quaternion targetRotation = Quaternion.Slerp(myTransform.rotation, tr, rs * delta); + + // 应用旋转 + myTransform.rotation = targetRotation; + } // ============================================================ // 角色移动更新(核心逻辑) // ============================================================ - private void UpdateCharacterMovement() + private void UpdateCharacterMovement(float delta) { - float delta = Time.deltaTime; // 获取帧时间 - // 处理输入(读取水平/垂直输入值) _inputHandler.TickInput(delta); @@ -190,51 +234,31 @@ namespace DS } } - // ============================================================ - // 移动与旋转相关方法 - // ============================================================ - #region Movement - - /// <summary> - /// 处理角色旋转逻辑。 - /// 根据输入方向和摄像机朝向,平滑旋转角色面向移动方向。 - /// </summary> - /// <param name="delta">帧时间(秒)</param> - private void HandleRotation(float delta) + private void HandleRollingAndSpringting(float delta) { - Vector3 targetDir = Vector3.zero; // 目标朝向向量 - // 注意:当前未使用 moveOverride,保留备用 - float moveOverride = _inputHandler.moveAmount; - - // ---------------------------------------------------------- - // 1. 根据输入计算目标朝向 - // ---------------------------------------------------------- - // 目标朝向 = 摄像机正方向 * 垂直输入 + 摄像机右方向 * 水平输入 - targetDir = _cameraObject.forward * _inputHandler.vertical; - targetDir += _cameraObject.right * _inputHandler.horizontal; - - // 归一化并置平 Y 轴 - targetDir.Normalize(); - targetDir.y = 0; - - // 如果没有输入(目标方向为零向量),则保持当前面向不变 - if (targetDir == Vector3.zero) + if (animatorHandler.animator.GetBool("isInteracting")) { - targetDir = myTransform.forward; + return; } - // ---------------------------------------------------------- - // 2. 通过 Slerp 平滑旋转至目标方向 - // ---------------------------------------------------------- - float rs = rotationSpeed; // 旋转速度 - Quaternion tr = Quaternion.LookRotation(targetDir); // 目标旋转四元数 - // 使用球形插值(Slerp)实现平滑旋转 - Quaternion targetRotation = Quaternion.Slerp(myTransform.rotation, tr, rs * delta); - - // 应用旋转 - myTransform.rotation = targetRotation; + if (_inputHandler.rollFlag) + { + _moveDirection = _cameraObject.forward * _inputHandler.vertical; + _moveDirection += _cameraObject.right * _inputHandler.horizontal; + + if (_inputHandler.moveAmount > 0) + { + animatorHandler.PlayerTargetAnimation("Roll",true); + _moveDirection.y = 0; + Quaternion rollRotation = Quaternion.LookRotation(_moveDirection); + myTransform.rotation = rollRotation; + } + else + { + animatorHandler.PlayerTargetAnimation("step_back",true); + } + } } - #endregion } diff --git a/Assets/Scripts/PlayerManager.cs b/Assets/Scripts/PlayerManager.cs index 46a2894..1acd8e4 100644 --- a/Assets/Scripts/PlayerManager.cs +++ b/Assets/Scripts/PlayerManager.cs @@ -1,8 +1,23 @@ +using System; using System.Collections; using System.Collections.Generic; +using DS; using UnityEngine; public class PlayerManager : MonoBehaviour { - public Animator animator; + private InputHandler _inputHandler; + private Animator _animator; + + private void Start() + { + _inputHandler = GetComponent<InputHandler>(); + _animator = GetComponentInChildren<Animator>(); + } + + private void Update() + { + _inputHandler.isInteracting = _animator.GetBool("isInteracting"); + _inputHandler.rollFlag = false; + } } diff --git a/Assets/Scripts/ResetIsInteracting.cs b/Assets/Scripts/ResetIsInteracting.cs new file mode 100644 index 0000000..a587a68 --- /dev/null +++ b/Assets/Scripts/ResetIsInteracting.cs @@ -0,0 +1,15 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class ResetIsInteracting : StateMachineBehaviour +{ + + // OnStateExit is called when a transition ends and the state machine finishes evaluating this state + override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) + { + animator.SetBool("isInteracting", false); + } +} + + diff --git a/Assets/Scripts/ResetIsInteracting.cs.meta b/Assets/Scripts/ResetIsInteracting.cs.meta new file mode 100644 index 0000000..1a66f6c --- /dev/null +++ b/Assets/Scripts/ResetIsInteracting.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c1eaee900a90ae44d8ea71f8887cfcd2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |
