152 lines
4.9 KiB
C#
152 lines
4.9 KiB
C#
using System;
|
||
using Cielonos.MainGame.Characters;
|
||
using Cielonos.MainGame.Characters.Inventory;
|
||
using Sirenix.OdinInspector;
|
||
using SLSUtilities.Feedback;
|
||
using SLSUtilities.FunctionalAnimation;
|
||
using UnityEngine;
|
||
|
||
namespace Cielonos.MainGame.Effects.Feedback
|
||
{
|
||
/// <summary>
|
||
/// FuncAnim Payload 集成层:在动画事件触发时播放指定的 FeedbackData。
|
||
/// 放入 FuncAnimData 的 animEvents 中,Invoke() 时自动通过角色/物品的
|
||
/// FeedbackSubcontroller 播放,获得正确的时间缩放和 owner Transform。
|
||
///
|
||
/// 支持两种来源模式:
|
||
/// 1. Direct:直接引用一个 FeedbackData 资产
|
||
/// 2. ByName:从执行者的 FeedbackSubcontroller 中按名称查找
|
||
/// </summary>
|
||
[Serializable]
|
||
[EventColor(0.4f, 0.8f, 1.0f)]
|
||
public class PlayFeedbackPayload : FuncAnimPayloadBase
|
||
{
|
||
public override string NameForInspector => "Play Feedback";
|
||
|
||
public enum SourceMode
|
||
{
|
||
/// <summary>
|
||
/// 直接引用 FeedbackData 资产。
|
||
/// </summary>
|
||
Direct,
|
||
|
||
/// <summary>
|
||
/// 从执行者的 FeedbackDataCollection 中按 feedbackName 查找。
|
||
/// </summary>
|
||
ByName
|
||
}
|
||
|
||
[Title("Feedback Source")]
|
||
public SourceMode sourceMode = SourceMode.Direct;
|
||
|
||
/// <summary>
|
||
/// Direct 模式下直接引用的 FeedbackData 资产。
|
||
/// </summary>
|
||
[ShowIf("sourceMode", SourceMode.Direct)]
|
||
[LabelText("Feedback Data")]
|
||
public FeedbackData feedbackData;
|
||
|
||
/// <summary>
|
||
/// ByName 模式下按名称查找的 feedbackName。
|
||
/// </summary>
|
||
[ShowIf("sourceMode", SourceMode.ByName)]
|
||
[LabelText("Feedback Name")]
|
||
public string feedbackName;
|
||
|
||
/// <summary>
|
||
/// 是否在播放前停止同名/同 Data 的正在播放的反馈。
|
||
/// </summary>
|
||
[Title("Options")]
|
||
[LabelText("Stop Previous")]
|
||
public bool stopPrevious;
|
||
|
||
public override void Invoke()
|
||
{
|
||
FeedbackData data = ResolveFeedbackData();
|
||
if (data == null)
|
||
{
|
||
Debug.LogWarning($"[PlayFeedbackPayload] Cannot resolve FeedbackData. " +
|
||
$"Mode: {sourceMode}, Name: {feedbackName}");
|
||
return;
|
||
}
|
||
|
||
// 尝试通过角色/物品的 FeedbackSubcontroller 播放(获得正确的 timeProvider 和 owner)
|
||
if (TryPlayViaSubcontroller(data)) return;
|
||
|
||
// 回退到全局 FeedbackManager
|
||
if (FeedbackManager.Instance != null)
|
||
{
|
||
FeedbackManager.Instance.Play(data);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("[PlayFeedbackPayload] No FeedbackSubcontroller or FeedbackManager available.");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据 sourceMode 解析实际的 FeedbackData。
|
||
/// </summary>
|
||
private FeedbackData ResolveFeedbackData()
|
||
{
|
||
if (sourceMode == SourceMode.Direct)
|
||
{
|
||
return feedbackData;
|
||
}
|
||
|
||
// ByName 模式:从执行者获取 FeedbackDataCollection 并查找
|
||
FeedbackDataCollection collection = GetCollectionFromExecutor();
|
||
if (collection != null && collection.TryGet(feedbackName, out FeedbackData result))
|
||
{
|
||
return result;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 尝试通过角色或物品的 FeedbackSubcontroller 播放。
|
||
/// </summary>
|
||
private bool TryPlayViaSubcontroller(FeedbackData data)
|
||
{
|
||
if (character == null) return false;
|
||
|
||
// 角色层级
|
||
if (character is CharacterBase characterBase && characterBase.feedbackSc != null)
|
||
{
|
||
characterBase.feedbackSc.PlayFeedback(data, stopPrevious);
|
||
return true;
|
||
}
|
||
|
||
// 物品层级
|
||
if (character is ItemBase itemBase && itemBase.feedbackSc != null)
|
||
{
|
||
itemBase.feedbackSc.PlayFeedback(data, stopPrevious);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从执行者获取 FeedbackDataCollection。
|
||
/// </summary>
|
||
private FeedbackDataCollection GetCollectionFromExecutor()
|
||
{
|
||
if (character == null) return null;
|
||
|
||
if (character is CharacterBase characterBase && characterBase.feedbackSc != null)
|
||
{
|
||
return characterBase.feedbackSc.feedbackDataCollection;
|
||
}
|
||
|
||
if (character is ItemBase itemBase && itemBase.feedbackSc != null)
|
||
{
|
||
return itemBase.feedbackSc.feedbackDataCollection;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
}
|