Files
MRSnowWhite/Assets/_SnowWhite/Scripts/Cutscene/Mirror.cs

499 lines
13 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 BehaviorDesigner.Runtime;
using DG.Tweening;
using DarkTonic.MasterAudio;
using DragonLi.Core;
/// <summary>
/// 魔镜控制器 - 挂载到魔镜预制体上
/// 配合行为树使用,控制魔镜的动画、音频、移动和传送门变换
/// </summary>
public class Mirror : MonoBehaviour
{
[Header("组件引用")]
public Animator animator;
public AudioSource audioSource;
public Renderer mirrorRenderer;
public ParticleSystem portalParticles;
public GameObject portalEffect;
[Header("行为树")]
public BehaviorTree behaviorTree;
[Header("动画参数")]
public string talkAnimParam = "Talk";
public string idleAnimParam = "Idle";
public string transformAnimParam = "Transform";
[Header("移动配置")]
public float flyToPlayerDistance = 2f;
public float moveSpeed = 3f;
[Header("传送门配置")]
public Color portalGlowColor = new Color(0.5f, 0.8f, 1f, 1f);
public float portalTransformDuration = 2f;
[Header("调试模式")]
public bool debugMode = true;
// 私有变量
private Material mirrorMaterial;
private Color originalColor;
private Tweener currentTween;
// 状态
public enum MirrorState
{
Idle,
Talking,
FlyingToPlayer,
Transforming,
Portal,
Disappeared
}
public MirrorState currentState = MirrorState.Idle;
private void Awake()
{
if (animator == null)
animator = GetComponent<Animator>();
if (audioSource == null)
audioSource = GetComponent<AudioSource>();
if (behaviorTree == null)
behaviorTree = GetComponent<BehaviorTree>();
if (mirrorRenderer != null)
{
mirrorMaterial = mirrorRenderer.material;
originalColor = mirrorMaterial.HasProperty("_Color") ? mirrorMaterial.color : Color.white;
}
}
private void Start()
{
currentState = MirrorState.Idle;
// 初始隐藏传送门效果
if (portalEffect != null)
portalEffect.SetActive(false);
if (portalParticles != null)
portalParticles.Stop();
}
/// <summary>
/// 播放动画
/// </summary>
public void PlayAnimation(string animParam)
{
if (animator != null && !string.IsNullOrEmpty(animParam))
{
animator.SetTrigger(animParam);
if (debugMode)
Debug.Log($"[Mirror] 播放动画: {animParam}");
}
}
/// <summary>
/// 播放说话动画
/// </summary>
public void PlayTalkAnim()
{
currentState = MirrorState.Talking;
PlayAnimation(talkAnimParam);
}
/// <summary>
/// 播放待机动画
/// </summary>
public void PlayIdleAnim()
{
currentState = MirrorState.Idle;
PlayAnimation(idleAnimParam);
}
/// <summary>
/// 播放变换动画
/// </summary>
public void PlayTransformAnim()
{
PlayAnimation(transformAnimParam);
}
/// <summary>
/// 播放音频通过MasterAudio
/// </summary>
public void PlayAudio(string audioName)
{
if (!string.IsNullOrEmpty(audioName))
{
MasterAudio.PlaySound3DAtTransform(audioName, transform);
if (debugMode)
Debug.Log($"[Mirror] 播放音频: {audioName}");
}
}
/// <summary>
/// 停止当前音频
/// </summary>
public void StopAudio()
{
MasterAudio.StopAllSoundsOfTransform(transform);
}
/// <summary>
/// 转向玩家
/// </summary>
public void TurnToPlayer(float duration = 1f)
{
if (GameLocal.Ins == null || GameLocal.Ins.self == null)
{
Debug.LogWarning("[Mirror] 无法找到玩家");
return;
}
Transform playerTransform = GameLocal.Ins.self.transform;
Vector3 direction = playerTransform.position - transform.position;
direction.y = 0;
if (direction != Vector3.zero)
{
Quaternion targetRotation = Quaternion.LookRotation(direction);
if (currentTween != null)
currentTween.Kill();
currentTween = transform.DORotateQuaternion(targetRotation, duration);
if (debugMode)
Debug.Log("[Mirror] 转向玩家");
}
}
/// <summary>
/// 飞向玩家
/// </summary>
public void FlyToPlayer(float duration = 2f, System.Action onComplete = null)
{
if (GameLocal.Ins == null || GameLocal.Ins.self == null)
{
Debug.LogWarning("[Mirror] 无法找到玩家");
onComplete?.Invoke();
return;
}
currentState = MirrorState.FlyingToPlayer;
Transform playerTransform = GameLocal.Ins.self.transform;
// 计算目标位置(玩家前方)
Vector3 targetPos = playerTransform.position + playerTransform.forward * flyToPlayerDistance;
targetPos.y = transform.position.y;
if (currentTween != null)
currentTween.Kill();
Sequence sequence = DOTween.Sequence();
sequence.Join(transform.DOMove(targetPos, duration).SetEase(Ease.OutQuad));
sequence.Join(transform.DOLookAt(playerTransform.position, duration * 0.5f));
sequence.OnComplete(() =>
{
currentState = MirrorState.Idle;
onComplete?.Invoke();
if (debugMode)
Debug.Log("[Mirror] 飞向玩家完成");
});
}
/// <summary>
/// 变换为传送门
/// </summary>
public void TransformToPortal(float duration = 2f, System.Action onComplete = null)
{
currentState = MirrorState.Transforming;
// 播放变换动画
PlayTransformAnim();
// 播放粒子效果
if (portalParticles != null)
portalParticles.Play();
// 发光效果
if (mirrorMaterial != null)
{
float elapsedTime = 0f;
DOTween.To(
() => 0f,
t =>
{
if (mirrorMaterial.HasProperty("_Color"))
{
mirrorMaterial.color = Color.Lerp(originalColor, portalGlowColor, t);
}
if (mirrorMaterial.HasProperty("_EmissionColor"))
{
float intensity = Mathf.Lerp(0f, 2f, t);
mirrorMaterial.SetColor("_EmissionColor", portalGlowColor * intensity);
}
},
1f,
duration
).OnComplete(() =>
{
currentState = MirrorState.Portal;
// 显示传送门效果
if (portalEffect != null)
portalEffect.SetActive(true);
onComplete?.Invoke();
if (debugMode)
Debug.Log("[Mirror] 传送门变换完成");
});
}
else
{
currentState = MirrorState.Portal;
onComplete?.Invoke();
}
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
FadeOut(2, () =>
{
GameManager.Ins.StartCutscene(1);
});
}, 2f);
}
/// <summary>
/// 发光效果
/// </summary>
public void Glow(float intensity = 1f, float duration = 1f)
{
if (mirrorMaterial != null && mirrorMaterial.HasProperty("_EmissionColor"))
{
DOTween.To(
() => mirrorMaterial.GetColor("_EmissionColor").r,
x => mirrorMaterial.SetColor("_EmissionColor", portalGlowColor * x),
intensity,
duration
);
}
}
/// <summary>
/// 渐隐消失
/// </summary>
public void FadeOut(float duration = 1f, System.Action onComplete = null)
{
var renderers = GetComponentsInChildren<Renderer>();
if (renderers.Length > 0)
{
DOTween.To(
() => 1f,
alpha =>
{
foreach (var renderer in renderers)
{
var mat = renderer.material;
if (mat.HasProperty("_Color"))
{
Color color = mat.color;
color.a = alpha;
mat.color = color;
}
}
},
0f,
duration
).OnComplete(() =>
{
currentState = MirrorState.Disappeared;
gameObject.SetActive(false);
onComplete?.Invoke();
if (debugMode)
Debug.Log("[Mirror] 渐隐消失完成");
});
}
else
{
currentState = MirrorState.Disappeared;
gameObject.SetActive(false);
onComplete?.Invoke();
}
}
/// <summary>
/// 缩放消失
/// </summary>
public void ScaleAndDisappear(float duration = 0.5f, System.Action onComplete = null)
{
if (currentTween != null)
currentTween.Kill();
transform.DOScale(Vector3.zero, duration)
.SetEase(Ease.InBack)
.OnComplete(() =>
{
currentState = MirrorState.Disappeared;
gameObject.SetActive(false);
onComplete?.Invoke();
if (debugMode)
Debug.Log("[Mirror] 缩放消失完成");
});
}
/// <summary>
/// 移动到指定位置
/// </summary>
public void MoveTo(Vector3 targetPos, float duration = 2f, System.Action onComplete = null)
{
if (currentTween != null)
currentTween.Kill();
currentTween = transform.DOMove(targetPos, duration)
.SetEase(Ease.OutQuad)
.OnComplete(() =>
{
onComplete?.Invoke();
if (debugMode)
Debug.Log($"[Mirror] 移动完成到: {targetPos}");
});
}
/// <summary>
/// 停止所有动作
/// </summary>
public void StopAllActions()
{
if (currentTween != null)
currentTween.Kill();
//StopAudio();
if (portalParticles != null && portalParticles.isPlaying)
portalParticles.Stop();
}
/// <summary>
/// 初始化魔镜
/// </summary>
public void Init()
{
currentState = MirrorState.Idle;
// 重置材质
if (mirrorMaterial != null && mirrorMaterial.HasProperty("_Color"))
{
mirrorMaterial.color = originalColor;
}
// 重置缩放
transform.localScale = Vector3.one;
// 隐藏传送门效果
if (portalEffect != null)
portalEffect.SetActive(false);
if (portalParticles != null)
portalParticles.Stop();
// 显示魔镜
gameObject.SetActive(true);
if (debugMode)
Debug.Log("[Mirror] 初始化完成");
}
/// <summary>
/// 启动行为树
/// </summary>
public void StartBehaviorTree()
{
if (behaviorTree != null)
{
behaviorTree.EnableBehavior();
if (debugMode)
Debug.Log("[Mirror] 启动行为树");
}
}
/// <summary>
/// 停止行为树
/// </summary>
public void StopBehaviorTree()
{
if (behaviorTree != null)
{
behaviorTree.DisableBehavior();
}
}
private void OnDestroy()
{
StopAllActions();
}
#region
#if UNITY_EDITOR
[ContextMenu("测试:播放说话动画")]
private void TestPlayTalkAnim()
{
PlayTalkAnim();
}
[ContextMenu("测试:转向玩家")]
private void TestTurnToPlayer()
{
TurnToPlayer();
}
[ContextMenu("测试:飞向玩家")]
private void TestFlyToPlayer()
{
FlyToPlayer();
}
[ContextMenu("测试:变换为传送门")]
private void TestTransformToPortal()
{
TransformToPortal();
}
[ContextMenu("测试:缩放消失")]
private void TestScaleAndDisappear()
{
ScaleAndDisappear();
}
[ContextMenu("测试:渐隐消失")]
private void TestFadeOut()
{
FadeOut();
}
[ContextMenu("测试:发光效果")]
private void TestGlow()
{
Glow(2f, 1f);
}
#endif
#endregion
}