Live: play the stage's own Animation clips (missing AnimationObjectController)
The stage prefab references 11 script classes and UmaViewer implements exactly one of them (StageController). The other ten deserialize with a null script reference and never run: AnimationObjectController, BillboardController, CustomLensFlare, UnityLensFlareController, CustomProjector, LightProjection, MirrorBallProjector, MirrorReflection, ShaderParamController, WashLightController. AnimationObjectController's absence has the most visible effect. live10149 has 283 Animation components, all 283 with playAutomatically = true and all 283 with a null default clip. playAutomatically plays the default clip, so a null one plays nothing — the original drives them with an explicit Play(name). The result is that no stage animation runs at all: the mirror ball does not spin, the wash lights do not sweep, the neon signs do not move. Only the unambiguous case is handled. Clip counts per component are 1 (4 objects), 3 (6), 5 (272) and 0 (1). The single-clip objects are all named *_loop_000 — mirrorball_flarelight and wash_ground_b/c/d — and are played. The 3-clip sets are loop_000 / up_000 / loop_001, a transition plus two loop states, and AnimationObjectController carries no serialized fields at all, so nothing in the data says which to pick or when to switch. Those and the 5-clip sets are logged with their clip names and left alone rather than guessed at. Playback happens in OnEnable, not once at init: timeline-controlled lights start inactive and Play() does not stick on an inactive object. The mirror ball's container is pfb_env_live10149_blinklight_mirrorball_flarelight, which is exactly that case. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Gallop.Live
|
||||
{
|
||||
/// <summary>
|
||||
/// 舞台自带 <see cref="Animation"/> 的播放。
|
||||
///
|
||||
/// 为什么需要:live10149 的舞台 prefab 引用了 11 个脚本类,UmaViewer 里**只有
|
||||
/// StageController 存在**,另外 10 个(AnimationObjectController、MirrorBallProjector、
|
||||
/// MirrorReflection、CustomLensFlare、UnityLensFlareController、CustomProjector、
|
||||
/// LightProjection、WashLightController、BillboardController、ShaderParamController)
|
||||
/// 全部缺失,那些 MonoBehaviour 反序列化后脚本引用为空,永远不执行。
|
||||
///
|
||||
/// 其中 AnimationObjectController 的缺席后果最直接:舞台上 283 个 Animation 组件
|
||||
/// **全部** `playAutomatically = true`,但**默认 clip(m_Animation)全部为空**。
|
||||
/// Unity 的 playAutomatically 播的是默认 clip,默认 clip 为空就什么都不播 ——
|
||||
/// 原版是靠那个脚本显式 Play("clip名") 的。于是整个舞台的动画一个都没动:
|
||||
/// 迪斯科灯球不转、wash 灯不扫、霓虹灯牌不动。
|
||||
///
|
||||
/// **只处理唯一解的情形。** clip 数量分布:
|
||||
/// 1 个 clip → 4 个对象(mirrorball_flarelight、wash_ground_b/c/d),全是 `*_loop_000`,
|
||||
/// 没有歧义,直接播。
|
||||
/// 3 个 clip → `loop_000` / `up_000` / `loop_001`,是「过渡 + 两个循环态」的状态机,
|
||||
/// 选哪个、何时切换都没有依据。
|
||||
/// 5 个 clip → 272 个对象(占 96%,多半是观众席),同样未知。
|
||||
/// 后两类只打一次日志把 clip 名列出来,**不猜**。选择规则逆出来之后再补。
|
||||
///
|
||||
/// 播放时机走 OnEnable 而不是初始化时一次性 Play:受时间轴控制的灯(名字含
|
||||
/// blinklight/_wash_/laser/spotlight3d)初始是 inactive 的,要等轨道把它们打开,
|
||||
/// 在 inactive 对象上调 Play() 不会生效。镜面球容器
|
||||
/// pfb_env_live10149_blinklight_mirrorball_flarelight 正好就是这种情况。
|
||||
/// </summary>
|
||||
public static class StageAnimationPlayer
|
||||
{
|
||||
public static void Setup(StageController stage)
|
||||
{
|
||||
if (stage == null) return;
|
||||
|
||||
int single = 0, ambiguous = 0, empty = 0;
|
||||
var loggedClipSets = new HashSet<string>();
|
||||
|
||||
foreach (var anim in stage.GetComponentsInChildren<Animation>(true))
|
||||
{
|
||||
if (anim == null || !anim.playAutomatically) continue;
|
||||
|
||||
var clips = new List<AnimationClip>();
|
||||
foreach (AnimationState st in anim)
|
||||
{
|
||||
if (st != null && st.clip != null) clips.Add(st.clip);
|
||||
}
|
||||
|
||||
if (clips.Count == 0) { empty++; continue; }
|
||||
|
||||
if (clips.Count == 1)
|
||||
{
|
||||
// 唯一解:把它设成默认 clip 并在每次启用时播放。
|
||||
anim.clip = clips[0];
|
||||
var auto = anim.gameObject.GetComponent<StageAnimationAutoPlay>();
|
||||
if (auto == null) auto = anim.gameObject.AddComponent<StageAnimationAutoPlay>();
|
||||
auto.Bind(anim, clips[0].name);
|
||||
single++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ambiguous++;
|
||||
var names = new List<string>();
|
||||
foreach (var c in clips) names.Add(c.name);
|
||||
string key = string.Join(",", names);
|
||||
if (loggedClipSets.Add(key))
|
||||
{
|
||||
Debug.Log($"[StageAnim] '{anim.gameObject.name}' 有 {clips.Count} 个 clip," +
|
||||
$"选择规则未知,**未播放**:{key}");
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[StageAnim] 单 clip 已接管 {single} 个;多 clip 未处理 {ambiguous} 个;无 clip {empty} 个");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在 OnEnable 时播放绑定的 clip。受时间轴控制的舞台灯初始 inactive,
|
||||
/// 等 BlinkLight/WashLight/Laser 的 handler 把它们 SetActive(true) 之后才需要动起来。
|
||||
/// </summary>
|
||||
public class StageAnimationAutoPlay : MonoBehaviour
|
||||
{
|
||||
private Animation _anim;
|
||||
private string _clipName;
|
||||
|
||||
public void Bind(Animation anim, string clipName)
|
||||
{
|
||||
_anim = anim;
|
||||
_clipName = clipName;
|
||||
if (isActiveAndEnabled) PlayClip();
|
||||
}
|
||||
|
||||
private void OnEnable() => PlayClip();
|
||||
|
||||
private void PlayClip()
|
||||
{
|
||||
if (_anim == null || string.IsNullOrEmpty(_clipName)) return;
|
||||
// 已经在播就不要重来,否则每次 SetActive 都会把循环打回起点。
|
||||
if (_anim.IsPlaying(_clipName)) return;
|
||||
_anim.Play(_clipName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d81b24efae747a9ad81969e4c19800e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -106,6 +106,9 @@ namespace Gallop.Live
|
||||
}
|
||||
}
|
||||
|
||||
// 舞台自带 Animation 的播放(原版由缺失的 AnimationObjectController 负责)。
|
||||
StageAnimationPlayer.Setup(this);
|
||||
|
||||
// 地板发白的诊断,只打日志不改任何东西。见 StageEnvMapDiag 的说明。
|
||||
StageEnvMapDiag.Dump(this);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user