210 lines
8.1 KiB
C#
210 lines
8.1 KiB
C#
#if UNITY_EDITOR
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
using Event1v1Battle.Data;
|
|
using UnityEngine;
|
|
|
|
namespace Event1v1Battle.Data
|
|
{
|
|
/// <summary>
|
|
/// TV 调试专用:不访问 <see cref="Activity.IEventDataRepository"/>,避免 <c>Repository.Load</c> 在容器未就绪时 NRE。
|
|
/// </summary>
|
|
internal sealed class Event1v1BattleSlapManagerDebugPreview : Event1v1BattleSlapManager
|
|
{
|
|
readonly Event1v1BattleSlapData _stubData;
|
|
|
|
public Event1v1BattleSlapManagerDebugPreview()
|
|
{
|
|
_stubData = new Event1v1BattleSlapData
|
|
{
|
|
MaxHp = 100,
|
|
NpcHp = 100,
|
|
PlayerHp = 100,
|
|
PlayerLifeCount = 3,
|
|
CurrentStageID = 1,
|
|
CurrentRoundForm1 = 1,
|
|
NpcName = string.Empty,
|
|
NpcIcon = string.Empty,
|
|
IsOnGoing = true,
|
|
};
|
|
}
|
|
|
|
public override Event1v1BattleSlapData LoadData() => _stubData;
|
|
}
|
|
}
|
|
|
|
namespace game
|
|
{
|
|
public partial class Event1v1BattleSlapTvPopupPanel
|
|
{
|
|
[Header("Editor Preview")]
|
|
[SerializeField] private bool debugSkipAutoPlayOnStart = false;
|
|
[SerializeField][Min(0)] private int debugPlayerAttackQuality = 0;
|
|
[SerializeField] private bool debugPlayerAttackKillNpc = false;
|
|
[SerializeField][Min(0)] private int debugNpcAttackQuality = 0;
|
|
[SerializeField] private bool debugNpcAttackKillPlayer = false;
|
|
|
|
partial void OnStartDebugHook(ref bool shouldAutoPlay)
|
|
{
|
|
if (!debugSkipAutoPlayOnStart)
|
|
return;
|
|
shouldAutoPlay = false;
|
|
EnsureDebugPreviewRuntimeReferences();
|
|
PlayDirectorClipLoopingNoWait(_playerDirector, idle_player, 0);
|
|
PlayDirectorClipLoopingNoWait(_enemyDirector, idle_enemy, 0);
|
|
}
|
|
|
|
[ContextMenu("Debug/Preview Player Attack")]
|
|
private async void DebugPreviewPlayerAttack()
|
|
{
|
|
if (!Application.isPlaying)
|
|
{
|
|
Debug.LogWarning($"[{nameof(Event1v1BattleSlapTvPopupPanel)}] Debug preview only works in Play Mode.");
|
|
return;
|
|
}
|
|
|
|
EnsureManagerForDebugPreview();
|
|
|
|
EnsureDebugPreviewRuntimeReferences();
|
|
ApplyDebugPresentationForPlayerAttackPreview();
|
|
|
|
LogDebugPreviewState(
|
|
"PlayerAttack (TryPlayPlayerAttack)",
|
|
debugPlayerAttackQuality,
|
|
debugPlayerAttackKillNpc,
|
|
GetPlayerAttackAsset(debugPlayerAttackQuality),
|
|
GetEnemyHitAsset(debugPlayerAttackQuality));
|
|
try
|
|
{
|
|
await TryPlayPlayerAttack();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError($"[{nameof(Event1v1BattleSlapTvPopupPanel)}] Debug preview PlayerAttack error, {e}");
|
|
}
|
|
}
|
|
|
|
[ContextMenu("Debug/Preview NPC Attack")]
|
|
private async void DebugPreviewNpcAttack()
|
|
{
|
|
if (!Application.isPlaying)
|
|
{
|
|
Debug.LogWarning($"[{nameof(Event1v1BattleSlapTvPopupPanel)}] Debug preview only works in Play Mode.");
|
|
return;
|
|
}
|
|
|
|
EnsureManagerForDebugPreview();
|
|
|
|
EnsureDebugPreviewRuntimeReferences();
|
|
ApplyDebugPresentationForNpcAttackPreview();
|
|
|
|
LogDebugPreviewState(
|
|
"NpcAttack (TryPlayNpcAttack)",
|
|
debugNpcAttackQuality,
|
|
debugNpcAttackKillPlayer,
|
|
GetEnemyAttackAsset(debugNpcAttackQuality),
|
|
GetPlayerHitAsset(debugNpcAttackQuality));
|
|
try
|
|
{
|
|
await TryPlayNpcAttack();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError($"[{nameof(Event1v1BattleSlapTvPopupPanel)}] Debug preview NpcAttack error, {e}");
|
|
}
|
|
}
|
|
|
|
/// <summary>无正式 Manager 时使用 <see cref="Event1v1BattleSlapManagerDebugPreview"/>,保证 <see cref="Event1v1BattleSlapManager.LoadData"/> 不碰 Repository。</summary>
|
|
private void EnsureManagerForDebugPreview()
|
|
{
|
|
if (_manager != null)
|
|
return;
|
|
_manager = new Event1v1BattleSlapManagerDebugPreview();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 与正式 TV 一致:先 <see cref="Event1v1BattleSlapPresentationData.SyncFromRealData"/> 再写本段表现字段。
|
|
/// </summary>
|
|
private void ApplyDebugPresentationForPlayerAttackPreview()
|
|
{
|
|
var pd = _manager.PresentationData;
|
|
pd.Clear();
|
|
var data = _manager.LoadData();
|
|
pd.SyncFromRealData(data);
|
|
pd.IsPlayAttacking = true;
|
|
pd.CanQuality = debugPlayerAttackQuality;
|
|
pd.KilledNpc = debugPlayerAttackKillNpc;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 与正式 TV 一致:先 <see cref="Event1v1BattleSlapPresentationData.SyncFromRealData"/> 再写本段表现字段。
|
|
/// </summary>
|
|
private void ApplyDebugPresentationForNpcAttackPreview()
|
|
{
|
|
var pd = _manager.PresentationData;
|
|
pd.Clear();
|
|
var data = _manager.LoadData();
|
|
pd.SyncFromRealData(data);
|
|
pd.IsNpcAttacking = true;
|
|
pd.NpcAttackCanQuality = debugNpcAttackQuality;
|
|
pd.KilledPlayer = debugNpcAttackKillPlayer;
|
|
}
|
|
|
|
private void EnsureDebugPreviewRuntimeReferences()
|
|
{
|
|
if (_playerDirector == null || _enemyDirector == null)
|
|
{
|
|
var spineRoot = gameObject.FindChildGameObject("spine_root");
|
|
if (spineRoot != null)
|
|
{
|
|
var directors = spineRoot.GetComponentsInChildren<UnityEngine.Playables.PlayableDirector>(true);
|
|
if (_playerDirector == null && directors.Length > 0)
|
|
_playerDirector = directors[0];
|
|
if (_enemyDirector == null && directors.Length > 1)
|
|
_enemyDirector = directors[1];
|
|
}
|
|
}
|
|
_playerDirector?.Stop();
|
|
_enemyDirector?.Stop();
|
|
_resDirector?.Stop();
|
|
}
|
|
|
|
private void LogDebugPreviewState(string previewName, int quality, bool killedTarget, UnityEngine.Playables.PlayableAsset attackAsset, UnityEngine.Playables.PlayableAsset hitAsset)
|
|
{
|
|
float attackDuration = _playerDirector != null ? GetPlayableDuration(_playerDirector, attackAsset) : 0f;
|
|
float hitDuration = _enemyDirector != null ? GetPlayableDuration(_enemyDirector, hitAsset) : 0f;
|
|
Debug.Log(
|
|
$"[{nameof(Event1v1BattleSlapTvPopupPanel)}] Debug preview {previewName} " +
|
|
$"quality={quality} killed={killedTarget} " +
|
|
$"playerDirector={_playerDirector?.name ?? "null"} enemyDirector={_enemyDirector?.name ?? "null"} " +
|
|
$"attackAsset={attackAsset?.name ?? "null"} attackDuration={attackDuration:F3} " +
|
|
$"hitAsset={hitAsset?.name ?? "null"} hitDuration={hitDuration:F3}");
|
|
}
|
|
|
|
private UnityEngine.Playables.PlayableAsset GetPlayerAttackAsset(int quality)
|
|
{
|
|
bool heavy = IsHeavyFromQuality(quality);
|
|
return heavy ? attack_player_2 ?? attack_player_1 : attack_player_1 ?? attack_player_2;
|
|
}
|
|
|
|
private UnityEngine.Playables.PlayableAsset GetEnemyHitAsset(int quality)
|
|
{
|
|
bool heavy = IsHeavyFromQuality(quality);
|
|
return heavy ? hit_enemy_2 ?? hit_enemy_1 : hit_enemy_1 ?? hit_enemy_2;
|
|
}
|
|
|
|
private UnityEngine.Playables.PlayableAsset GetEnemyAttackAsset(int quality)
|
|
{
|
|
bool heavy = IsHeavyFromQuality(quality);
|
|
return heavy ? attack_enemy_2 ?? attack_enemy_1 : attack_enemy_1 ?? attack_enemy_2;
|
|
}
|
|
|
|
private UnityEngine.Playables.PlayableAsset GetPlayerHitAsset(int quality)
|
|
{
|
|
bool heavy = IsHeavyFromQuality(quality);
|
|
return heavy ? hit_player_2 ?? hit_player_1 : hit_player_1 ?? hit_player_2;
|
|
}
|
|
}
|
|
}
|
|
#endif
|