结构大修改,改成朴实无华的结构,不过度架构。能跑就行
This commit is contained in:
@@ -0,0 +1,427 @@
|
||||
using System.Collections.Generic;
|
||||
using Fantasy;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using Fantasy.Helper;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct MoveState
|
||||
{
|
||||
public Vector3 startPosition; // 开始移动时的位置
|
||||
public Vector3 moveDirection; // 移动方向(标准化向量)
|
||||
public float moveSpeed; // 移动速度
|
||||
public bool isMoving; // 是否正在移动
|
||||
public double serverTimestamp; // 服务器时间戳
|
||||
}
|
||||
|
||||
public class CharacterControllerComponent : Entity
|
||||
{
|
||||
public bool IsSelf;
|
||||
public bool Run;
|
||||
public CharacterController characterController;
|
||||
public PlayerModelAsset PlayerModelAsset;
|
||||
|
||||
public readonly Queue<MoveState> MoveStateQueue = new Queue<MoveState>();
|
||||
|
||||
public Transform transform => characterController.transform;
|
||||
private MoveState currentMoveState;
|
||||
|
||||
// private Vector3 networkFacingDirection;
|
||||
|
||||
// 添加目标位置和旋转用于插值
|
||||
private Vector3 targetPosition;
|
||||
private Quaternion targetRotation;
|
||||
|
||||
// 插值平滑参数
|
||||
public float positionLerpSpeed = 10f;
|
||||
public float rotationLerpSpeed = 10f;
|
||||
|
||||
|
||||
private float currentSpeed = 0f;
|
||||
private float acceleration = 10f; // 加速度
|
||||
|
||||
/// <summary>
|
||||
/// 重力加速度
|
||||
/// </summary>
|
||||
private float gravity = 9.81f;
|
||||
|
||||
|
||||
private Vector3 currentVelocity = Vector3.zero;
|
||||
private float verticalVelocity = 0f;
|
||||
|
||||
private float groundedGravity = -0.5f; // 小的向下力确保角色保持在地面
|
||||
private float airControl = 0.5f; // 空中控制系数
|
||||
|
||||
#region System
|
||||
|
||||
public class MoveComponentDestroySystem : DestroySystem<CharacterControllerComponent>
|
||||
{
|
||||
protected override void Destroy(CharacterControllerComponent self)
|
||||
{
|
||||
self.characterController = null;
|
||||
self.IsSelf = false;
|
||||
self.Run = false;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
if (inputComponent != null)
|
||||
{
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerCanceled;
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerPerformed;
|
||||
|
||||
inputComponent.OnPlayerValueCanceled -= self.OnPlayerValueCanceled;
|
||||
inputComponent.OnPlayerValuePerformed -= self.OnPlayerValuePerformed;
|
||||
}
|
||||
}
|
||||
|
||||
self.PlayerModelAsset = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class MoveComponentAwakeSystem : AwakeSystem<CharacterControllerComponent>
|
||||
{
|
||||
protected override void Awake(CharacterControllerComponent self)
|
||||
{
|
||||
var unitUnityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self.PlayerModelAsset = unitUnityComponent.ModelAsset;
|
||||
self.characterController = unitUnityComponent.GameObject.GetComponent<CharacterController>();
|
||||
self.lastSyncedFacing = self.characterController.transform.forward;
|
||||
// 初始化目标位置和旋转
|
||||
self.targetPosition = self.characterController.transform.position;
|
||||
self.targetRotation = self.characterController.transform.rotation;
|
||||
self.characterController.enabled = true;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
self.IsSelf = true;
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerCanceled;
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerPerformed;
|
||||
|
||||
inputComponent.OnPlayerValueCanceled += self.OnPlayerValueCanceled;
|
||||
inputComponent.OnPlayerValuePerformed += self.OnPlayerValuePerformed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MoveComponentUpdateSystem : UpdateSystem<CharacterControllerComponent>
|
||||
{
|
||||
protected override void Update(CharacterControllerComponent self)
|
||||
{
|
||||
self.ProcessMoveStates();
|
||||
self.CheckRotationSync();
|
||||
// 插值更新位置和旋转
|
||||
self.InterpolatePositionAndRotation();
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
mapUnit.Position = self.characterController.transform.position;
|
||||
mapUnit.Rotation = self.characterController.transform.rotation;
|
||||
var f = mapUnit.Forward;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Input
|
||||
|
||||
private void OnPlayerPerformed(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Run = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerCanceled(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Run = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValueCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
var name = context.action.name;
|
||||
if (name == InputDef.Player.Move)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
SendMoveMessage(v2, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValuePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
// var mapUnit = Parent as MapUnit;
|
||||
// Log.Info($"OnPlayerValuePerformed IsSelf={mapUnit.IsSelf()} id={mapUnit.Id}");
|
||||
var name = context.action.name;
|
||||
if (name == InputDef.Player.Move)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
SendMoveMessage(v2, false);
|
||||
}
|
||||
else if (name == InputDef.Player.Look)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
UpdatePlayerRotation(v2);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Message
|
||||
|
||||
private void SendMoveMessage(Vector3 movementInput, bool isStop = false)
|
||||
{
|
||||
var mapUnit = Parent as MapUnit;
|
||||
|
||||
Vector3 movementDirection = Vector3.zero;
|
||||
|
||||
// 发送本地相对坐标而不是世界坐标
|
||||
if (!isStop)
|
||||
{
|
||||
movementDirection = new Vector3(movementInput.x, 0, movementInput.y);
|
||||
}
|
||||
|
||||
Net.Send(new C2Map_Move()
|
||||
{
|
||||
Direction = movementDirection.ToVector3Info(),
|
||||
IsStop = isStop,
|
||||
IsRun = Run,
|
||||
Timestamp = TimeHelper.Now,
|
||||
Position = mapUnit.Position.ToVector3Info(),
|
||||
Rotation = mapUnit.Forward.ToVector3Info(),
|
||||
});
|
||||
}
|
||||
|
||||
private void SendLookMessage()
|
||||
{
|
||||
Log.Info("发送朝向同步消息");
|
||||
Net.Send(new C2Map_Look()
|
||||
{
|
||||
Rotation = characterController.transform.forward.ToVector3Info(),
|
||||
Timestamp = TimeHelper.Now
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收服务器移动开始通知
|
||||
/// </summary>
|
||||
/// <param name="startPosition"></param>
|
||||
/// <param name="moveDirection"></param>
|
||||
/// <param name="speed"></param>
|
||||
/// <param name="timestamp"></param>
|
||||
public void OnServerStartMove(Vector3 startPosition, Vector3 moveDirection, float speed, double timestamp)
|
||||
{
|
||||
MoveState moveState = new MoveState
|
||||
{
|
||||
startPosition = startPosition,
|
||||
moveDirection = moveDirection.normalized,
|
||||
moveSpeed = speed,
|
||||
isMoving = true,
|
||||
serverTimestamp = timestamp
|
||||
};
|
||||
|
||||
MoveStateQueue.Enqueue(moveState);
|
||||
Log.Info($"MoveStateQueue Count={MoveStateQueue.Count}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 接收服务器移动停止通知
|
||||
/// </summary>
|
||||
/// <param name="finalPosition"></param>
|
||||
/// <param name="timestamp"></param>
|
||||
public void OnServerStopMove(Vector3 finalPosition, double timestamp)
|
||||
{
|
||||
MoveState moveState = new MoveState
|
||||
{
|
||||
startPosition = finalPosition,
|
||||
moveDirection = Vector3.zero,
|
||||
moveSpeed = 0f,
|
||||
isMoving = false,
|
||||
serverTimestamp = timestamp
|
||||
};
|
||||
|
||||
MoveStateQueue.Enqueue(moveState);
|
||||
Log.Info($"MoveStateQueue Count={MoveStateQueue.Count}");
|
||||
}
|
||||
|
||||
|
||||
public void OnServerLook(Vector3 rotation, double timestamp)
|
||||
{
|
||||
// 设置目标旋转用于插值
|
||||
targetRotation = Quaternion.LookRotation(rotation);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Move
|
||||
|
||||
private void ProcessMoveStates()
|
||||
{
|
||||
// 只有在当前状态不是移动状态时,才处理下一个状态
|
||||
if (MoveStateQueue.Count > 0)
|
||||
{
|
||||
currentMoveState = MoveStateQueue.Dequeue();
|
||||
|
||||
if (currentMoveState.isMoving)
|
||||
{
|
||||
StartMovement(currentMoveState);
|
||||
}
|
||||
else
|
||||
{
|
||||
StopMovement(currentMoveState);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果正在移动,持续更新
|
||||
if (currentMoveState.isMoving)
|
||||
{
|
||||
UpdateMovement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void StartMovement(MoveState moveState)
|
||||
{
|
||||
targetPosition = moveState.startPosition;
|
||||
Debug.Log($"开始移动 - 位置: {moveState.startPosition}");
|
||||
}
|
||||
|
||||
private void StopMovement(MoveState moveState)
|
||||
{
|
||||
targetPosition = moveState.startPosition;
|
||||
Debug.Log($"停止移动 - 最终位置: {moveState.startPosition}");
|
||||
}
|
||||
|
||||
private void UpdateMovement()
|
||||
{
|
||||
// 将本地相对方向转换为世界方向
|
||||
Vector3 localDirection = currentMoveState.moveDirection;
|
||||
Vector3 characterRight = Vector3.ProjectOnPlane(characterController.transform.right, Vector3.up).normalized;
|
||||
Vector3 characterForward = Vector3.ProjectOnPlane(characterController.transform.forward, Vector3.up).normalized;
|
||||
Vector3 movementDirection = characterForward * localDirection.z + characterRight * localDirection.x;
|
||||
|
||||
float targetSpeed = currentMoveState.moveSpeed;
|
||||
|
||||
// 平滑加速
|
||||
if (movementDirection.magnitude > 0.1f)
|
||||
{
|
||||
currentSpeed = Mathf.Lerp(currentSpeed, targetSpeed, acceleration * Time.deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSpeed = Mathf.Lerp(currentSpeed, 0f, acceleration * 2f * Time.deltaTime);
|
||||
}
|
||||
|
||||
// 处理重力
|
||||
if (characterController.isGrounded)
|
||||
{
|
||||
verticalVelocity = groundedGravity;
|
||||
|
||||
// 地面移动 - 完全控制
|
||||
currentVelocity = Vector3.Lerp(currentVelocity, movementDirection.normalized * currentSpeed,
|
||||
acceleration * Time.deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
verticalVelocity -= gravity * Time.deltaTime;
|
||||
|
||||
// 空中移动 - 有限控制
|
||||
Vector3 targetAirVelocity = movementDirection.normalized * currentSpeed * airControl;
|
||||
currentVelocity = Vector3.Lerp(currentVelocity,
|
||||
new Vector3(targetAirVelocity.x, currentVelocity.y, targetAirVelocity.z),
|
||||
acceleration * Time.deltaTime);
|
||||
}
|
||||
|
||||
// 组合移动
|
||||
Vector3 totalMovement = currentVelocity * Time.deltaTime;
|
||||
totalMovement.y = verticalVelocity * Time.deltaTime;
|
||||
|
||||
Log.Info($"移动=== Id={Parent.Id} 位置: {characterController.transform.position} 移动量: {totalMovement}");
|
||||
|
||||
characterController.Move(totalMovement);
|
||||
}
|
||||
|
||||
// 添加位置和旋转插值方法
|
||||
private void InterpolatePositionAndRotation()
|
||||
{
|
||||
// 只对非本地玩家进行插值
|
||||
if (!IsSelf)
|
||||
{
|
||||
// 插值位置
|
||||
// characterController.transform.position = Vector3.Lerp(
|
||||
// characterController.transform.position,
|
||||
// targetPosition,
|
||||
// positionLerpSpeed * Time.deltaTime);
|
||||
|
||||
// 插值旋转 - 使用更平滑的插值方法
|
||||
characterController.transform.rotation = Quaternion.Slerp(
|
||||
characterController.transform.rotation,
|
||||
targetRotation,
|
||||
rotationLerpSpeed * Time.deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Look
|
||||
|
||||
public float rotationSyncInterval = 0.15f;
|
||||
public float minRotationChange = 10f;
|
||||
|
||||
private Vector3 _rotationInput = Vector3.zero;
|
||||
private float rotationSyncTimer;
|
||||
private Vector3 lastSyncedFacing;
|
||||
private bool isRotating = false;
|
||||
|
||||
[Tooltip("视角旋转敏感度")] public Vector2 sensitivity = new Vector2(0.015f, 0.015f);
|
||||
|
||||
private void UpdatePlayerRotation(Vector2 lookValue)
|
||||
{
|
||||
// Look
|
||||
Vector2 lookInput = lookValue * sensitivity;
|
||||
|
||||
// 处理水平旋转 (Yaw)
|
||||
if (lookInput.x != 0.0f)
|
||||
{
|
||||
_rotationInput.y += lookInput.x;
|
||||
isRotating = true;
|
||||
}
|
||||
|
||||
// 应用旋转到角色和相机
|
||||
if (_rotationInput != Vector3.zero)
|
||||
{
|
||||
characterController.transform.rotation *= Quaternion.Euler(0, _rotationInput.y, 0);
|
||||
_rotationInput = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
// 检查朝向同步
|
||||
private void CheckRotationSync()
|
||||
{
|
||||
if (!IsSelf) return;
|
||||
rotationSyncTimer += Time.deltaTime;
|
||||
if (rotationSyncTimer >= rotationSyncInterval)
|
||||
{
|
||||
float angleChange = Vector3.Angle(transform.forward, lastSyncedFacing);
|
||||
|
||||
// 修改:即使在旋转中也定期同步朝向,避免累积误差
|
||||
if (angleChange >= minRotationChange || isRotating)
|
||||
{
|
||||
SendLookMessage();
|
||||
lastSyncedFacing = transform.forward;
|
||||
rotationSyncTimer = 0f;
|
||||
isRotating = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36fb267f0f5149caa23ac1b6cf005067
|
||||
timeCreated: 1757164955
|
||||
108
Assets/Scripts/Fishing2~/Unit/Move/CharacterLookComponent.cs
Normal file
108
Assets/Scripts/Fishing2~/Unit/Move/CharacterLookComponent.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using ECM2.Examples.FirstPerson;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class CharacterLookComponent : Entity
|
||||
{
|
||||
// private UnitUnityComponent _UnitUnityComponent;
|
||||
public FirstPersonCharacter FirstPerson { get; set; }
|
||||
private float lookXRot;
|
||||
private float lookYRot;
|
||||
private Vector2 _moveInput;
|
||||
|
||||
public float MouseSensitivity = 0.1f;
|
||||
[Space(15f)] public bool invertLook = true;
|
||||
|
||||
public float minPitch = -60f;
|
||||
|
||||
public float maxPitch = 60f;
|
||||
|
||||
|
||||
private InputComponent _inputComponent;
|
||||
private Quaternion lastRotation;
|
||||
public MapUnit MapUnit;
|
||||
|
||||
#region System
|
||||
|
||||
public class LookComponentDestroySystem : DestroySystem<CharacterLookComponent>
|
||||
{
|
||||
protected override void Destroy(CharacterLookComponent self)
|
||||
{
|
||||
self.FirstPerson = null;
|
||||
// var mapUnit = self.Parent as MapUnit;
|
||||
|
||||
self._inputComponent = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class LookComponentAwakeSystem : AwakeSystem<CharacterLookComponent>
|
||||
{
|
||||
protected override void Awake(CharacterLookComponent self)
|
||||
{
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
self.MapUnit = mapUnit;
|
||||
var unitUnityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self.FirstPerson = unitUnityComponent.FirstPerson;
|
||||
self._inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
}
|
||||
}
|
||||
|
||||
public class LookComponentUpdateSystem : UpdateSystem<CharacterLookComponent>
|
||||
{
|
||||
protected override void Update(CharacterLookComponent self)
|
||||
{
|
||||
self.UpdateLookInput();
|
||||
}
|
||||
}
|
||||
|
||||
// public class LookComponentLateUpdateSystem : LateUpdateSystem<CharacterLookComponent>
|
||||
// {
|
||||
// protected override void LateUpdate(CharacterLookComponent self)
|
||||
// {
|
||||
// self.UpdateLookInput();
|
||||
// }
|
||||
// }
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void UpdateLookInput()
|
||||
{
|
||||
|
||||
// TPPLookTarget.position = base.transform.position;
|
||||
// if (CameraView.Value == CameraViewType.TPP)
|
||||
// {
|
||||
// lookXRot -= MouseInput.Value.y;
|
||||
// lookXRot = Mathf.Clamp(lookXRot, -25f, 55f);
|
||||
// lookYRot += MouseInput.Value.x;
|
||||
// lookYRot = Mathf.Repeat(lookYRot, 360f);
|
||||
// TPPLookTarget.localEulerAngles = new Vector3(lookXRot, lookYRot, 0f);
|
||||
// }
|
||||
// else if (CameraView.Value == CameraViewType.FPP)
|
||||
{
|
||||
// if (_IsInVehicle && PlayerState.Value == State.vehicle)
|
||||
// {
|
||||
// lookXRot -= MouseInput.Value.y;
|
||||
// lookXRot = Mathf.Clamp(lookXRot, VehicleLookXMinMax.x, VehicleLookXMinMax.y);
|
||||
// lookYRot += MouseInput.Value.x;
|
||||
// lookYRot = Mathf.Clamp(lookYRot, VehicleLookYMinMax.x, VehicleLookYMinMax.y);
|
||||
// VehicleLookTargetParent.localEulerAngles = new Vector3(lookXRot, lookYRot, 0f);
|
||||
// _character.CameraPitch = 0f;
|
||||
// }
|
||||
// else
|
||||
{
|
||||
Vector2 value = _inputComponent.GetLookInput();
|
||||
FirstPerson.AddControlYawInput(value.x * (float)MouseSensitivity);
|
||||
FirstPerson.AddControlPitchInput((invertLook ? (0f - value.y) : value.y) * (float)MouseSensitivity,
|
||||
minPitch, maxPitch);
|
||||
// lookXRot = base.transform.eulerAngles.x;
|
||||
// lookYRot = base.transform.eulerAngles.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 316d2e71f8b3473e961ac86ce4568704
|
||||
timeCreated: 1765283815
|
||||
214
Assets/Scripts/Fishing2~/Unit/Move/CharacterMovementComponent.cs
Normal file
214
Assets/Scripts/Fishing2~/Unit/Move/CharacterMovementComponent.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using ECM2;
|
||||
using ECM2.Examples.FirstPerson;
|
||||
using Fantasy.Entitas;
|
||||
using Fantasy.Entitas.Interface;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace NBF.Fishing2
|
||||
{
|
||||
public class CharacterMovementComponent : Entity
|
||||
{
|
||||
public bool IsSelf;
|
||||
public bool Run;
|
||||
|
||||
private Vector2 _moveInput;
|
||||
public MapUnit MapUnit;
|
||||
|
||||
private FirstPersonCharacter _Character;
|
||||
private Quaternion lastRotation;
|
||||
|
||||
#region System
|
||||
|
||||
public class MovementComponentDestroySystem : DestroySystem<CharacterMovementComponent>
|
||||
{
|
||||
protected override void Destroy(CharacterMovementComponent self)
|
||||
{
|
||||
// self.characterController = null;
|
||||
self.IsSelf = false;
|
||||
self.Run = false;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
if (inputComponent != null)
|
||||
{
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerCanceled;
|
||||
inputComponent.OnPlayerPerformed -= self.OnPlayerPerformed;
|
||||
|
||||
inputComponent.OnPlayerValueCanceled -= self.OnPlayerValueCanceled;
|
||||
inputComponent.OnPlayerValuePerformed -= self.OnPlayerValuePerformed;
|
||||
}
|
||||
}
|
||||
|
||||
// self.PlayerAsset = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class MovementComponentAwakeSystem : AwakeSystem<CharacterMovementComponent>
|
||||
{
|
||||
protected override void Awake(CharacterMovementComponent self)
|
||||
{
|
||||
var unitUnityComponent = self.Parent.GetComponent<UnitUnityComponent>();
|
||||
self._Character = unitUnityComponent.FirstPerson;
|
||||
var mapUnit = self.Parent as MapUnit;
|
||||
self.MapUnit = mapUnit;
|
||||
if (mapUnit.IsSelf())
|
||||
{
|
||||
self.IsSelf = true;
|
||||
var inputComponent = self.Scene.GetComponent<InputComponent>();
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerCanceled;
|
||||
inputComponent.OnPlayerPerformed += self.OnPlayerPerformed;
|
||||
|
||||
inputComponent.OnPlayerValueCanceled += self.OnPlayerValueCanceled;
|
||||
inputComponent.OnPlayerValuePerformed += self.OnPlayerValuePerformed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MovementComponentUpdateSystem : UpdateSystem<CharacterMovementComponent>
|
||||
{
|
||||
protected override void Update(CharacterMovementComponent self)
|
||||
{
|
||||
self.UpdateGrounded();
|
||||
self.UpdateWater();
|
||||
self.ProcessMoveStates();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Input
|
||||
|
||||
private void OnPlayerPerformed(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Run = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerCanceled(string action)
|
||||
{
|
||||
if (action == InputDef.Player.Run)
|
||||
{
|
||||
Run = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValueCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
var name = context.action.name;
|
||||
if (name == InputDef.Player.Move)
|
||||
{
|
||||
// var v2 = context.ReadValue<Vector2>();
|
||||
_moveInput = Vector2.zero;
|
||||
// SendMoveMessage(v2, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerValuePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
// var mapUnit = Parent as MapUnit;
|
||||
// Log.Info($"OnPlayerValuePerformed IsSelf={mapUnit.IsSelf()} id={mapUnit.Id}");
|
||||
var name = context.action.name;
|
||||
if (name == InputDef.Player.Move)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
_moveInput = v2;
|
||||
// SendMoveMessage(v2, false);
|
||||
}
|
||||
else if (name == InputDef.Player.Look)
|
||||
{
|
||||
var v2 = context.ReadValue<Vector2>();
|
||||
// UpdatePlayerRotation(v2);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Move
|
||||
|
||||
private void UpdateGrounded()
|
||||
{
|
||||
MapUnit.IsGrounded = _Character.IsGrounded();
|
||||
MapUnit.Speed = _Character.velocity.magnitude;
|
||||
|
||||
|
||||
Quaternion rotation = _Character.transform.rotation;
|
||||
|
||||
// 计算当前帧与上一帧的旋转差异
|
||||
Quaternion rotationDelta = rotation * Quaternion.Inverse(lastRotation);
|
||||
|
||||
// 将四元数转换为角度轴表示
|
||||
rotationDelta.ToAngleAxis(out float angle, out Vector3 axis);
|
||||
|
||||
// 确保角度在0-360范围内
|
||||
if (angle > 180f) angle -= 360f;
|
||||
|
||||
// 获取Y轴旋转分量(归一化处理)
|
||||
float yRotation = 0f;
|
||||
if (Mathf.Abs(angle) > 0.001f && Mathf.Abs(axis.y) > 0.1f)
|
||||
{
|
||||
// 计算Y轴方向的旋转角度(考虑旋转轴方向)
|
||||
yRotation = angle * Mathf.Sign(axis.y);
|
||||
}
|
||||
|
||||
float maxTurnSpeed = 180f; // 度/秒
|
||||
// 转换为角速度并归一化到[-1, 1]
|
||||
float angularSpeed = yRotation / Time.deltaTime;
|
||||
float turnValue = Mathf.Clamp(angularSpeed / maxTurnSpeed, -1f, 1f);
|
||||
|
||||
|
||||
MapUnit.RotationSpeed = turnValue;
|
||||
|
||||
lastRotation = rotation;
|
||||
}
|
||||
|
||||
private void UpdateWater()
|
||||
{
|
||||
// SceneSettings.Instance.Water.w
|
||||
}
|
||||
|
||||
private void ProcessMoveStates()
|
||||
{
|
||||
// if (CameraView.Value == CameraViewType.TPP)
|
||||
// {
|
||||
// float num = (IsRunPressed.Value ? MovementSpeed.Value : (MovementSpeed.Value * 0.5f));
|
||||
// num = (IsFlyModeEnabled ? (num * (float)FlySpeed) : num);
|
||||
// Vector3 zero = Vector3.zero;
|
||||
// zero += Vector3.right * MovementDirection.Value.x;
|
||||
// zero += Vector3.forward * MovementDirection.Value.y;
|
||||
// zero = zero.relativeTo(_CameraTPPTarget, _Character.GetUpVector());
|
||||
// _Character.RotateTowards(zero, Time.deltaTime * _RotateTPPSpeed);
|
||||
// float value = Vector3.Dot(_Character.GetForwardVector(), zero);
|
||||
// Vector3 vector = _Character.GetForwardVector() * Mathf.Clamp01(value) * num;
|
||||
// if (checkWaterBound)
|
||||
// {
|
||||
// SetMovementDirectionWithRaycastCheck(vector);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// _Character.SetMovementDirection(vector);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
{
|
||||
float num2 = Run ? 7 : 5; //(IsRunPressed.Value ? MovementSpeed.Value : (MovementSpeed.Value * 0.5f));
|
||||
// num2 = (IsFlyModeEnabled ? (num2 * (float)FlySpeed) : num2);
|
||||
Vector3 vector2 = _Character.GetRightVector() * _moveInput.x * num2;
|
||||
vector2 += _Character.GetForwardVector() * _moveInput.y * num2;
|
||||
// if (checkWaterBound)
|
||||
// {
|
||||
// SetMovementDirectionWithRaycastCheck(vector2);
|
||||
// }
|
||||
// else
|
||||
{
|
||||
_Character.SetMovementDirection(vector2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f032bbea4a2a4ab099d2f4800670ad48
|
||||
timeCreated: 1765282951
|
||||
Reference in New Issue
Block a user