更新
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using SLSFramework.General;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -11,15 +12,22 @@ namespace Cielonos.MainGame.Characters
|
||||
|
||||
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;
|
||||
@@ -29,6 +37,7 @@ namespace Cielonos.MainGame.Characters
|
||||
{
|
||||
if (inputSc.Look.sqrMagnitude >= RotateThreshold && !lockCameraPosition)
|
||||
{
|
||||
isRecentering = false;
|
||||
float deltaTimeMultiplier = inputSc.CurrentScheme == "KeyboardMouse" ? 1.0f : Time.deltaTime;
|
||||
//if (!viewSc.lockTargetModule.isLockedMelee)
|
||||
{
|
||||
@@ -36,13 +45,26 @@ namespace Cielonos.MainGame.Characters
|
||||
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.cameraTarget.rotation = Quaternion.Euler(
|
||||
viewSc.cameraRoot.rotation = Quaternion.Euler(
|
||||
cinemachineTargetPitch + cameraAngleOverride /*- viewSc.muzzleLiftModule.currentMuzzlePositionY*/, cinemachineTargetYaw, 0.0f);
|
||||
/*
|
||||
/*
|
||||
if (player.motionController.characterRotationType == PlayerMotionController.CharacterRotationType.ByAiming)
|
||||
{
|
||||
player.transform.rotation = Quaternion.Euler(0.0f, cinemachineTargetYaw, 0.0f);
|
||||
@@ -60,7 +82,43 @@ namespace Cielonos.MainGame.Characters
|
||||
cinemachineEndLockYaw = viewSc.lockingCamera.transform.eulerAngles.y;
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [新增] 触发相机战斗校准
|
||||
/// </summary>
|
||||
/// <param name="attackDirection">攻击的方向向量 (通常是 player.transform.forward)</param>
|
||||
/// <param name="duration">校准持续时间 (建议 0.2f ~ 0.5f)</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class LockTargetCamera : MonoBehaviour
|
||||
{
|
||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbc378284638d9549945b8c5090f5a1b
|
||||
@@ -67,7 +67,7 @@ namespace Cielonos.MainGame.Characters
|
||||
obstructionLayer = LayerMask.GetMask("FadableEnvironment");
|
||||
targetCamera = owner.playerCamera;
|
||||
playerHead = owner.player.bodyPartsSc.head;
|
||||
playerCenter = owner.player.bodyPartsSc.centerPoint;
|
||||
playerCenter = owner.player.bodyPartsSc.flexibleCenterPoint;
|
||||
playerFeet = owner.player.bodyPartsSc.footPoint;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using DG.Tweening;
|
||||
using SLSFramework.General;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Cielonos.MainGame.Characters
|
||||
@@ -11,28 +13,102 @@ namespace Cielonos.MainGame.Characters
|
||||
public Player player => owner;
|
||||
|
||||
public Camera playerCamera;
|
||||
public Transform cameraTarget;
|
||||
public Transform cameraRoot;
|
||||
public CinemachineStateDrivenCamera stateDrivenCamera;
|
||||
public CinemachineCamera freeLookCamera;
|
||||
public CinemachineCamera lockOnCamera;
|
||||
public bool isLockedOn = false;
|
||||
public bool isLockedSetRoot;
|
||||
public CharacterBase testEnemy;
|
||||
public Transform testEnemyTarget;
|
||||
|
||||
public CameraRotationSubmodule cameraRotationSm;
|
||||
public OcclusionFadeSubmodule occlusionFadeSm;
|
||||
|
||||
public LerpFloat cameraDistance;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
cameraRotationSm = new CameraRotationSubmodule(this, player.transform.eulerAngles.y);
|
||||
occlusionFadeSm = new OcclusionFadeSubmodule(this);
|
||||
cameraDistance = new LerpFloat(10f, 1f);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
testEnemyTarget = testEnemy.bodyPartsSc.staticCenterPoint;
|
||||
//SwitchToLockTarget( testEnemyTarget );
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Keyboard.current.tabKey.wasPressedThisFrame)
|
||||
{
|
||||
if (!isLockedOn)
|
||||
{
|
||||
SwitchToLockTarget( testEnemyTarget );
|
||||
}
|
||||
else
|
||||
{
|
||||
SwitchToFreeLook();
|
||||
}
|
||||
}
|
||||
|
||||
cameraDistance.Update(player.selfTimeSm.DeltaTime);
|
||||
freeLookCamera.GetComponent<CinemachineThirdPersonFollow>().CameraDistance = cameraDistance.currentValue;
|
||||
lockOnCamera.GetComponent<CinemachinePositionComposer>().CameraDistance = cameraDistance.currentValue;
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
cameraRotationSm.Update();
|
||||
if (!isLockedOn)
|
||||
{
|
||||
cameraRotationSm.Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isLockedSetRoot) cameraRoot.LookAt(testEnemyTarget);
|
||||
float distance = (testEnemyTarget.position - cameraRoot.transform.position).Flatten().magnitude;
|
||||
if(distance < 1f) SwitchToFreeLook();
|
||||
}
|
||||
occlusionFadeSm.Update();
|
||||
}
|
||||
|
||||
void SwitchToLockTarget(Transform target)
|
||||
{
|
||||
testEnemyTarget = target;
|
||||
isLockedOn = true;
|
||||
isLockedSetRoot = false;
|
||||
|
||||
// --- CM3 核心操作 ---
|
||||
// 1. 设置 LookAt 目标。在 CM3 中,LookingAt 是 Target 结构体的一部分,或者直接赋值给 LookAt 属性
|
||||
lockOnCamera.Target.LookAtTarget = testEnemyTarget;
|
||||
|
||||
// 2. 提高优先级,激活锁定相机
|
||||
stateDrivenCamera.GetComponent<Animator>().SetBool("isLockTarget", true);
|
||||
cameraRoot.DOLookAt(testEnemyTarget.position, 0.5f).SetEase(Ease.InOutSine).OnComplete(()=>isLockedSetRoot = true).Play();
|
||||
|
||||
// (可选) 你可以在这里播放锁定音效或显示 UI 准星
|
||||
Debug.Log($"Locked on: {target.name}");
|
||||
}
|
||||
|
||||
void SwitchToFreeLook()
|
||||
{
|
||||
cameraRotationSm.SyncRotationWithCamera(playerCamera);
|
||||
|
||||
isLockedOn = false;
|
||||
|
||||
// --- CM3 核心操作 ---
|
||||
// 1. 重置 LookAt 目标
|
||||
//lockOnCamera.Target.LookAtTarget = null;
|
||||
|
||||
// 2. 降低优先级,切换回自由视角相机
|
||||
stateDrivenCamera.GetComponent<Animator>().SetBool("isLockTarget", false);
|
||||
|
||||
// (可选) 你可以在这里播放解锁音效或隐藏 UI 准星
|
||||
Debug.Log("Switched to Free Look");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user