Files
VFSUnity/Assets/Scripts/Animation/OpeningFlowController.cs
T
yangbear c592358ef8 fix: 修复 manIdle 未播放问题 + 添加 camera2 切换
- RunOpeningFlow 开头强制重置 Animator: SetBool(false) + Play("manIdle")
- Step2 前确保 IsFull=false(适配 Idle→Shoot 过渡条件)
- 黑屏转场后调用 SwitchToCamera2(),启用 camera2、禁用主摄像机
- 所有关键步骤增加详细 Debug.Log
2026-06-29 20:35:12 +08:00

200 lines
7.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
{
[Header("=== 角色引用 ===")]
[SerializeField] private Animator _manAnimator;
[SerializeField] private Animator _man2Animator;
[SerializeField] private GameObject _man2Object;
[SerializeField] private GameObject _womanObject;
[SerializeField] private GameObject _manInjuryObject;
[Header("=== 黑幕 UI ===")]
[SerializeField] private GameObject _blackScreenPanel;
[SerializeField] private Image _blackScreenImage;
[Header("=== 时间配置 ===")]
[SerializeField] private float _idleDuration = 2f;
[SerializeField] private float _fadeDuration = 1f;
private void Start()
{
// 自动查找引用
AutoAssignReferences();
// 初始状态确认:woman 和 maninjury 应该隐藏
if (_womanObject != null) _womanObject.SetActive(false);
if (_manInjuryObject != null) _manInjuryObject.SetActive(false);
if (_blackScreenPanel != null) _blackScreenPanel.SetActive(false);
// 不自动启动动画流程 —— 等待用户选择模式和固定方式后由 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");
if (_blackScreenPanel == null) _blackScreenPanel = GameObject.Find("BlackScreenPanel");
if (_blackScreenImage == null && _blackScreenPanel != null)
_blackScreenImage = _blackScreenPanel.GetComponent<Image>();
}
/// <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)
// 先确保 IsFull=false(因为 Idle→Shoot 过渡条件需要 IsFull=false
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 (2.1s)
Debug.Log("[OpeningFlow] Step3: man Fall 动画开始");
if (_manAnimator != null)
{
_manAnimator.SetBool("IsFull", true);
Debug.Log("[OpeningFlow] man IsFull=true, 触发 manfull");
yield return new WaitForSeconds(2.1f);
Debug.Log("[OpeningFlow] Step3: man Fall 动画结束");
}
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);
}
}