Files
Cielonos/Assets/Scripts/MainGame/Items/Submodules/FeedbackSubcontroller.cs
SoulliesOfficial 39b43680a9 爆更
2026-07-18 03:16:20 -04:00

265 lines
8.9 KiB
C#

using System;
using System.Collections.Generic;
using Cielonos.MainGame.Effects.Feedback;
using SLSUtilities.Feedback;
using UnityEngine;
namespace Cielonos.MainGame.Inventory
{
[RequireComponent(typeof(ItemBase))]
public class FeedbackSubcontroller : SubcontrollerBase<ItemBase>
{
public FeedbackDataCollection feedbackDataCollection;
public FeedbackData this[string feedbackName] => GetFeedbackData(feedbackName);
private IFeedbackTimeProvider _timeProvider;
private readonly List<FeedbackPlayer> _activePlayers = new List<FeedbackPlayer>(8);
public override void Initialize()
{
base.Initialize();
_timeProvider = new CharacterFeedbackTimeProvider(owner.player);
}
public FeedbackData GetFeedbackData(string feedbackName)
{
if (feedbackDataCollection == null)
{
Debug.LogWarning($"[Item.FeedbackSubcontroller] feedbackDataCollection is null on {owner?.name}.");
return null;
}
if (!feedbackDataCollection.TryGet(feedbackName, out FeedbackData data))
{
Debug.LogWarning($"[Item.FeedbackSubcontroller] FeedbackData '{feedbackName}' not found on {owner?.name}.");
return null;
}
return data;
}
public bool TryGetFeedbackData(string feedbackName, out FeedbackData data)
{
data = null;
if (feedbackDataCollection == null || string.IsNullOrEmpty(feedbackName)) return false;
return feedbackDataCollection.TryGet(feedbackName, out data);
}
public bool HasFeedback(string feedbackName)
{
return TryGetFeedbackData(feedbackName, out _);
}
/// <summary>
/// 通过新系统播放一个 FeedbackData。
/// </summary>
public FeedbackPlayer PlayFeedback(FeedbackData data, bool stopPrevious = false)
{
return PlayFeedback(data, null, stopPrevious);
}
public FeedbackPlayer PlayFeedback(FeedbackData data, Action<RuntimeFeedback> configureRuntime, bool stopPrevious = false)
{
if (data == null) return null;
if (data.playbackStrategy == FeedbackPlaybackStrategy.Detached)
{
return PlayDetachedFeedback(data, configureRuntime, stopPrevious);
}
if (!data.CanPlay()) return null;
data.RecordPlay();
if (stopPrevious)
{
StopFeedback(data);
}
_timeProvider ??= owner?.player != null ? new CharacterFeedbackTimeProvider(owner.player) : DefaultFeedbackTimeProvider.Instance;
RuntimeFeedback runtimeFeedback = data.CreateRuntimeFeedback();
configureRuntime?.Invoke(runtimeFeedback);
Transform ownerTransform = owner?.player?.transform;
var player = new FeedbackPlayer(runtimeFeedback, _timeProvider, ownerTransform);
player.Play();
_activePlayers.Add(player);
return player;
}
public FeedbackPlayer PlayFeedback(RuntimeFeedback runtimeFeedback, bool stopPrevious = false)
{
if (runtimeFeedback == null) return null;
FeedbackData template = runtimeFeedback.templateData;
if (runtimeFeedback.playbackStrategy == FeedbackPlaybackStrategy.Detached)
{
return PlayDetachedFeedback(runtimeFeedback, stopPrevious);
}
if (template != null)
{
if (!FeedbackPlaybackGate.CanPlay(template)) return null;
FeedbackPlaybackGate.RecordPlay(template);
}
if (stopPrevious && template != null)
{
StopFeedback(template);
}
_timeProvider ??= owner?.player != null ? new CharacterFeedbackTimeProvider(owner.player) : DefaultFeedbackTimeProvider.Instance;
Transform ownerTransform = owner?.player?.transform;
var player = new FeedbackPlayer(runtimeFeedback, _timeProvider, ownerTransform);
player.Play();
_activePlayers.Add(player);
return player;
}
private FeedbackPlayer PlayDetachedFeedback(FeedbackData data, Action<RuntimeFeedback> configureRuntime, bool stopPrevious)
{
RuntimeFeedback runtimeFeedback = data.CreateRuntimeFeedback();
configureRuntime?.Invoke(runtimeFeedback);
return PlayDetachedFeedback(runtimeFeedback, stopPrevious);
}
private FeedbackPlayer PlayDetachedFeedback(RuntimeFeedback runtimeFeedback, bool stopPrevious)
{
FeedbackManager manager = FeedbackManager.Instance;
if (manager == null)
{
Debug.LogWarning($"[Item.FeedbackSubcontroller] Cannot play detached FeedbackData '{runtimeFeedback?.feedbackName}': FeedbackManager not found.");
return null;
}
if (stopPrevious && runtimeFeedback?.templateData != null)
{
manager.Stop(runtimeFeedback.templateData);
}
return manager.Play(runtimeFeedback);
}
/// <summary>
/// 通过名称从 FeedbackDataCollection 中查找并播放。
/// </summary>
public FeedbackPlayer PlayFeedback(string name, bool stopPrevious = false)
{
return PlayFeedback(name, null, stopPrevious);
}
public FeedbackPlayer PlayFeedback(string name, Action<RuntimeFeedback> configureRuntime, bool stopPrevious = false)
{
if (feedbackDataCollection == null)
{
Debug.LogWarning($"[Item.FeedbackSubcontroller] feedbackDataCollection is null on {owner?.name}.");
return null;
}
if (!feedbackDataCollection.TryGet(name, out FeedbackData data))
{
Debug.LogWarning($"[Item.FeedbackSubcontroller] FeedbackData '{name}' not found on {owner?.name}.");
return null;
}
return PlayFeedback(data, configureRuntime, stopPrevious);
}
public FeedbackPlayer TryPlayFeedback(string name, bool stopPrevious = false)
{
return TryGetFeedbackData(name, out FeedbackData data) ? PlayFeedback(data, stopPrevious) : null;
}
public FeedbackPlayer TryPlayFirstFeedback(params string[] feedbackNames)
{
return TryPlayFirstFeedback(false, feedbackNames);
}
public FeedbackPlayer TryPlayFirstFeedback(bool stopPrevious, params string[] feedbackNames)
{
if (feedbackNames == null) return null;
for (int i = 0; i < feedbackNames.Length; i++)
{
if (TryGetFeedbackData(feedbackNames[i], out FeedbackData data))
{
return PlayFeedback(data, stopPrevious);
}
}
return null;
}
/// <summary>
/// 停止指定 FeedbackData 的所有活跃播放器。
/// </summary>
public void StopFeedback(FeedbackData data)
{
if (data != null && data.playbackStrategy == FeedbackPlaybackStrategy.Detached)
{
FeedbackManager.Instance?.Stop(data);
return;
}
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
if (_activePlayers[i].Data == data)
{
_activePlayers[i].Stop();
_activePlayers.RemoveAt(i);
}
}
}
/// <summary>
/// 按名称停止正在播放的 Feedback。
/// </summary>
public void StopFeedback(string feedbackName)
{
if (feedbackDataCollection == null) return;
if (feedbackDataCollection.TryGet(feedbackName, out FeedbackData data))
{
StopFeedback(data);
}
}
/// <summary>
/// 停止所有活跃的新系统播放器。
/// </summary>
public void StopAllFeedbacks()
{
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
_activePlayers[i].Stop();
}
_activePlayers.Clear();
}
private void Update()
{
float dt = Time.deltaTime;
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
FeedbackPlayer player = _activePlayers[i];
player.Tick(dt);
if (player.IsCompleted || !player.IsActive)
{
_activePlayers.RemoveAt(i);
}
}
}
private void OnDisable()
{
StopAllFeedbacks();
}
private void OnDestroy()
{
StopAllFeedbacks();
}
}
}