Files
VFSUnity/Assets/Scripts/Animation/OpeningFlowController.cs
T
yangbear 4147d6e800 fix: 修复黑幕不显示的根因 — BlackScreenPanel active=false 导致 GameObject.Find 找不到
根因: BlackScreenPanel 初始 active=false,GameObject.Find() 只能找活跃对象
→ _blackScreenPanel 一直为 null → FadeBlackScreen() 直接 yield break 跳过

修复:
1. 场景中激活 BlackScreenPanel(alpha=0 所以视觉不可见)
2. AutoAssignReferences() 增加 FindObjectsOfType<Image>(true) 兜底
3. Start() 改为保持 BlackScreenPanel active + alpha=0,而非 SetActive(false)
4. 增加 Debug.Log 确认 BlackScreenPanel 找到状态
2026-06-29 20:41:12 +08:00

224 lines
8.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
/// <summary>
/// 片头动画流程控制器:控制 man 的 Idle → Shoot → Fall 流程,
/// 摔倒后黑幕转场,显示 woman 和 maninjury。
/// 挂在一个独立的空 GameObject 上(如 SceneRoot)。
/// </summary>
public class OpeningFlowController : MonoBehaviour
{
private void Start()
{
// 自动查找引用
AutoAssignReferences();
// 初始状态确认:woman 和 maninjury 应该隐藏
if (_womanObject != null) _womanObject.SetActive(false);
if (_manInjuryObject != null) _manInjuryObject.SetActive(false);
// BlackScreenPanel:保持 active,但确保 alpha=0(透明不可见)
if (_blackScreenPanel != null)
{
_blackScreenPanel.SetActive(true);
if (_blackScreenImage != null)
_blackScreenImage.color = new Color(0, 0, 0, 0);
Debug.Log("[OpeningFlow] BlackScreenPanel 已就绪,初始透明");
}
// 不自动启动动画流程 —— 等待用户选择模式和固定方式后由 PageController 触发
Debug.Log("[OpeningFlow] 就绪,等待用户选择模式和固定方式。");
}
private void AutoAssignReferences()
{
var manGo = GameObject.Find("man");
if (manGo != null && _manAnimator == null)
_manAnimator = manGo.GetComponent<Animator>();
var man2Go = GameObject.Find("man2");
if (man2Go != null)
{
if (_man2Animator == null) _man2Animator = man2Go.GetComponent<Animator>();
if (_man2Object == null) _man2Object = man2Go;
}
if (_womanObject == null) _womanObject = GameObject.Find("woman");
if (_manInjuryObject == null) _manInjuryObject = GameObject.Find("maninjury");
// BlackScreenPanel:先用常规 Find,找不到再用 includeInactive 兜底
if (_blackScreenPanel == null)
_blackScreenPanel = GameObject.Find("BlackScreenPanel");
if (_blackScreenPanel == null)
{
// 兜底:搜索非活跃对象
var allImages = FindObjectsOfType<Image>(true);
foreach (var img in allImages)
{
if (img.name == "BlackScreenPanel")
{
_blackScreenPanel = img.gameObject;
_blackScreenImage = img;
Debug.Log("[OpeningFlow] BlackScreenPanel 通过 includeInactive 兜底找到");
break;
}
}
}
if (_blackScreenPanel != null && _blackScreenImage == null)
_blackScreenImage = _blackScreenPanel.GetComponent<Image>();
if (_blackScreenPanel == null)
Debug.LogWarning("[OpeningFlow] BlackScreenPanel 未找到!黑幕转场将不会显示");
else
Debug.Log($"[OpeningFlow] BlackScreenPanel 已找到: activeInHierarchy={_blackScreenPanel.activeInHierarchy}, Image={_blackScreenImage != null}");
}
/// <summary>
/// 公开方法:由 PageController 在用户选定固定方式后调用。
/// 播放片头动画(man Idle→Shoot→Fall→黑幕转场→显示woman+maninjury),
/// 完成后回调 onComplete。
/// </summary>
public void PlayOpeningFlow(System.Action onComplete)
{
Debug.Log("[OpeningFlow] PlayOpeningFlow() 被调用,开始播放片头动画。");
StartCoroutine(RunOpeningFlow(onComplete));
}
private IEnumerator RunOpeningFlow(System.Action onComplete)
{
Debug.Log("=== [OpeningFlow] 片头动画流程开始 ===");
// 强制重置 man 所有动画参数,确保从 Idle 状态开始
if (_manAnimator != null)
{
_manAnimator.SetBool("IsStart", false);
_manAnimator.SetBool("IsFull", false);
_manAnimator.Play("manIdle", 0, 0f);
Debug.Log("[OpeningFlow] man Animator 已重置: IsStart=false, IsFull=false, 强制播放 manIdle");
}
else
{
Debug.LogWarning("[OpeningFlow] _manAnimator 为空!");
}
// Step 1: man 和 man2 同时 Idle,持续 _idleDuration 秒
Debug.Log($"[OpeningFlow] Step1: man + man2 Idle ({_idleDuration}s)");
yield return new WaitForSeconds(_idleDuration);
// Step 2: man 投篮动画 Shoot (3.15s)
Debug.Log("[OpeningFlow] Step2: man Shoot 动画开始");
if (_manAnimator != null)
{
_manAnimator.SetBool("IsFull", false);
_manAnimator.SetBool("IsStart", true);
Debug.Log("[OpeningFlow] man IsStart=true, IsFull=false, 触发 Shoot");
yield return new WaitForSeconds(3.15f);
_manAnimator.SetBool("IsStart", false);
Debug.Log("[OpeningFlow] Step2: man Shoot 动画结束");
}
else
{
Debug.LogWarning("[OpeningFlow] _manAnimator 为空,跳过 Step2");
}
// Step 3: man 摔倒动画 manfull,等待动画播完 + 停留缓冲
Debug.Log("[OpeningFlow] Step3: man Fall 动画开始");
if (_manAnimator != null)
{
_manAnimator.SetBool("IsFull", true);
Debug.Log("[OpeningFlow] man IsFull=true, 触发 manfull");
// 等待 manfull 动画播放完成(2.1s
yield return new WaitForSeconds(2.1f);
Debug.Log("[OpeningFlow] Step3: man Fall 动画结束");
// 摔倒后停留缓冲,让玩家看清摔倒结果
Debug.Log($"[OpeningFlow] Step3: 摔倒后停留缓冲 {_fallHoldDuration}s");
yield return new WaitForSeconds(_fallHoldDuration);
}
else
{
Debug.LogWarning("[OpeningFlow] _manAnimator 为空,跳过 Step3");
}
// Step 4: 黑幕转场 —— 渐入 -> 切换角色+摄像机 -> 渐出
Debug.Log("[OpeningFlow] Step4: 黑幕转场开始");
yield return StartCoroutine(FadeBlackScreen(0f, 1f));
// 切换角色
if (_man2Object != null) { _man2Object.SetActive(false); Debug.Log("[OpeningFlow] man2 已隐藏"); }
if (_womanObject != null) { _womanObject.SetActive(true); Debug.Log("[OpeningFlow] woman 已显示"); }
if (_manInjuryObject != null) { _manInjuryObject.SetActive(true); Debug.Log("[OpeningFlow] maninjury 已显示"); }
// 切换摄像机到 camera2
SwitchToCamera2();
yield return new WaitForSeconds(0.3f);
yield return StartCoroutine(FadeBlackScreen(1f, 0f));
Debug.Log("=== [OpeningFlow] 片头动画流程完成 ===");
onComplete?.Invoke();
}
/// <summary>
/// 切换到 camera2,禁用主摄像机
/// </summary>
private void SwitchToCamera2()
{
var camera2Go = GameObject.Find("camera2");
if (camera2Go != null)
{
var cam2 = camera2Go.GetComponent<Camera>();
if (cam2 != null)
{
cam2.enabled = true;
Debug.Log("[OpeningFlow] camera2 已启用");
}
else
{
Debug.LogWarning("[OpeningFlow] camera2 上没有 Camera 组件!");
}
// 禁用主摄像机(MainCamera 或标签为 MainCamera 的)
var mainCam = Camera.main;
if (mainCam != null)
{
mainCam.enabled = false;
Debug.Log("[OpeningFlow] 主摄像机已禁用");
}
}
else
{
Debug.LogWarning("[OpeningFlow] 未找到 camera2,摄像机未切换");
}
}
private IEnumerator FadeBlackScreen(float fromAlpha, float toAlpha)
{
if (_blackScreenPanel == null || _blackScreenImage == null)
{
Debug.LogWarning("[OpeningFlow] BlackScreenPanel 或 Image 为空,跳过转场");
yield break;
}
_blackScreenPanel.SetActive(true);
float elapsed = 0f;
while (elapsed < _fadeDuration)
{
elapsed += Time.deltaTime;
float t = Mathf.Clamp01(elapsed / _fadeDuration);
_blackScreenImage.color = new Color(0, 0, 0, Mathf.Lerp(fromAlpha, toAlpha, t));
yield return null;
}
_blackScreenImage.color = new Color(0, 0, 0, toAlpha);
if (toAlpha <= 0.01f)
_blackScreenPanel.SetActive(false);
}
[SerializeField] private float _fallHoldDuration = 1.5f;
}