using Sirenix.OdinInspector; using SLSFramework.General; using UnityEngine; namespace Cielonos.MainGame.Characters { public class CameraRotationSubmodule : SubmoduleBase { private Player player => owner.player; private PlayerViewSubcontroller viewSc => owner; private PlayerInputSubcontroller inputSc => player.inputSc; private const float RotateThreshold = 0.01f; [Title("Cinemachine Settings")] public float cinemachineTargetYaw; public float cinemachineEndLockYaw; public float cinemachineTargetPitch; public float topClamp = 70.0f; public float bottomClamp = -30.0f; public float cameraAngleOverride = 0.0f; public bool lockCameraPosition = false; [Title("Combat Recenter Settings")] public float recenterSmoothTime = 0.1f; // 平滑时间,越小转得越快 private float recenterVelocity; // SmoothDamp使用的速度变量 private float targetRecenterYaw; // 目标角度 private bool isRecentering = false; // 是否正在校准 private float recenterTimer = 0.0f; // 校准剩余时间 public CameraRotationSubmodule(PlayerViewSubcontroller owner, float initialYaw) : base(owner) { this.cinemachineTargetYaw = initialYaw; } public void Update() { if (inputSc.Look.sqrMagnitude >= RotateThreshold && !lockCameraPosition) { isRecentering = false; float deltaTimeMultiplier = inputSc.CurrentScheme == "KeyboardMouse" ? 1.0f : Time.deltaTime; //if (!viewSc.lockTargetModule.isLockedMelee) { cinemachineTargetYaw += inputSc.Look.x * deltaTimeMultiplier; cinemachineTargetPitch += inputSc.Look.y * deltaTimeMultiplier; } } else if (isRecentering) { recenterTimer -= Time.deltaTime; if (recenterTimer <= 0) { isRecentering = false; } else { cinemachineTargetYaw = Mathf.SmoothDampAngle(cinemachineTargetYaw, targetRecenterYaw, ref recenterVelocity, recenterSmoothTime); } } cinemachineTargetYaw = MathExtensions.ClampAngle(cinemachineTargetYaw, float.MinValue, float.MaxValue); cinemachineTargetPitch = MathExtensions.ClampAngle(cinemachineTargetPitch, bottomClamp, topClamp); viewSc.cameraRoot.rotation = Quaternion.Euler( cinemachineTargetPitch + cameraAngleOverride /*- viewSc.muzzleLiftModule.currentMuzzlePositionY*/, cinemachineTargetYaw, 0.0f); if (viewSc.isLockingTarget) { cinemachineEndLockYaw = viewSc.lockOnCamera.transform.eulerAngles.y; } /* if (player.motionController.characterRotationType == PlayerMotionController.CharacterRotationType.ByAiming) { player.transform.rotation = Quaternion.Euler(0.0f, cinemachineTargetYaw, 0.0f); if (viewSc.lockTargetModule.isLockedMelee) { //cinemachineEndLockYaw = player.viewController.lockingCamera.transform.eulerAngles.y; //player.transform.rotation = Quaternion.Euler(0.0f, cinemachineEndLockYaw, 0.0f); } } else { if (viewSc.lockTargetModule.isLockedMelee) { cinemachineEndLockYaw = viewSc.lockingCamera.transform.eulerAngles.y; } } */ } /// /// [新增] 触发相机战斗校准 /// /// 攻击的方向向量 (通常是 player.transform.forward) /// 校准持续时间 (建议 0.2f ~ 0.5f) public void TriggerCameraRecenter(Vector3 attackDirection, float duration = 0.2f) { if (attackDirection.sqrMagnitude < 0.01f) return; // 计算目标角度 Quaternion targetRot = Quaternion.LookRotation(attackDirection); targetRecenterYaw = targetRot.eulerAngles.y; // 激活状态 recenterTimer = duration; isRecentering = true; } // 将此方法添加到你控制相机旋转的脚本中 (例如 PlayerCameraController) public void SyncRotationWithCamera(Camera camera = null) { camera ??= viewSc.playerCamera; Vector3 currentEuler = camera.transform.eulerAngles; cinemachineTargetYaw = currentEuler.y; float currentPitch = currentEuler.x; if (currentPitch > 180) { currentPitch -= 360; } cinemachineTargetPitch = currentPitch - cameraAngleOverride; isRecentering = false; // 强制执行一次旋转更新,防止下一帧才生效导致的微小跳动 (可选) // viewSc.cameraRoot.rotation = Quaternion.Euler( // cinemachineTargetPitch + cameraAngleOverride, cinemachineTargetYaw, 0.0f); } } }