470 lines
14 KiB
C#
470 lines
14 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using DG.Tweening;
|
||
using DragonLi.Core;
|
||
|
||
/// <summary>
|
||
/// 拼图完成CG控制器 - 播放桃花绽放、桃花雨等完成特效
|
||
/// </summary>
|
||
public class PuzzleCompleteCG : MonoBehaviour
|
||
{
|
||
[Header("CG设置")]
|
||
[SerializeField] private float cgTotalDuration = 10f; // CG总时长
|
||
[SerializeField] private bool playOnEnable = false; // 是否在激活时自动播放
|
||
|
||
[Header("桃花树")]
|
||
[SerializeField] private List<GameObject> peachTrees; // 桃树列表
|
||
[SerializeField] private List<Transform> blossomPoints; // 花骨朵绽放点
|
||
[SerializeField] private GameObject blossomPrefab; // 桃花绽放特效预制体
|
||
[SerializeField] private float blossomDelayBetweenTrees = 0.5f; // 每棵树绽放间隔
|
||
[SerializeField] private float blossomDuration = 2f; // 单棵树绽放时长
|
||
|
||
[Header("桃花雨")]
|
||
[SerializeField] private ParticleSystem peachRainEffect; // 桃花雨特效
|
||
[SerializeField] private float peachRainDelay = 3f; // 桃花雨开始延迟
|
||
[SerializeField] private float peachRainDuration = 5f; // 桃花雨持续时间
|
||
[SerializeField] private Transform peachRainArea; // 桃花雨区域
|
||
[SerializeField] private float rainAreaWidth = 10f; // 雨区域宽度
|
||
[SerializeField] private float rainAreaHeight = 5f; // 雨区域高度
|
||
|
||
[Header("猴子跳舞")]
|
||
[SerializeField] private List<Animator> monkeyAnimators; // 猴子动画控制器列表
|
||
[SerializeField] private string monkeyDanceAnimName = "dance"; // 猴子跳舞动画名
|
||
[SerializeField] private float monkeyDanceDelay = 2f; // 猴子跳舞延迟
|
||
[SerializeField] private float monkeyDanceDuration = 8f; // 猴子跳舞时长
|
||
|
||
[Header("相机动画")]
|
||
[SerializeField] private Camera mainCamera; // 主相机
|
||
[SerializeField] private Transform cameraStartPos; // 相机起始位置
|
||
[SerializeField] private Transform cameraEndPos; // 相机结束位置
|
||
[SerializeField] private float cameraMoveDuration = 5f; // 相机移动时长
|
||
[SerializeField] private float cameraDelay = 1f; // 相机动画延迟
|
||
|
||
[Header("灯光效果")]
|
||
[SerializeField] private Light mainLight; // 主光源
|
||
[SerializeField] private Color normalLightColor = Color.white; // 正常灯光颜色
|
||
[SerializeField] private Color cgLightColor = new Color(1f, 0.9f, 0.7f); // CG灯光颜色(暖色调)
|
||
[SerializeField] private float lightTransitionDuration = 3f; // 灯光渐变时长
|
||
|
||
[Header("音效")]
|
||
[SerializeField] private string cgStartSound = "1.51"; // CG开始音效
|
||
[SerializeField] private string blossomSound = "1.52"; // 花绽放音效
|
||
[SerializeField] private string peachRainSound = "1.53"; // 桃花雨音效
|
||
[SerializeField] private string monkeyDanceSound = "1.54"; // 猴子跳舞音效
|
||
[SerializeField] private int bgmCueName = 1; // 结束BGM
|
||
|
||
[Header("UI")]
|
||
[SerializeField] private GameObject cgUIPanel; // CG UI面板
|
||
[SerializeField] private UnityEngine.UI.Text cgText; // CG文字
|
||
[SerializeField] private float textFadeDelay = 8f; // 文字淡入延迟
|
||
|
||
// CG播放状态
|
||
private bool isPlayingCG = false;
|
||
private Coroutine cgCoroutine;
|
||
|
||
public bool IsPlayingCG => isPlayingCG;
|
||
|
||
private void Start()
|
||
{
|
||
if (playOnEnable)
|
||
{
|
||
PlayCompleteCG();
|
||
}
|
||
}
|
||
|
||
#region CG播放控制
|
||
|
||
/// <summary>
|
||
/// 播放完成CG
|
||
/// </summary>
|
||
public void PlayCompleteCG()
|
||
{
|
||
if (isPlayingCG) return;
|
||
|
||
isPlayingCG = true;
|
||
cgCoroutine = StartCoroutine(PlayCGSequence());
|
||
|
||
Debug.Log("开始播放拼图完成CG...");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 停止CG播放
|
||
/// </summary>
|
||
public void StopCG()
|
||
{
|
||
if (cgCoroutine != null)
|
||
{
|
||
StopCoroutine(cgCoroutine);
|
||
cgCoroutine = null;
|
||
}
|
||
|
||
isPlayingCG = false;
|
||
|
||
// 重置所有效果
|
||
ResetAllEffects();
|
||
|
||
Debug.Log("CG播放已停止");
|
||
}
|
||
|
||
/// <summary>
|
||
/// CG播放序列
|
||
/// </summary>
|
||
private IEnumerator PlayCGSequence()
|
||
{
|
||
// 播放CG开始音效
|
||
if (!string.IsNullOrEmpty(cgStartSound))
|
||
{
|
||
GameManager.Ins?.PlaySound2DRPC(cgStartSound);
|
||
}
|
||
|
||
// 切换BGM
|
||
GameManager.Ins?.PlayBGM(bgmCueName);
|
||
|
||
// 显示CG UI
|
||
if (cgUIPanel != null)
|
||
{
|
||
cgUIPanel.SetActive(true);
|
||
}
|
||
|
||
// 灯光渐变
|
||
StartCoroutine(TransitionLight());
|
||
|
||
// 相机动画(如果有设置)
|
||
if (mainCamera != null && cameraStartPos != null && cameraEndPos != null)
|
||
{
|
||
yield return new WaitForSeconds(cameraDelay);
|
||
StartCoroutine(MoveCamera());
|
||
}
|
||
|
||
// 桃花绽放
|
||
yield return new WaitForSeconds(1f);
|
||
StartCoroutine(PlayBlossomEffect());
|
||
|
||
// 猴子跳舞
|
||
yield return new WaitForSeconds(monkeyDanceDelay);
|
||
StartCoroutine(PlayMonkeyDance());
|
||
|
||
// 桃花雨
|
||
yield return new WaitForSeconds(peachRainDelay - monkeyDanceDelay);
|
||
StartCoroutine(PlayPeachRain());
|
||
|
||
// 文字淡入
|
||
yield return new WaitForSeconds(textFadeDelay - peachRainDelay);
|
||
ShowEndingText();
|
||
|
||
// 等待CG完成
|
||
yield return new WaitForSeconds(cgTotalDuration - textFadeDelay);
|
||
|
||
// CG结束
|
||
OnCGComplete();
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 子效果播放
|
||
|
||
/// <summary>
|
||
/// 灯光渐变
|
||
/// </summary>
|
||
private IEnumerator TransitionLight()
|
||
{
|
||
if (mainLight == null) yield break;
|
||
|
||
float elapsed = 0f;
|
||
Color startColor = mainLight.color;
|
||
|
||
while (elapsed < lightTransitionDuration)
|
||
{
|
||
mainLight.color = Color.Lerp(startColor, cgLightColor, elapsed / lightTransitionDuration);
|
||
elapsed += Time.deltaTime;
|
||
yield return null;
|
||
}
|
||
|
||
mainLight.color = cgLightColor;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 相机移动动画
|
||
/// </summary>
|
||
private IEnumerator MoveCamera()
|
||
{
|
||
if (mainCamera == null || cameraStartPos == null || cameraEndPos == null) yield break;
|
||
|
||
// 设置起始位置
|
||
mainCamera.transform.position = cameraStartPos.position;
|
||
mainCamera.transform.rotation = cameraStartPos.rotation;
|
||
|
||
// 移动到结束位置
|
||
float elapsed = 0f;
|
||
Vector3 startPos = cameraStartPos.position;
|
||
Vector3 endPos = cameraEndPos.position;
|
||
Quaternion startRot = cameraStartPos.rotation;
|
||
Quaternion endRot = cameraEndPos.rotation;
|
||
|
||
while (elapsed < cameraMoveDuration)
|
||
{
|
||
mainCamera.transform.position = Vector3.Lerp(startPos, endPos, elapsed / cameraMoveDuration);
|
||
mainCamera.transform.rotation = Quaternion.Lerp(startRot, endRot, elapsed / cameraMoveDuration);
|
||
elapsed += Time.deltaTime;
|
||
yield return null;
|
||
}
|
||
|
||
mainCamera.transform.position = endPos;
|
||
mainCamera.transform.rotation = endRot;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 桃花绽放效果
|
||
/// </summary>
|
||
private IEnumerator PlayBlossomEffect()
|
||
{
|
||
// 播放花绽放音效
|
||
if (!string.IsNullOrEmpty(blossomSound))
|
||
{
|
||
GameManager.Ins?.PlaySound2DRPC(blossomSound);
|
||
}
|
||
|
||
// 每棵树依次绽放
|
||
foreach (var tree in peachTrees)
|
||
{
|
||
// 在树上创建绽放特效
|
||
if (blossomPrefab != null && blossomPoints.Count > 0)
|
||
{
|
||
// 随机选择绽放点
|
||
foreach (var point in blossomPoints)
|
||
{
|
||
if (Random.value > 0.5f) // 随机绽放
|
||
{
|
||
GameObject blossom = Instantiate(blossomPrefab, point.position, point.rotation);
|
||
blossom.transform.SetParent(tree.transform);
|
||
|
||
// 播放绽放动画
|
||
blossom.transform.localScale = Vector3.zero;
|
||
blossom.transform.DOScale(1f, blossomDuration).SetEase(Ease.OutBack);
|
||
|
||
// 延迟后淡出
|
||
DOVirtual.DelayedCall(blossomDuration + 1f, () =>
|
||
{
|
||
blossom.GetComponent<Renderer>()?.material.DOFade(0f, 1f).OnComplete(() =>
|
||
{
|
||
Destroy(blossom);
|
||
});
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
// 等待下一棵树
|
||
yield return new WaitForSeconds(blossomDelayBetweenTrees);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 桃花雨效果
|
||
/// </summary>
|
||
private IEnumerator PlayPeachRain()
|
||
{
|
||
// 播放桃花雨音效
|
||
if (!string.IsNullOrEmpty(peachRainSound))
|
||
{
|
||
GameManager.Ins?.PlaySound2DRPC(peachRainSound);
|
||
}
|
||
|
||
if (peachRainEffect != null)
|
||
{
|
||
peachRainEffect.Play();
|
||
|
||
// 设置雨区域大小
|
||
if (peachRainArea != null)
|
||
{
|
||
var shape = peachRainEffect.shape;
|
||
shape.scale = new Vector3(rainAreaWidth, rainAreaHeight, 1f);
|
||
}
|
||
|
||
// 持续播放
|
||
yield return new WaitForSeconds(peachRainDuration);
|
||
|
||
peachRainEffect.Stop();
|
||
}
|
||
else
|
||
{
|
||
yield return new WaitForSeconds(peachRainDuration);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 猴子跳舞动画
|
||
/// </summary>
|
||
private IEnumerator PlayMonkeyDance()
|
||
{
|
||
// 播放猴子跳舞音效
|
||
if (!string.IsNullOrEmpty(monkeyDanceSound))
|
||
{
|
||
GameManager.Ins?.PlaySound2DRPC(monkeyDanceSound);
|
||
}
|
||
|
||
// 让所有猴子开始跳舞
|
||
foreach (var animator in monkeyAnimators)
|
||
{
|
||
if (animator != null)
|
||
{
|
||
animator.Play(monkeyDanceAnimName);
|
||
|
||
// 随机延迟,让每个猴子跳舞节奏不同
|
||
yield return new WaitForSeconds(Random.Range(0.1f, 0.3f));
|
||
}
|
||
}
|
||
|
||
// 持续跳舞
|
||
yield return new WaitForSeconds(monkeyDanceDuration);
|
||
|
||
// 停止跳舞
|
||
foreach (var animator in monkeyAnimators)
|
||
{
|
||
if (animator != null)
|
||
{
|
||
animator.Play("idle");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示结束文字
|
||
/// </summary>
|
||
private void ShowEndingText()
|
||
{
|
||
// if (cgText != null)
|
||
// {
|
||
// cgText.gameObject.SetActive(true);
|
||
// cgText.text = "拼图完成!\n桃花源已重现...";
|
||
//
|
||
// // 淡入动画
|
||
// var canvasGroup = cgText.GetComponent<UnityEngine.UI.CanvasGroup>();
|
||
// if (canvasGroup == null) canvasGroup = cgText.gameObject.AddComponent<UnityEngine.UI.CanvasGroup>();
|
||
//
|
||
// canvasGroup.alpha = 0f;
|
||
// canvasGroup.DOFade(1f, 1f);
|
||
// }
|
||
}
|
||
|
||
/// <summary>
|
||
/// CG完成回调
|
||
/// </summary>
|
||
private void OnCGComplete()
|
||
{
|
||
isPlayingCG = false;
|
||
|
||
Debug.Log("拼图完成CG播放完毕");
|
||
|
||
// 触发游戏胜利结算
|
||
GameManager.Ins?.GameOver(GameState.Victory);
|
||
|
||
// 隐藏CG UI
|
||
if (cgUIPanel != null)
|
||
{
|
||
cgUIPanel.SetActive(false);
|
||
// var canvasGroup = cgUIPanel.GetComponent<UnityEngine.UI.CanvasGroup>();
|
||
// if (canvasGroup != null)
|
||
// {
|
||
// canvasGroup.DOFade(0f, 2f).OnComplete(() =>
|
||
// {
|
||
// cgUIPanel.SetActive(false);
|
||
// });
|
||
// }
|
||
// else
|
||
// {
|
||
// cgUIPanel.SetActive(false);
|
||
// }
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 效果重置
|
||
|
||
/// <summary>
|
||
/// 重置所有效果
|
||
/// </summary>
|
||
private void ResetAllEffects()
|
||
{
|
||
// 停止桃花雨
|
||
if (peachRainEffect != null)
|
||
{
|
||
peachRainEffect.Stop();
|
||
}
|
||
|
||
// 重置灯光
|
||
if (mainLight != null)
|
||
{
|
||
mainLight.color = normalLightColor;
|
||
}
|
||
|
||
// 重置相机
|
||
if (mainCamera != null && cameraStartPos != null)
|
||
{
|
||
mainCamera.transform.position = cameraStartPos.position;
|
||
mainCamera.transform.rotation = cameraStartPos.rotation;
|
||
}
|
||
|
||
// 停止猴子跳舞
|
||
foreach (var animator in monkeyAnimators)
|
||
{
|
||
if (animator != null)
|
||
{
|
||
animator.Play("idle");
|
||
}
|
||
}
|
||
|
||
// 隐藏UI
|
||
if (cgUIPanel != null)
|
||
{
|
||
cgUIPanel.SetActive(false);
|
||
}
|
||
|
||
if (cgText != null)
|
||
{
|
||
cgText.gameObject.SetActive(false);
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 公共方法
|
||
|
||
/// <summary>
|
||
/// 设置桃树列表(外部调用)
|
||
/// </summary>
|
||
public void SetPeachTrees(List<GameObject> trees)
|
||
{
|
||
peachTrees = trees;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置猴子动画控制器列表(外部调用)
|
||
/// </summary>
|
||
public void SetMonkeyAnimators(List<Animator> animators)
|
||
{
|
||
monkeyAnimators = animators;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加单个桃树
|
||
/// </summary>
|
||
public void AddPeachTree(GameObject tree)
|
||
{
|
||
if (peachTrees == null) peachTrees = new List<GameObject>();
|
||
peachTrees.Add(tree);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加单个猴子
|
||
/// </summary>
|
||
public void AddMonkeyAnimator(Animator animator)
|
||
{
|
||
if (monkeyAnimators == null) monkeyAnimators = new List<Animator>();
|
||
monkeyAnimators.Add(animator);
|
||
}
|
||
|
||
#endregion
|
||
} |