using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using DarkTonic.MasterAudio;
using DG.Tweening;
///
/// 水晶雕像事件 - 继承CutsceneBase
/// 管理三轮水晶雕像挑战的完整流程
///
public class CrystalStatueEvent : CutsceneBase
{
#region 配置
[Header("雕像预制体")]
public GameObject crystalStatuePrefab;
[Header("生成配置")]
public int statueCount = 5;
public float statueRadius = 3f; // 五角星排列半径
public float statueHeight = 0f; // 雕像高度
[Header("时间配置")]
public float roundTimeLimit = 90f; // 每轮时间限制(秒)
public float delayBetweenRounds = 3f; // 轮次间隔
[Header("音效配置")]
public string audioRound1Intro = "1.5"; // 第一轮介绍
public string audioRound1Success = "1.7"; // 第一轮成功
public string audioRound2Intro = "1.8"; // 第二轮介绍
public string audioRound2Success = "1.9"; // 第二轮成功
public string audioRound3Intro = "1.10"; // 第三轮介绍
public string audioRound3Success = "1.11"; // 第三轮成功
public string audioFail = "1.6"; // 失败提示
public string audioCrystalBreak = "2.1"; // 水晶敲碎
public string audioSuccessEffect = "2.2"; // 成功音效
public string audioEvilLaugh = "2.3"; // 狞笑音效
[Header("场景配置")]
public GameObject crystalWorldEnvironment; // 水晶世界环境
#endregion
#region 状态
public enum CrystalEventState
{
None,
SceneTransition, // 场景切换
Round1_Intro, // 第一轮介绍
Round1_Playing, // 第一轮进行中
Round1_Success, // 第一轮成功
Round1_Fail, // 第一轮失败
Round2_Intro, // 第二轮介绍
Round2_Playing, // 第二轮进行中
Round2_Success, // 第二轮成功
Round2_Fail, // 第二轮失败
Round3_Intro, // 第三轮介绍
Round3_Playing, // 第三轮进行中
Round3_Success, // 第三轮成功
Round3_Fail, // 第三轮失败
TimeUp, // 超时失败
Complete // 全部完成
}
public CrystalEventState currentState = CrystalEventState.None;
public int currentRound = 0;
#endregion
#region 私有变量
private List spawnedStatues = new List();
private CrystalStatue targetStatue; // 当前目标雕像
private float currentRoundTime; // 当前剩余时间
private bool isRoundActive; // 当前轮次是否激活
private bool isTimeUp; // 时间是否耗尽
private Coroutine roundTimerCoroutine;
#endregion
#region 实现抽象方法
public override void StartCutscene()
{
if (isPlaying)
{
Debug.LogWarning("[CrystalStatueEvent] 事件已在进行中");
return;
}
isPlaying = true;
currentStep = 0;
currentRound = 0;
currentState = CrystalEventState.None;
if (debugMode)
Debug.Log("[CrystalStatueEvent] ========== 开始水晶雕像事件 ==========");
// 进入雕像事件模式,切换道具
if (GameManager.Ins.playerRightHand != null)
{
GameManager.Ins.playerRightHand.EnterStatueEventMode();
}
StartCoroutine(PlayEventSequence());
}
public override string GetCurrentStateDescription()
{
return $"轮次{currentRound}: {currentState}, 剩余时间: {currentRoundTime:F1}秒";
}
#endregion
#region 事件流程
private IEnumerator PlayEventSequence()
{
// ========== 场景切换 ==========
currentState = CrystalEventState.SceneTransition;
currentStep = 1;
if (debugMode)
Debug.Log("[CrystalStatueEvent] 步骤1: 场景切换到水晶世界");
// 激活水晶世界环境
if (crystalWorldEnvironment != null)
crystalWorldEnvironment.SetActive(true);
// 播放BGM
GameManager.Ins.PlayBGM(1);
yield return new WaitForSeconds(1f);
// ========== 第一轮:邪恶表情 ==========
currentRound = 1;
yield return StartCoroutine(PlayRound(1, CrystalStatue.StatueType.EvilFace,
audioRound1Intro, audioRound1Success));
if (!isPlaying) yield break;
// ========== 第二轮:恶毒双手 ==========
currentRound = 2;
yield return new WaitForSeconds(delayBetweenRounds);
yield return StartCoroutine(PlayRound(2, CrystalStatue.StatueType.EvilHands,
audioRound2Intro, audioRound2Success));
if (!isPlaying) yield break;
// ========== 第三轮:嫉妒之心 ==========
currentRound = 3;
yield return new WaitForSeconds(delayBetweenRounds);
yield return StartCoroutine(PlayRound(3, CrystalStatue.StatueType.JealousHeart,
audioRound3Intro, audioRound3Success));
if (!isPlaying) yield break;
// ========== 完成 ==========
currentState = CrystalEventState.Complete;
currentStep = 10;
if (debugMode)
Debug.Log("[CrystalStatueEvent] ========== 水晶雕像事件完成 ==========");
// 清理雕像
CleanupStatues();
TriggerComplete();
}
///
/// 执行一轮挑战
///
private IEnumerator PlayRound(int round, CrystalStatue.StatueType type,
string introAudio, string successAudio)
{
// 设置状态
SetRoundState(round, CrystalEventState.Round1_Intro, CrystalEventState.Round2_Intro, CrystalEventState.Round3_Intro);
// 生成雕像
SpawnStatuesForRound(round, type);
// 播放介绍语音
PlayAudio2D(introAudio);
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 第{round}轮开始: {type}");
// 等待介绍语音播放完成
yield return StartCoroutine(WaitForAudioComplete(introAudio, 10f));
// 额外等待一小段时间
yield return new WaitForSeconds(0.5f);
// 开始游戏
SetRoundState(round, CrystalEventState.Round1_Playing, CrystalEventState.Round2_Playing, CrystalEventState.Round3_Playing);
// 启动计时器
isRoundActive = true;
isTimeUp = false;
currentRoundTime = roundTimeLimit;
roundTimerCoroutine = StartCoroutine(RoundTimer());
// 等待结果
bool roundComplete = false;
bool roundSuccess = false;
System.Action onRoundEnd = (success) =>
{
roundComplete = true;
roundSuccess = success;
};
// 注册雕像碎裂回调
foreach (var statue in spawnedStatues)
{
statue.OnStatueBroken = (s, isTarget) =>
{
if (isTarget)
{
// 击中目标,成功
onRoundEnd(true);
}
else
{
// 击中非目标,失败
onRoundEnd(false);
}
};
}
// 等待玩家操作
yield return new WaitUntil(() => roundComplete || isTimeUp);
// 停止计时器
if (roundTimerCoroutine != null)
{
StopCoroutine(roundTimerCoroutine);
roundTimerCoroutine = null;
}
isRoundActive = false;
// 处理结果
// 第三轮特殊处理:无论成功失败都结束事件
if (round == 3)
{
if (isTimeUp)
{
// 第三轮超时失败
currentState = CrystalEventState.TimeUp;
yield return StartCoroutine(HandleTimeUp());
yield return StartCoroutine(WaitForAudioComplete(audioFail, 10f));
if (debugMode)
Debug.Log("[CrystalStatueEvent] 第三轮超时失败,结束水晶雕像事件");
}
else if (roundSuccess)
{
// 第三轮成功
currentState = CrystalEventState.Round3_Success;
yield return StartCoroutine(AllStatuesDisappearExcept(null));
PlayAudio2D(successAudio);
PlayAudio2D(audioSuccessEffect);
if (debugMode)
Debug.Log("[CrystalStatueEvent] 第三轮成功! 播放1.11语音");
yield return StartCoroutine(WaitForAudioComplete(successAudio, 10f));
}
else
{
// 第三轮失败(击打错误)
currentState = CrystalEventState.Round3_Fail;
yield return StartCoroutine(HandleFailButContinue());
yield return StartCoroutine(WaitForAudioComplete(audioFail, 10f));
if (debugMode)
Debug.Log("[CrystalStatueEvent] 第三轮失败,播放1.6语音,结束水晶雕像事件");
}
// 第三轮结束,清理雕像并完成事件
CleanupStatues();
currentState = CrystalEventState.Complete;
currentStep = 10;
if (debugMode)
Debug.Log("[CrystalStatueEvent] ========== 水晶雕像事件完成 ==========");
TriggerComplete();
yield break; // 直接结束,不继续后续流程
}
// 第一轮和第二轮的处理
if (isTimeUp)
{
// 超时失败
currentState = CrystalEventState.TimeUp;
yield return StartCoroutine(HandleTimeUp());
// 等待失败语音播放完成后再进入下一轮
yield return StartCoroutine(WaitForAudioComplete(audioFail, 10f));
yield return new WaitForSeconds(0.5f);
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 第{round}轮超时,进入下一轮");
}
else if (roundSuccess)
{
// 成功
SetRoundState(round, CrystalEventState.Round1_Success, CrystalEventState.Round2_Success, CrystalEventState.Round3_Success);
// 所有其他雕像消失
yield return StartCoroutine(AllStatuesDisappearExcept(null));
// 播放成功语音
PlayAudio2D(successAudio);
PlayAudio2D(audioSuccessEffect);
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 第{round}轮成功!");
// 等待成功语音播放完成后再进入下一轮
yield return StartCoroutine(WaitForAudioComplete(successAudio, 10f));
yield return new WaitForSeconds(0.5f);
}
else
{
// 失败(击打错误)- 播放失败提示,但仍进入下一轮
SetRoundState(round, CrystalEventState.Round1_Fail, CrystalEventState.Round2_Fail, CrystalEventState.Round3_Fail);
yield return StartCoroutine(HandleFailButContinue());
// 等待失败语音播放完成后再进入下一轮
yield return StartCoroutine(WaitForAudioComplete(audioFail, 10f));
yield return new WaitForSeconds(0.5f);
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 第{round}轮失败(击打错误),进入下一轮");
}
// 清理雕像
CleanupStatues();
}
///
/// 设置轮次状态
///
private void SetRoundState(int round, CrystalEventState state1, CrystalEventState state2, CrystalEventState state3)
{
switch (round)
{
case 1: currentState = state1; break;
case 2: currentState = state2; break;
case 3: currentState = state3; break;
}
}
#endregion
#region 计时器
private IEnumerator RoundTimer()
{
while (isRoundActive && currentRoundTime > 0)
{
currentRoundTime -= Time.deltaTime;
// 更新UI(如果有)
UpdateTimerUI(currentRoundTime);
yield return null;
}
if (currentRoundTime <= 0)
{
isTimeUp = true;
if (debugMode)
Debug.Log("[CrystalStatueEvent] 时间耗尽!");
}
}
///
/// 等待音频播放完成
///
private IEnumerator WaitForAudioComplete(string audioName, float maxWaitTime = 10f)
{
float elapsedTime = 0f;
// 等待音频开始播放
yield return new WaitForSeconds(0.1f);
while (elapsedTime < maxWaitTime)
{
MasterAudioGroup audioGroup = MasterAudio.GrabGroup(audioName);
if (audioGroup == null || audioGroup.ActiveVoices <= 0)
{
// 音频播放完成
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 音频 {audioName} 播放完成,耗时: {elapsedTime:F1}秒");
yield break;
}
elapsedTime += Time.deltaTime;
yield return null;
}
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 音频 {audioName} 等待超时");
}
///
/// 更新计时器UI(子类可重写)
///
protected virtual void UpdateTimerUI(float remainingTime)
{
// TODO: 更新HUD倒计时显示
// HUDPanel.Ins.UpdateTimer(remainingTime);
}
#endregion
#region 雕像生成
///
/// 为指定轮次生成雕像
///
private void SpawnStatuesForRound(int round, CrystalStatue.StatueType type)
{
CleanupStatues();
// 生成五角星排列的位置
Vector3[] positions = GeneratePentagramPositions(GameLocal.Ins.self.transform.position, statueRadius);
// 随机选择目标位置
int targetIndex = Random.Range(0, statueCount);
for (int i = 0; i < statueCount; i++)
{
Vector3 pos = positions[i];
pos.y = statueHeight;
GameObject statueObj = Instantiate(crystalStatuePrefab, pos, Quaternion.identity);
statueObj.name = $"CrystalStatue_{i}";
// 面向中心
statueObj.transform.LookAt(GameLocal.Ins.self.transform.position);
statueObj.transform.eulerAngles = new Vector3(0, statueObj.transform.eulerAngles.y, 0);
CrystalStatue statue = statueObj.GetComponent();
if (statue == null)
{
statue = statueObj.AddComponent();
}
// 初始化雕像
bool isTarget = (i == targetIndex);
statue.Initialize(type, isTarget);
if (isTarget)
{
targetStatue = statue;
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 目标雕像: 位置{i}");
}
spawnedStatues.Add(statue);
}
if (debugMode)
Debug.Log($"[CrystalStatueEvent] 生成{statueCount}个雕像, 类型: {type}");
}
///
/// 生成五角星排列位置
///
private Vector3[] GeneratePentagramPositions(Vector3 center, float radius)
{
Vector3[] positions = new Vector3[statueCount];
for (int i = 0; i < statueCount; i++)
{
// 五角星角度,从顶部开始
float angle = i * (360f / statueCount) * Mathf.Deg2Rad - 90f * Mathf.Deg2Rad;
positions[i] = center + new Vector3(
Mathf.Cos(angle) * radius,
0,
Mathf.Sin(angle) * radius
);
}
return positions;
}
#endregion
#region 结果处理
///
/// 处理超时
///
private IEnumerator HandleTimeUp()
{
if (debugMode)
Debug.Log("[CrystalStatueEvent] 处理超时失败");
// 所有雕像消失
yield return StartCoroutine(AllStatuesDisappear());
// 播放失败语音
PlayAudio2D(audioFail);
}
///
/// 处理失败
///
private IEnumerator HandleFail()
{
if (debugMode)
Debug.Log("[CrystalStatueEvent] 处理失败");
// 所有雕像狞笑
foreach (var statue in spawnedStatues)
{
if (!statue.IsBroken())
{
statue.PlayEvilLaugh();
}
}
// 播放狞笑音效
PlayAudio2D(audioEvilLaugh);
yield return new WaitForSeconds(1f);
// 所有雕像消失
yield return StartCoroutine(AllStatuesDisappear());
// 播放失败语音
PlayAudio2D(audioFail);
}
///
/// 处理失败但继续进入下一轮
///
private IEnumerator HandleFailButContinue()
{
if (debugMode)
Debug.Log("[CrystalStatueEvent] 处理失败(继续下一轮)");
// 所有雕像狞笑
foreach (var statue in spawnedStatues)
{
if (!statue.IsBroken())
{
statue.PlayEvilLaugh();
}
}
// 播放狞笑音效
PlayAudio2D(audioEvilLaugh);
yield return new WaitForSeconds(1f);
// 所有雕像消失
yield return StartCoroutine(AllStatuesDisappear());
// 播放失败提示语音
PlayAudio2D(audioFail);
}
///
/// 所有雕像消失
///
private IEnumerator AllStatuesDisappear()
{
foreach (var statue in spawnedStatues)
{
if (!statue.IsBroken())
{
statue.ForceDisappear(0.5f);
}
}
yield return new WaitForSeconds(0.6f);
}
///
/// 除指定雕像外所有雕像消失
///
private IEnumerator AllStatuesDisappearExcept(CrystalStatue exception)
{
foreach (var statue in spawnedStatues)
{
if (statue != exception && !statue.IsBroken())
{
statue.ForceDisappear(0.5f);
}
}
yield return new WaitForSeconds(0.6f);
}
#endregion
#region 清理
///
/// 清理所有雕像
///
private void CleanupStatues()
{
foreach (var statue in spawnedStatues)
{
if (statue != null)
{
Destroy(statue.gameObject);
}
}
spawnedStatues.Clear();
targetStatue = null;
}
public override void Cleanup()
{
CleanupStatues();
if (crystalWorldEnvironment != null)
crystalWorldEnvironment.SetActive(false);
// 退出雕像事件模式,恢复道具
if (GameManager.Ins.playerRightHand != null)
{
GameManager.Ins.playerRightHand.ExitStatueEventMode();
}
base.Cleanup();
}
#endregion
#region 编辑器辅助
#if UNITY_EDITOR
[ContextMenu("开始事件")]
private void TestStartEvent()
{
StartCutscene();
}
[ContextMenu("停止事件")]
private void TestStopEvent()
{
StopCutscene();
}
[ContextMenu("清理雕像")]
private void TestCleanup()
{
CleanupStatues();
}
[ContextMenu("测试:生成第一轮雕像")]
private void TestSpawnRound1()
{
SpawnStatuesForRound(1, CrystalStatue.StatueType.EvilFace);
}
[ContextMenu("测试:生成第二轮雕像")]
private void TestSpawnRound2()
{
SpawnStatuesForRound(2, CrystalStatue.StatueType.EvilHands);
}
[ContextMenu("测试:生成第三轮雕像")]
private void TestSpawnRound3()
{
SpawnStatuesForRound(3, CrystalStatue.StatueType.JealousHeart);
}
#endif
#endregion
}