新Feedback系统

This commit is contained in:
SoulliesOfficial
2026-04-12 02:11:15 -04:00
parent f26f9fd374
commit 41140a2017
171 changed files with 296190 additions and 219527 deletions

View File

@@ -195,6 +195,11 @@ namespace Cielonos.MainGame.Characters
_ => 0
};
if (string.IsNullOrEmpty(funcAnimName))
{
funcAnimName = GetHitFuncAnimName(breakthroughType, direction);
}
if (CheckBreakthrough(breakthroughType))
{
if (!animationSc.fullBodyFuncAnimSm.Stop(disruptionType))
@@ -225,6 +230,7 @@ namespace Cielonos.MainGame.Characters
protected virtual string GetHitFuncAnimName(BreakthroughType breakthroughType, Vector3 direction)
{
string prefix = "GetHitMedium";
if (breakthroughType >= BreakthroughType.Medium)
{
prefix = breakthroughType switch
@@ -236,7 +242,7 @@ namespace Cielonos.MainGame.Characters
_ => "GetHit"
};
}
string directionStr = "Front";
if (direction != default)
{
@@ -256,6 +262,16 @@ namespace Cielonos.MainGame.Characters
}
string fullName = prefix + directionStr;
if (!animationSc.fullBodyFuncAnimSm.collection.ContainsKey(fullName))
{
if (prefix == "GetHitForced")
{
prefix = "GetHitHeavy"; //如果没有专门的“强制等级”受击动画,就使用“重度等级”的动画
fullName = prefix + directionStr;
}
}
return fullName;
}
}

View File

@@ -232,67 +232,12 @@ namespace Cielonos.MainGame.Characters
}
}
public virtual void PlayGetHitAnimation(string getHitAnimPrefix, out float animDuration,
Vector3 direction = default, string funcAnimName = "")
public virtual void PlayGetHitAnimation(string funcAnimName, out float animDuration,
Vector3 direction = default)
{
bool useCustomFuncAnim = !string.IsNullOrEmpty(funcAnimName);
int fullBodyActionIndex = animator.GetLayerIndex("FullBodyAction");
if (useCustomFuncAnim)
{
fullBodyFuncAnimSm.Play(funcAnimName);
animDuration = fullBodyFuncAnimSm.currentClip.length;
return;
}
string getHitAnim = getHitAnimPrefix + "Front";
string getHitFrontAnim = getHitAnimPrefix + "Front";
float normalizedTransitionDuration = 0.1f / animator.GetCurrentAnimatorStateInfo(fullBodyActionIndex).length;
animDuration = 0f;
if (animator.HasState(fullBodyActionIndex, Animator.StringToHash(getHitAnim)))
{
direction.y = 0;
direction = direction.normalized;
float angle = Vector3.SignedAngle(transform.forward, direction, Vector3.up);
string directionStr = angle switch
{
> -45f and <= 45f => "Back",
> 45f and <= 135f => "Left",
> -135f and <= -45f => "Right",
_ => "Front"
};
getHitAnim = getHitAnimPrefix + directionStr;
if (direction == default || !animator.HasState(fullBodyActionIndex, Animator.StringToHash(getHitAnim)))
{
animator.CrossFade(getHitFrontAnim, normalizedTransitionDuration, fullBodyActionIndex, 0);
animDuration = mapper.GetClip(getHitFrontAnim).length;
}
else
{
animator.CrossFade(getHitAnim, normalizedTransitionDuration, fullBodyActionIndex, 0);
animDuration = mapper.GetClip(getHitAnim).length;
}
}
else if (animator.HasState(fullBodyActionIndex, Animator.StringToHash(getHitAnimPrefix)))
{
getHitAnim = getHitAnimPrefix;
animator.CrossFade(getHitAnim, normalizedTransitionDuration, fullBodyActionIndex, 0);
animDuration = mapper.GetClip(getHitAnim).length;
}
else
{
if (animator.HasState(fullBodyActionIndex, Animator.StringToHash("GetHit")))
{
animator.CrossFade("GetHit", normalizedTransitionDuration, fullBodyActionIndex, 0);
animDuration = mapper.GetClip("GetHit").length;
}
else
{
animator.CrossFade("Empty", 0.1f, fullBodyActionIndex, 0);
}
}
fullBodyFuncAnimSm.Play(funcAnimName);
animDuration = fullBodyFuncAnimSm.currentData.Interval(IntervalType.ActionDisruption).StartTime;
//animDuration = fullBodyFuncAnimSm.currentData.Interval(IntervalType.Active).EndTime;
}
}
}

View File

@@ -1,7 +1,9 @@
using System.Collections.Generic;
using Cielonos.MainGame.Effects.Feedback;
using Lean.Pool;
using MoreMountains.Feedbacks;
using MoreMountains.FeedbacksForThirdParty;
using SLSUtilities.Feedback;
using SLSUtilities.FeelAssistance;
using UnityEngine;
@@ -9,18 +11,114 @@ namespace Cielonos.MainGame.Characters
{
public partial class FeedbackSubcontroller : SubcontrollerBase<CharacterBase>
{
// === 旧系统Feel—— 保留向后兼容 ===
public Dictionary<string, FeedbackUnit> feedbacks;
public FeedbackUnit this[string feedbackName] => feedbacks?.GetValueOrDefault(feedbackName, null);
// === 新系统Feedback System===
public FeedbackDataCollection feedbackDataCollection;
private CharacterFeedbackTimeProvider _timeProvider;
private readonly List<FeedbackPlayer> _activePlayers = new List<FeedbackPlayer>(8);
public override void Initialize()
{
base.Initialize();
if (owner != null)
{
_timeProvider = new CharacterFeedbackTimeProvider(owner);
}
}
/// <summary>
/// 通过新系统播放一个 FeedbackData。
/// </summary>
public FeedbackPlayer PlayFeedback(FeedbackData data, bool stopPrevious = false)
{
if (data == null) return null;
if (stopPrevious)
{
StopFeedback(data);
}
var player = new FeedbackPlayer(data, _timeProvider, owner?.transform);
player.Play();
_activePlayers.Add(player);
return player;
}
/// <summary>
/// 通过名称从 FeedbackDataCollection 中查找并播放。
/// </summary>
public FeedbackPlayer PlayFeedback(string name, bool stopPrevious = false)
{
if (feedbackDataCollection == null)
{
Debug.LogWarning($"[FeedbackSubcontroller] feedbackDataCollection is null on {owner?.name}.");
return null;
}
if (!feedbackDataCollection.TryGet(name, out FeedbackData data))
{
Debug.LogWarning($"[FeedbackSubcontroller] FeedbackData '{name}' not found on {owner?.name}.");
return null;
}
return PlayFeedback(data, stopPrevious);
}
/// <summary>
/// 停止指定 FeedbackData 的所有活跃播放器。
/// </summary>
public void StopFeedback(FeedbackData data)
{
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
if (_activePlayers[i].Data == data)
{
_activePlayers[i].Stop();
_activePlayers.RemoveAt(i);
}
}
}
/// <summary>
/// 停止所有活跃的新系统播放器。
/// </summary>
public void StopAllFeedbacks()
{
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
_activePlayers[i].Stop();
}
_activePlayers.Clear();
}
private void Update()
{
if (feedbacks == null) return;
foreach (var feedbackUnit in feedbacks.Values)
// 旧系统驱动
if (feedbacks != null)
{
float timeScaleMultiplier = owner.selfTimeSm.TimeScale;
feedbackUnit.feedback.ExternalTimeScale = timeScaleMultiplier;
feedbackUnit.Update();
foreach (var feedbackUnit in feedbacks.Values)
{
float timeScaleMultiplier = owner.selfTimeSm.TimeScale;
feedbackUnit.feedback.ExternalTimeScale = timeScaleMultiplier;
feedbackUnit.Update();
}
}
// 新系统驱动
float dt = Time.unscaledDeltaTime;
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
FeedbackPlayer player = _activePlayers[i];
player.Tick(dt);
if (player.IsCompleted || !player.IsActive)
{
_activePlayers.RemoveAt(i);
}
}
}
}