2025-11-25 08:19:33 -05:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Linq;
|
2025-12-08 05:27:53 -05:00
|
|
|
|
using Cielonos.UI;
|
|
|
|
|
|
using FIMSpace.FProceduralAnimation;
|
2025-12-22 18:36:29 -05:00
|
|
|
|
using MoreMountains.FeedbacksForThirdParty;
|
2025-11-25 08:19:33 -05:00
|
|
|
|
using RootMotion.FinalIK;
|
|
|
|
|
|
using SLSFramework.General;
|
|
|
|
|
|
using SLSUtilities.FunctionalAnimation;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.InputSystem;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Cielonos.MainGame.Characters
|
|
|
|
|
|
{
|
|
|
|
|
|
public partial class PlayerAnimationSubcontroller : AnimationSubcontrollerBase, IPlayerSubcontroller
|
|
|
|
|
|
{
|
|
|
|
|
|
public Player player => owner as Player;
|
|
|
|
|
|
public AnimatorOverrideController animatorOverride;
|
2025-12-08 05:27:53 -05:00
|
|
|
|
|
|
|
|
|
|
public LegsAnimator legsAnimator;
|
2025-11-25 08:19:33 -05:00
|
|
|
|
|
|
|
|
|
|
public override void Initialize()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Initialize();
|
2025-12-22 23:27:18 -05:00
|
|
|
|
player.operationSc.OnDash += delegate(Vector3 inputDirection)
|
2025-12-22 18:36:29 -05:00
|
|
|
|
{
|
|
|
|
|
|
Vector3 cameraForward = player.viewSc.playerCamera.transform.forward.Flatten();
|
2025-12-22 23:27:18 -05:00
|
|
|
|
player.landMovementSc.TurnToDirection(inputDirection);
|
2026-01-03 18:19:39 -05:00
|
|
|
|
Vector3 playerForward = player.transform.forward.Flatten();
|
|
|
|
|
|
Vector3 dashCameraRotation = CalculateDashAngles(playerForward, cameraForward);
|
2025-12-22 18:36:29 -05:00
|
|
|
|
player.feedbackSc["Dash"].feedback.GetFeedbackOfType<MMF_CinemachineRotation>().RotationAmplitude = dashCameraRotation;
|
|
|
|
|
|
player.feedbackSc["Dash"].feedback.GetFeedbackOfType<MMF_RadialBlur>().TargetCenter = player.GetNormalizedScreenPosition();
|
|
|
|
|
|
fullBodyFuncAnimSm.Play("Dash");
|
|
|
|
|
|
};
|
|
|
|
|
|
player.operationSc.OnDodge += delegate
|
|
|
|
|
|
{
|
2026-01-03 18:19:39 -05:00
|
|
|
|
Vector3 playerBackward = -player.transform.forward.Flatten();
|
2025-12-22 18:36:29 -05:00
|
|
|
|
Vector3 cameraForward = player.viewSc.playerCamera.transform.forward.Flatten();
|
2026-01-03 18:19:39 -05:00
|
|
|
|
Vector3 dodgeCameraRotation = CalculateDashAngles(playerBackward, cameraForward);
|
2025-12-22 18:36:29 -05:00
|
|
|
|
player.feedbackSc["Dodge"].feedback.GetFeedbackOfType<MMF_CinemachineRotation>().RotationAmplitude = dodgeCameraRotation;
|
|
|
|
|
|
player.feedbackSc["Dodge"].feedback.GetFeedbackOfType<MMF_RadialBlur>().TargetCenter = player.GetNormalizedScreenPosition();
|
|
|
|
|
|
fullBodyFuncAnimSm.Play("Dodge");
|
|
|
|
|
|
};
|
2025-11-25 08:19:33 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Update()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.Update();
|
|
|
|
|
|
|
|
|
|
|
|
player.inputSc.preinputSubmodule.Update(isDuringPreinput, isAtActionDisruption);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void LateUpdate()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.LateUpdate();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override void RegisterDefaultFunctions()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.RegisterDefaultFunctions();
|
|
|
|
|
|
|
|
|
|
|
|
registeredFunctions.Add("DashStart", anim =>
|
|
|
|
|
|
{
|
|
|
|
|
|
player.landMovementSc.isDashing = true;
|
|
|
|
|
|
player.landMovementSc.dashMoveMultiplier = anim.funcAnimData.variableCollection.GetVariable<float>("DashMoveMultiplier");
|
2025-12-22 18:36:29 -05:00
|
|
|
|
player.selfTimeSm.ModifyTimeScale(0.1f, 1.25f);
|
2025-11-25 08:19:33 -05:00
|
|
|
|
player.audioSc.PlayDashSound();
|
2025-12-08 05:27:53 -05:00
|
|
|
|
player.feedbackSc["Dash"]?.Play();
|
|
|
|
|
|
//player.renderSc.dashTrails.ForEach(ds => ds.active = true);
|
|
|
|
|
|
//player.renderSc.dashTrails.ForEach(ds => ds.Restart());
|
2025-11-25 08:19:33 -05:00
|
|
|
|
|
|
|
|
|
|
DodgeSource defaultDodge = new DodgeSource(owner, null, "DefaultDodge", 0, "NormalDodge", "PerfectDodge", Mathf.Infinity, 0.2f);
|
|
|
|
|
|
defaultDodge.onPerfectDodge = () =>
|
|
|
|
|
|
{
|
2025-12-22 18:36:29 -05:00
|
|
|
|
player.feedbackSc["PerfectDodge"].feedback.GetFeedbackOfType<MMF_RadialBlur>().TargetCenter = player.GetNormalizedScreenPosition();
|
|
|
|
|
|
player.feedbackSc["PerfectDodge"].feedback.GetFeedbackOfType<MMF_AdvancedVignette>().Center = player.GetNormalizedScreenPosition();
|
2025-11-25 08:19:33 -05:00
|
|
|
|
};
|
|
|
|
|
|
player.reactionSc.dodgeSm.ApplyDodge(defaultDodge);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
registeredFunctions.Add("DashEnd", anim =>
|
|
|
|
|
|
{
|
|
|
|
|
|
player.landMovementSc.isDashing = false;
|
|
|
|
|
|
player.landMovementSc.dashMoveMultiplier = 1;
|
|
|
|
|
|
player.landMovementSc.isSprinting = true;
|
2025-12-08 05:27:53 -05:00
|
|
|
|
//player.renderSc.dashTrails.ForEach(ds => ds.active = false);
|
2025-11-25 08:19:33 -05:00
|
|
|
|
|
|
|
|
|
|
player.reactionSc.dodgeSm.RemoveDodge("DefaultDodge");
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
registeredFunctions.Add("DodgeStart", anim =>
|
|
|
|
|
|
{
|
|
|
|
|
|
player.landMovementSc.isDashing = true;
|
|
|
|
|
|
player.landMovementSc.dashMoveMultiplier = anim.funcAnimData.variableCollection.GetVariable<float>("DashMoveMultiplier");
|
|
|
|
|
|
player.audioSc.PlayDashSound();
|
2025-12-08 05:27:53 -05:00
|
|
|
|
player.feedbackSc["Dodge"]?.Play();
|
|
|
|
|
|
//player.renderSc.dashTrails.ForEach(ds => ds.active = true);
|
|
|
|
|
|
//player.renderSc.dashTrails.ForEach(ds => ds.Restart());
|
2025-11-25 08:19:33 -05:00
|
|
|
|
|
|
|
|
|
|
DodgeSource defaultDodge = new DodgeSource(owner, null, "DefaultDodge", 0, "NormalDodge", "PerfectDodge", Mathf.Infinity, 0.2f);
|
|
|
|
|
|
defaultDodge.onPerfectDodge = () =>
|
|
|
|
|
|
{
|
2025-12-22 18:36:29 -05:00
|
|
|
|
player.feedbackSc["PerfectDodge"].feedback.GetFeedbackOfType<MMF_RadialBlur>().TargetCenter = player.GetNormalizedScreenPosition();
|
|
|
|
|
|
player.feedbackSc["PerfectDodge"].feedback.GetFeedbackOfType<MMF_AdvancedVignette>().Center = player.GetNormalizedScreenPosition();
|
2025-11-25 08:19:33 -05:00
|
|
|
|
};
|
|
|
|
|
|
player.reactionSc.dodgeSm.ApplyDodge(defaultDodge);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
registeredFunctions.Add("DodgeEnd", anim =>
|
|
|
|
|
|
{
|
|
|
|
|
|
player.landMovementSc.isDashing = false;
|
|
|
|
|
|
player.landMovementSc.dashMoveMultiplier = 1;
|
2025-12-08 05:27:53 -05:00
|
|
|
|
//player.renderSc.dashTrails.ForEach(ds => ds.active = false);
|
2025-11-25 08:19:33 -05:00
|
|
|
|
|
|
|
|
|
|
player.reactionSc.dodgeSm.RemoveDodge("DefaultDodge");
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public partial class PlayerAnimationSubcontroller
|
|
|
|
|
|
{
|
|
|
|
|
|
public bool isDuringPreinput;
|
|
|
|
|
|
public bool isAtActionDisruption;
|
|
|
|
|
|
|
|
|
|
|
|
protected override void UpdateIntervalInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.UpdateIntervalInfo();
|
|
|
|
|
|
|
|
|
|
|
|
isDuringPreinput = currentIntervals.Any(interval => interval.intervalType == IntervalType.Preinput);
|
|
|
|
|
|
isAtActionDisruption = lastFrameIntervals.SwitchOut(currentIntervals, (interval) => interval.intervalType == IntervalType.Preinput);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-22 18:36:29 -05:00
|
|
|
|
|
|
|
|
|
|
public partial class PlayerAnimationSubcontroller
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
2026-01-03 18:19:39 -05:00
|
|
|
|
/// 计算冲刺时的摄像机倾斜角度
|
2025-12-22 18:36:29 -05:00
|
|
|
|
/// </summary>
|
2026-01-03 18:19:39 -05:00
|
|
|
|
/// <param name="dashDir">冲刺输入的平整化方向 (y=0, normalized)</param>
|
|
|
|
|
|
/// <param name="camFwd">摄像机的平整化前方 (y=0, normalized)</param>
|
|
|
|
|
|
/// <returns>Vector3(Pitch角度, 0, Roll角度)</returns>
|
|
|
|
|
|
public Vector3 CalculateDashAngles(Vector3 dashDir, Vector3 camFwd)
|
2025-12-22 18:36:29 -05:00
|
|
|
|
{
|
2026-01-03 18:19:39 -05:00
|
|
|
|
// 1. 确保输入向量是归一化的(以防万一)
|
|
|
|
|
|
Vector3 d = dashDir.normalized;
|
|
|
|
|
|
Vector3 f = camFwd.normalized;
|
2025-12-22 18:36:29 -05:00
|
|
|
|
|
2026-01-03 18:19:39 -05:00
|
|
|
|
// 2. 通过叉乘获取摄像机的水平右方向 (camRight)
|
|
|
|
|
|
// 在左手坐标系(Unity)中,Up x Forward = Right
|
|
|
|
|
|
Vector3 r = Vector3.Cross(Vector3.up, f);
|
2025-12-22 18:36:29 -05:00
|
|
|
|
|
2026-01-03 18:19:39 -05:00
|
|
|
|
// 3. 计算投影权重 (范围在 -1 到 1 之间)
|
|
|
|
|
|
// forwardWeight: 1表示完全同向,-1表示完全反向
|
|
|
|
|
|
float forwardWeight = Vector3.Dot(d, f);
|
|
|
|
|
|
// sideWeight: 1表示向右冲,-1表示向左冲
|
|
|
|
|
|
float sideWeight = Vector3.Dot(d, r);
|
2025-12-22 18:36:29 -05:00
|
|
|
|
|
2026-01-03 18:19:39 -05:00
|
|
|
|
// 4. 定义倾斜强度系数 (控制在 1.5度 左右)
|
|
|
|
|
|
const float tiltIntensity = 1.5f;
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 计算最终角度
|
|
|
|
|
|
// x 轴旋转 (Pitch):正值向下倾斜(向前冲),负值向上倾斜(向后退)
|
|
|
|
|
|
float pitch = forwardWeight * tiltIntensity;
|
|
|
|
|
|
|
|
|
|
|
|
// z 轴旋转 (Dutch/Roll):
|
|
|
|
|
|
// 注意:向右冲时(sideWeight=1),通常相机向左倾斜(z为负值)更有动感
|
|
|
|
|
|
float roll = -sideWeight * tiltIntensity;
|
|
|
|
|
|
|
|
|
|
|
|
return new Vector3(pitch, 0, roll);
|
2025-12-22 18:36:29 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-25 08:19:33 -05:00
|
|
|
|
}
|