Files
Cielonos/Assets/Scripts/MainGame/Characters/Base/Subcontrollers/FeedbackSubcontroller.cs

271 lines
9.1 KiB
C#
Raw Normal View History

2026-07-18 03:16:20 -04:00
using System;
2025-11-25 08:19:33 -05:00
using System.Collections.Generic;
2026-04-12 02:11:15 -04:00
using Cielonos.MainGame.Effects.Feedback;
2026-07-18 03:16:20 -04:00
using SLSUtilities.General;
2026-04-12 02:11:15 -04:00
using SLSUtilities.Feedback;
2025-11-25 08:19:33 -05:00
using UnityEngine;
namespace Cielonos.MainGame.Characters
{
2026-07-18 03:16:20 -04:00
[RequireComponent(typeof(CharacterBase))]
2026-02-13 09:22:11 -05:00
public partial class FeedbackSubcontroller : SubcontrollerBase<CharacterBase>
2025-11-25 08:19:33 -05:00
{
2026-07-18 03:16:20 -04:00
private const string DeathCleanupKey = nameof(FeedbackSubcontroller);
2026-04-12 02:11:15 -04:00
public FeedbackDataCollection feedbackDataCollection;
2026-04-29 06:16:07 -04:00
public FeedbackData this[string feedbackName] => GetFeedbackData(feedbackName);
2026-04-12 02:11:15 -04:00
2026-07-18 03:16:20 -04:00
private IFeedbackTimeProvider _timeProvider;
2026-04-12 02:11:15 -04:00
private readonly List<FeedbackPlayer> _activePlayers = new List<FeedbackPlayer>(8);
public override void Initialize()
{
base.Initialize();
if (owner != null)
{
_timeProvider = new CharacterFeedbackTimeProvider(owner);
2026-07-18 03:16:20 -04:00
owner.eventSm?.onDeath.TryAdd(DeathCleanupKey, new PrioritizedAction(StopAllFeedbacks));
2026-04-12 02:11:15 -04:00
}
}
2026-04-18 13:57:19 -04:00
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;
}
2026-04-12 02:11:15 -04:00
2026-07-18 03:16:20 -04:00
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 _);
}
2026-04-12 02:11:15 -04:00
/// <summary>
/// 通过新系统播放一个 FeedbackData。
/// </summary>
public FeedbackPlayer PlayFeedback(FeedbackData data, bool stopPrevious = false)
2026-07-18 03:16:20 -04:00
{
return PlayFeedback(data, null, stopPrevious);
}
public FeedbackPlayer PlayFeedback(FeedbackData data, Action<RuntimeFeedback> configureRuntime, bool stopPrevious = false)
2026-04-12 02:11:15 -04:00
{
if (data == null) return null;
2026-07-18 03:16:20 -04:00
if (data.playbackStrategy == FeedbackPlaybackStrategy.Detached)
{
return PlayDetachedFeedback(data, configureRuntime, stopPrevious);
}
2026-06-13 18:43:40 -04:00
if (!data.CanPlay()) return null;
data.RecordPlay();
2026-04-12 02:11:15 -04:00
if (stopPrevious)
{
StopFeedback(data);
}
2026-07-18 03:16:20 -04:00
_timeProvider ??= owner != null ? new CharacterFeedbackTimeProvider(owner) : DefaultFeedbackTimeProvider.Instance;
RuntimeFeedback runtimeFeedback = data.CreateRuntimeFeedback();
configureRuntime?.Invoke(runtimeFeedback);
var player = new FeedbackPlayer(runtimeFeedback, _timeProvider, owner?.transform);
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 != null ? new CharacterFeedbackTimeProvider(owner) : DefaultFeedbackTimeProvider.Instance;
var player = new FeedbackPlayer(runtimeFeedback, _timeProvider, owner?.transform);
2026-04-12 02:11:15 -04:00
player.Play();
_activePlayers.Add(player);
return player;
}
2026-07-18 03:16:20 -04:00
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($"[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);
}
2026-04-12 02:11:15 -04:00
/// <summary>
/// 通过名称从 FeedbackDataCollection 中查找并播放。
/// </summary>
public FeedbackPlayer PlayFeedback(string name, bool stopPrevious = false)
2026-07-18 03:16:20 -04:00
{
return PlayFeedback(name, null, stopPrevious);
}
public FeedbackPlayer PlayFeedback(string name, Action<RuntimeFeedback> configureRuntime, bool stopPrevious = false)
2026-04-12 02:11:15 -04:00
{
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;
}
2026-07-18 03:16:20 -04:00
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;
2026-04-12 02:11:15 -04:00
}
/// <summary>
/// 停止指定 FeedbackData 的所有活跃播放器。
/// </summary>
public void StopFeedback(FeedbackData data)
{
2026-07-18 03:16:20 -04:00
if (data != null && data.playbackStrategy == FeedbackPlaybackStrategy.Detached)
{
FeedbackManager.Instance?.Stop(data);
return;
}
2026-04-12 02:11:15 -04:00
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
if (_activePlayers[i].Data == data)
{
_activePlayers[i].Stop();
_activePlayers.RemoveAt(i);
}
}
}
2026-04-29 06:16:07 -04:00
/// <summary>
/// 按名称停止正在播放的 Feedback。
/// </summary>
public void StopFeedback(string feedbackName)
{
if (feedbackDataCollection == null) return;
if (feedbackDataCollection.TryGet(feedbackName, out FeedbackData data))
{
StopFeedback(data);
}
}
2026-04-12 02:11:15 -04:00
/// <summary>
/// 停止所有活跃的新系统播放器。
/// </summary>
public void StopAllFeedbacks()
{
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
_activePlayers[i].Stop();
}
_activePlayers.Clear();
}
2025-11-25 08:19:33 -05:00
private void Update()
{
2026-04-18 13:57:19 -04:00
float dt = Time.deltaTime;
2026-04-12 02:11:15 -04:00
for (int i = _activePlayers.Count - 1; i >= 0; i--)
{
FeedbackPlayer player = _activePlayers[i];
player.Tick(dt);
if (player.IsCompleted || !player.IsActive)
{
_activePlayers.RemoveAt(i);
}
2025-11-25 08:19:33 -05:00
}
}
2026-07-18 03:16:20 -04:00
private void OnDisable()
{
StopAllFeedbacks();
}
private void OnDestroy()
{
StopAllFeedbacks();
owner?.eventSm?.onDeath.Remove(DeathCleanupKey);
}
2025-11-25 08:19:33 -05:00
}
2026-07-18 03:16:20 -04:00
}