Bezi回来了

This commit is contained in:
SoulliesOfficial
2026-04-28 15:46:32 -04:00
parent 7379583165
commit 0902ca8a9e
56 changed files with 3285 additions and 3803 deletions

View File

@@ -1,5 +1,6 @@
using Cielonos.MainGame.Effects.Feedback;
using SLSUtilities.General;
using Unity.Mathematics;
using UnityEngine;
namespace Cielonos.MainGame.Characters
@@ -22,9 +23,6 @@ namespace Cielonos.MainGame.Characters
{
player.landMovementSc.TurnToDirection(direction, 0f);
}
// 计算冲刺方向用于相机震动方向设置
// Dash反馈的方向设置将在DashStart中通过新Feedback系统统一处理
}
}
@@ -32,10 +30,15 @@ namespace Cielonos.MainGame.Characters
{
player.landMovementSc.isDashing = true;
player.audioSc.PlayDashSound();
// 使用新Feedback系统播放Dash反馈
player.feedbackSc.PlayFeedback("Dash");
Vector3 playerForward = player.transform.forward.Flatten();
Vector3 cameraForward = player.viewSc.playerCamera.transform.forward.Flatten();
float forwardDot = Vector3.Dot(playerForward, cameraForward);
//如果角色和相机的角度相差120度以上
//播放普通Dash反馈
//播放背向Dash反馈
player.feedbackSc.PlayFeedback(forwardDot < -0.5f ? "Dash_NoCameraRotation" : "Dash");
//player.renderSc.dashTrails.ForEach(ds => ds.active = true);
//player.renderSc.dashTrails.ForEach(ds => ds.Restart());

View File

@@ -117,11 +117,20 @@ namespace Cielonos.MainGame.Characters
}
};
inputActions.Player.LockOnTarget.performed += ctx =>
inputActions.Player.LockonTarget.performed += ctx =>
{
if (ctx.performed && isCursorLocked.Value)
{
operation.LockOnTarget();
operation.LockonTarget();
}
};
inputActions.Player.SelectLockonTarget.performed += ctx =>
{
if (ctx.performed && isCursorLocked.Value)
{
Debug.Log("Value: " + ctx.ReadValue<float>());
operation.SelectLockonTarget(ctx.ReadValue<float>());
}
};

View File

@@ -159,7 +159,12 @@ namespace Cielonos.MainGame.Characters.Inventory
comboSm?[comboTreeName].SuspendThenSetup(actionCoolDownTime);
if (target != null)
{
if (autoRotate) player.landMovementSc.TurnToTarget(target);
if (autoRotate)
{
float angleLimit = player.viewSc.lockTargetModule.isLocking ? 240 : 150;
player.landMovementSc.SmartTurnToTarget(target, angleLimit);
}
if (keepAdsorption)
{
funcAnimSm.currentRuntimeFuncAnim.AddUpdateEvent(new SetRootAdsorptionAdjustment.Keep(target, adsorptionMinDistance));
@@ -185,13 +190,15 @@ namespace Cielonos.MainGame.Characters.Inventory
Debug.LogWarning($"没有找到名为 'Camera' 的轨道,请检查 FeedbackData '{feedBackName}' 的设置。");
return;
}
if (cameraTrack.clips.Find(clip => clip.action is CameraPositionShakeAction)?.action is CameraPositionShakeAction positionShakeAction)
var positionShakeAction = feedBackData.Action<CameraPositionShakeAction>("Camera");
if (positionShakeAction != null)
{
positionShakeAction.amplitude = swingPosition;
}
if (cameraTrack.clips.Find(clip => clip.action is CameraRotationShakeAction)?.action is CameraRotationShakeAction rotationShakeAction)
var rotationShakeAction = feedBackData.Action<CameraRotationShakeAction>("Camera");
if (rotationShakeAction != null)
{
rotationShakeAction.amplitude = swingRotation;
}

View File

@@ -54,7 +54,7 @@ namespace Cielonos.MainGame.Characters
eventSm.onHealthChanged.InsertByPriority("UI_HealthBarUpdate", new PrioritizedAction<float>(UI_HealthBarUpdate));
eventSm.onEnergyChanged.InsertByPriority("UI_EnergyBarUpdate", new PrioritizedAction<float>(UI_EnergyBarUpdate));
eventSm.onDodgeStart.InsertByPriority("Feedback_DodgeStart", new PrioritizedAction(() => { feedbackSc.PlayFeedback("PerfectDodge"); }));
//eventSm.onDodgeStart.InsertByPriority("Feedback_DodgeStart", new PrioritizedAction(() => { feedbackSc.PlayFeedback("PerfectDodge"); }));
eventSm.onNormalDodgeSuccess.InsertByPriority("Feedback_NormalDodge", new PrioritizedAction<AttackAreaBase, DodgeSource>(Feedback_NormalDodge));
eventSm.onPerfectDodgeSuccess.InsertByPriority("Feedback_PerfectDodge", new PrioritizedAction<AttackAreaBase, DodgeSource>(Feedback_PerfectDodge));
}
@@ -113,14 +113,14 @@ namespace Cielonos.MainGame.Characters
BreakthroughType breakthroughType = attackArea.attackSm.attackValue.breakthroughType;
if(breakthroughType == BreakthroughType.None) return;
string feedbackName = "GetHit" + breakthroughType.ToString();
feedbackSc[feedbackName]?.Play();
feedbackSc.PlayFeedback(feedbackName);
}
private void Feedback_GetAttacked(AttackAreaBase attackArea, AttackResult attackResult)
{
float ratio = attackResult.finalDamage / (attributeSm["MaximumHealth"] * 0.2f);
float intensity = Mathf.Lerp(0.25f, 1f, ratio);
feedbackSc["GetAttacked"]?.Play();
//feedbackSc.GetFeedbackData("GetAttacked")
}
private void Feedback_PerfectDodge(AttackAreaBase attackArea, DodgeSource dodgeSource)

View File

@@ -1,8 +1,10 @@
using System;
using Cielonos.MainGame.Effects.Feedback;
using DG.Tweening;
using SLSUtilities.General;
using SLSUtilities.FunctionalAnimation;
using UniRx;
using Unity.Cinemachine;
using UnityEngine;
namespace Cielonos.MainGame.Characters
@@ -249,6 +251,8 @@ namespace Cielonos.MainGame.Characters
float horizontalSpeed = horizontalMovement.magnitude / DeltaTime;
float remapFactor = Mathf.InverseLerp(10f, 15f, horizontalSpeed);
PostProcessingManager.Instance.speedLinesSm.SetRemap(1 - remapFactor);
//player.viewSc.cameraFovSm.UpdateFovBySpeed(horizontalSpeed, DeltaTime);
}
else
{

View File

@@ -23,7 +23,8 @@ namespace Cielonos.MainGame.Characters
public event Action<Vector3, float> OnDash;
public event Action<float> OnDodge;
public event Action OnLockOnTarget;
public event Action OnLockonTarget;
public event Action<float> OnSelectLockonTarget;
public event Action OnWalkPress;
public event Action OnWalkRelease;
@@ -70,7 +71,9 @@ namespace Cielonos.MainGame.Characters
public void Dodge(float length = -1) => OnDodge?.Invoke(length);
public void LockOnTarget() => OnLockOnTarget?.Invoke();
public void LockonTarget() => OnLockonTarget?.Invoke();
public void SelectLockonTarget(float direction) => OnSelectLockonTarget?.Invoke(direction);
public void WalkPress() => OnWalkPress?.Invoke();

View File

@@ -0,0 +1,134 @@
using Cielonos.MainGame.Effects.Feedback;
using DG.Tweening;
using Unity.Cinemachine;
using UnityEngine;
namespace Cielonos.MainGame.Characters
{
public class CameraFovSubmodule : SubmoduleBase<PlayerViewSubcontroller>
{
private Player player => owner.player;
private PlayerViewSubcontroller viewSc => owner;
[Header("基础FOV配置")] [Tooltip("静止时的基础FOV")]
public float baseFov = 45f;
[Tooltip("FOV最小值")] public float minFov = 40f;
[Tooltip("FOV最大值疾奔时")] public float maxFov = 55f;
[Header("速度阈值")] [Tooltip("开始FOV变化的最小速度")]
public float speedThreshold = 3f;
[Tooltip("达到最大FOV的速度")] public float maxSpeedThreshold = 15f;
[Header("过渡设置")] [Tooltip("FOV变化的速度")] public float fovChangeSpeed = 5f;
[Tooltip("是否平滑过渡FOV")] public bool useSmoothTransition = true;
private float currentFov;
private float targetFov;
private CinemachineCamera currentCamera => viewSc.currentCamera;
public CameraFovSubmodule(PlayerViewSubcontroller owner, float baseFov, float minFov,
float maxFov, float speedThreshold, float maxSpeedThreshold, float fovChangeSpeed, bool useSmoothTransition) : base(owner)
{
this.baseFov = baseFov;
this.minFov = minFov;
this.maxFov = maxFov;
this.speedThreshold = speedThreshold;
this.maxSpeedThreshold = maxSpeedThreshold;
this.fovChangeSpeed = fovChangeSpeed;
this.useSmoothTransition = useSmoothTransition;
this.currentFov = baseFov;
this.targetFov = baseFov;
}
/// <summary>
/// 根据水平速度更新FOV
/// </summary>
/// <param name="horizontalSpeed">水平速度(单位/秒)</param>
/// <param name="deltaTime">帧时间</param>
public void UpdateFovBySpeed(float horizontalSpeed, float deltaTime)
{
// 计算目标FOV
targetFov = CalculateTargetFov(horizontalSpeed);
// 平滑过渡
if (useSmoothTransition)
{
currentFov = Mathf.Lerp(currentFov, targetFov, deltaTime * fovChangeSpeed);
}
else
{
currentFov = targetFov;
}
// 应用FOV
ApplyFov(currentFov);
}
/// <summary>
/// 根据速度计算目标FOV
/// </summary>
private float CalculateTargetFov(float speed)
{
if (speed < speedThreshold)
{
return baseFov;
}
// 使用InverseLerp将速度映射到0-1范围
float t = Mathf.InverseLerp(speedThreshold, maxSpeedThreshold, speed);
// 使用SmoothStep使过渡更平滑
t = Mathf.SmoothStep(0f, 1f, t);
return Mathf.Lerp(baseFov, maxFov, t);
}
/// <summary>
/// 应用FOV到相机
/// </summary>
private void ApplyFov(float fov)
{
fov = Mathf.Clamp(fov, minFov, maxFov);
LensSettings lens = currentCamera.Lens;
lens.FieldOfView = fov;
currentCamera.Lens = lens;
}
/// <summary>
/// 立即设置FOV不使用平滑过渡
/// </summary>
public void SetFovImmediate(float fov)
{
currentFov = fov;
targetFov = fov;
ApplyFov(fov);
}
/// <summary>
/// 平滑过渡到指定FOV
/// </summary>
public void SetFovSmooth(float targetFovValue, float duration)
{
DOTween.To(() => currentFov, x =>
{
currentFov = x;
ApplyFov(x);
}, targetFovValue, duration)
.SetEase(Ease.OutQuad);
targetFov = targetFovValue;
}
/// <summary>
/// 重置为默认FOV
/// </summary>
public void ResetToBaseFov()
{
targetFov = baseFov;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1a007afcee9fd864cb29a8405fdc4d71

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using DG.Tweening;
using SickscoreGames.HUDNavigationSystem;
using UniRx;
@@ -31,8 +32,13 @@ namespace Cielonos.MainGame.Characters
/// 是否正在使用锁定目标摄像机
/// </summary>
public bool isUsingLockTargetCamera => isLocking && isAutoRotate;
public bool isDuringSwitch;
public bool isDuringCameraSwitch;
private const float CameraSwitchCooldown = 0.25f;
public CharacterBase lockTarget;
private float lastTargetSwitchTime;
private const float TargetSwitchCooldown = 0.25f;
public Transform targetPoint;
private Tweener iconTween;
@@ -40,20 +46,27 @@ namespace Cielonos.MainGame.Characters
{
isLocking = false;
isAutoRotate = false;
isDuringSwitch = false;
isDuringCameraSwitch = false;
lockTarget = null;
targetPoint = null;
}
public void Update()
{
if (isUsingLockTargetCamera && !isDuringSwitch)
if (isUsingLockTargetCamera && !isDuringCameraSwitch)
{
viewSc.cameraRoot.LookAt(targetPoint);
float distance = (targetPoint.position - viewSc.cameraRoot.transform.position).Flatten().magnitude;
if (isUsingLockTargetCamera && distance < 1f)
if (targetPoint != null)
{
UnlockTarget();
// 平滑跟随目标
Vector3 currentRotation = viewSc.cameraRoot.eulerAngles;
Vector3 targetDirection = targetPoint.position - viewSc.cameraRoot.position;
Quaternion targetRotation = Quaternion.LookRotation(targetDirection);
viewSc.cameraRoot.rotation = Quaternion.Slerp(
viewSc.cameraRoot.rotation,
targetRotation,
1f - Mathf.Exp(-10f * Time.deltaTime)
);
}
}
}
@@ -75,7 +88,7 @@ namespace Cielonos.MainGame.Characters
public void LockTarget(bool isAutoRotate)
{
if(isDuringSwitch) return;
if(isDuringCameraSwitch) return;
CharacterBase target = BattleManager.EnemySm.GetNearestEnemy(50f);
@@ -84,7 +97,7 @@ namespace Cielonos.MainGame.Characters
this.isLocking = true;
this.isAutoRotate = isAutoRotate;
this.lockTarget = target;
this.isDuringSwitch = true;
this.isDuringCameraSwitch = true;
if (isAutoRotate)
{
@@ -94,14 +107,14 @@ namespace Cielonos.MainGame.Characters
viewSc.stateDrivenCamera.GetComponent<Animator>().SetBool("isLockTarget", true);
viewSc.cameraRoot.DOLookAt(targetPoint.position, 0.5f)
.SetEase(Ease.InOutSine)
.OnComplete(() => { isDuringSwitch = false; })
.OnComplete(() => { isDuringCameraSwitch = false; })
.Play();
}
else
{
Observable.Timer(TimeSpan.FromSeconds(0.5f)).First().Subscribe(_ =>
{
isDuringSwitch = false;
isDuringCameraSwitch = false;
});
}
@@ -114,7 +127,7 @@ namespace Cielonos.MainGame.Characters
public void UnlockTarget()
{
if(isDuringSwitch) return;
if(isDuringCameraSwitch) return;
Vector3 currentEuler = viewSc.playerCamera.transform.rotation.eulerAngles;
@@ -134,12 +147,76 @@ namespace Cielonos.MainGame.Characters
orbitalFollow.HorizontalAxis.Value = newYaw;
orbitalFollow.VerticalAxis.Value = newPitch;
if (lockTarget != null)
{
lockTarget.navigationElement.showIndicator = false;
}
this.isLocking = false;
this.isAutoRotate = false;
this.lockTarget.navigationElement.showIndicator = false;
this.lockTarget = null;
this.targetPoint = null;
viewSc.stateDrivenCamera.GetComponent<Animator>().SetBool("isLockTarget", false);
}
/// <summary>
/// 切换锁定目标
/// </summary>
public void SwitchTarget(float direction)
{
if (!isLocking || isDuringCameraSwitch) return;
if (Time.time - lastTargetSwitchTime < TargetSwitchCooldown) return;
List<CharacterBase> sortedEnemies = BattleManager.EnemySm.GetVisibleEnemiesSortedByScreenX();
if (sortedEnemies.Count <= 1) return;
int currentIndex = sortedEnemies.IndexOf(lockTarget);
if (currentIndex < 0)
{
currentIndex = 0;
}
int dir = direction > 0 ? -1 : 1;
int newIndex = currentIndex + dir;
// 边界检查(无循环)
if (newIndex < 0 || newIndex >= sortedEnemies.Count)
{
return;
}
CharacterBase newTarget = sortedEnemies[newIndex];
// 目标相同检查
if (newTarget == lockTarget)
{
return;
}
lastTargetSwitchTime = Time.time;
SetNewTarget(sortedEnemies[newIndex]);
}
private void SetNewTarget(CharacterBase newTarget)
{
if (lockTarget != null)
{
lockTarget.navigationElement.showIndicator = false;
}
lockTarget = newTarget;
targetPoint = newTarget.bodyPartsSc.cameraLockingPoint ?? newTarget.bodyPartsSc.staticCenterPoint;
if (isUsingLockTargetCamera)
{
viewSc.lockingTargetCamera.LookAt = targetPoint;
}
lockTarget.navigationElement.showIndicator = true;
Image icon = lockTarget.navigationElement.Indicator.OnscreenIcon;
iconTween?.Kill(true);
iconTween = icon.GetComponent<RectTransform>().DOScale(1f, 0.3f).From(0.5f).SetEase(Ease.OutQuart).Play();
}
}
}

View File

@@ -21,6 +21,7 @@ namespace Cielonos.MainGame.Characters
public CinemachineCamera lockingTargetCamera;
public CharacterBase testEnemy;
public CameraFovSubmodule cameraFovSm;
public CameraRotationSubmodule cameraRotationSm;
public OcclusionFadeSubmodule occlusionFadeSm;
public LockTargetSubmodule lockTargetModule;
@@ -30,10 +31,14 @@ namespace Cielonos.MainGame.Characters
public override void Initialize()
{
base.Initialize();
cameraFovSm = new CameraFovSubmodule(this, 30f, 30f, 40f, 0.1f, 10f, 5f, true);
cameraRotationSm = new CameraRotationSubmodule(this, player.transform.eulerAngles.y);
occlusionFadeSm = new OcclusionFadeSubmodule(this);
lockTargetModule = new LockTargetSubmodule(this);
cameraFOV = new LerpFloat(30f, 2f);
player.operationSc.OnLockonTarget += lockTargetModule.SwitchLockState;
player.operationSc.OnSelectLockonTarget += lockTargetModule.SwitchTarget;
}
private void Start()
@@ -43,11 +48,6 @@ namespace Cielonos.MainGame.Characters
private void Update()
{
if (Keyboard.current.tabKey.wasPressedThisFrame)
{
lockTargetModule.SwitchLockState();
}
/*cameraFOV.targetValue = owner.landMovementSc.isSprinting ? 40f : 30f;
cameraFOV.Update(owner.selfTimeSm.DeltaTime);
freeLookCamera.Lens.FieldOfView = cameraFOV.currentValue;*/