276 lines
8.0 KiB
C#
276 lines
8.0 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using DG.Tweening;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// 石像拼凑器 - 管理石像碎片的显示和拼凑动画
|
||
/// </summary>
|
||
public class StatueAssembler : MonoBehaviour
|
||
{
|
||
[Header("石像配置")]
|
||
public int statueIndex; // 石像序号
|
||
public string statueName; // 石像名称
|
||
|
||
[Header("碎片配置")]
|
||
public int totalFragments = 10; // 总碎片数
|
||
public GameObject[] fragmentMeshes; // 10个碎片模型(按顺序)
|
||
|
||
[Header("材质配置")]
|
||
public Material grayMaterial; // 未激活时的灰色材质
|
||
public Material colorMaterial; // 完成后的彩色材质
|
||
public float materialTransitionDuration = 1f; // 材质过渡时间
|
||
|
||
[Header("完成特效")]
|
||
public ParticleSystem completeEffect; // 完成特效
|
||
public GameObject glowEffect; // 发光效果
|
||
public Light completeLight; // 完成时光照
|
||
public float lightIntensity = 2f; // 光照强度
|
||
|
||
[Header("动画配置")]
|
||
public float fragmentAppearDelay = 0.1f; // 碎片出现间隔
|
||
public float assembleShakeAmount = 0.1f; // 拼凑完成时的震动幅度
|
||
|
||
// 私有变量
|
||
private HashSet<int> collectedFragments = new HashSet<int>();
|
||
private bool isCompleted = false;
|
||
private List<MeshRenderer> fragmentRenderers = new List<MeshRenderer>();
|
||
|
||
public event Action<int> OnStatueCompleted; // 石像完成事件
|
||
|
||
private void Awake()
|
||
{
|
||
InitializeFragments();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化碎片
|
||
/// </summary>
|
||
private void InitializeFragments()
|
||
{
|
||
// 确保所有碎片初始隐藏
|
||
for (int i = 0; i < fragmentMeshes.Length; i++)
|
||
{
|
||
if (fragmentMeshes[i] != null)
|
||
{
|
||
fragmentMeshes[i].SetActive(false);
|
||
|
||
// 获取渲染器并设置灰色材质
|
||
MeshRenderer renderer = fragmentMeshes[i].GetComponent<MeshRenderer>();
|
||
if (renderer != null)
|
||
{
|
||
fragmentRenderers.Add(renderer);
|
||
if (grayMaterial != null)
|
||
renderer.material = grayMaterial;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 关闭完成特效
|
||
if (completeEffect != null)
|
||
completeEffect.gameObject.SetActive(false);
|
||
if (glowEffect != null)
|
||
glowEffect.SetActive(false);
|
||
if (completeLight != null)
|
||
completeLight.enabled = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加碎片
|
||
/// </summary>
|
||
public void AddFragment(int fragmentIndex)
|
||
{
|
||
if (isCompleted) return;
|
||
if (collectedFragments.Contains(fragmentIndex)) return;
|
||
|
||
// 计算在这个石像中的本地碎片序号
|
||
int localIndex = fragmentIndex % totalFragments;
|
||
|
||
collectedFragments.Add(fragmentIndex);
|
||
|
||
// 显示对应碎片
|
||
ShowFragment(localIndex);
|
||
|
||
// 检查是否完成
|
||
CheckCompletion();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示单个碎片
|
||
/// </summary>
|
||
private void ShowFragment(int localIndex)
|
||
{
|
||
if (localIndex < 0 || localIndex >= fragmentMeshes.Length) return;
|
||
|
||
GameObject fragment = fragmentMeshes[localIndex];
|
||
if (fragment == null) return;
|
||
|
||
// 激活碎片
|
||
fragment.SetActive(true);
|
||
|
||
// 从缩放0开始的弹出动画
|
||
fragment.transform.localScale = Vector3.zero;
|
||
fragment.transform.DOScale(Vector3.one, 0.3f)
|
||
.SetEase(Ease.OutBack);
|
||
|
||
// 轻微旋转动画
|
||
fragment.transform.DORotate(new Vector3(0, 360, 0), 0.5f, RotateMode.LocalAxisAdd)
|
||
.SetEase(Ease.OutQuad);
|
||
|
||
// 添加发光效果
|
||
MeshRenderer renderer = fragment.GetComponent<MeshRenderer>();
|
||
if (renderer != null && grayMaterial != null)
|
||
{
|
||
renderer.material = grayMaterial;
|
||
// 可以添加闪烁效果
|
||
renderer.material.DOFloat(1.5f, "_EmissionIntensity", 0.3f)
|
||
.SetLoops(2, LoopType.Yoyo);
|
||
}
|
||
GameManager.Ins.PlaySound3D("雕像碎片堆叠音效",transform);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否完成
|
||
/// </summary>
|
||
private void CheckCompletion()
|
||
{
|
||
if (collectedFragments.Count >= totalFragments)
|
||
{
|
||
CompleteStatue();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 完成石像
|
||
/// </summary>
|
||
private void CompleteStatue()
|
||
{
|
||
if (isCompleted) return;
|
||
isCompleted = true;
|
||
|
||
Debug.Log($"[StatueAssembler] {statueName} 拼凑完成!");
|
||
|
||
// 播放完成动画
|
||
PlayCompleteAnimation();
|
||
|
||
// 触发事件
|
||
OnStatueCompleted?.Invoke(statueIndex);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 播放完成动画
|
||
/// </summary>
|
||
private void PlayCompleteAnimation()
|
||
{
|
||
// 1. 震动效果
|
||
transform.DOShakePosition(0.5f, assembleShakeAmount, 10, 90);
|
||
|
||
// 2. 所有碎片变色
|
||
foreach (var renderer in fragmentRenderers)
|
||
{
|
||
if (renderer != null && colorMaterial != null)
|
||
{
|
||
// 材质渐变
|
||
Material targetMat = new Material(colorMaterial);
|
||
renderer.material = targetMat;
|
||
|
||
// 发光强度动画
|
||
targetMat.SetFloat("_EmissionIntensity", 0);
|
||
targetMat.DOFloat(2f, "_EmissionIntensity", materialTransitionDuration)
|
||
.SetEase(Ease.OutQuad);
|
||
}
|
||
}
|
||
|
||
// 3. 整体缩放动画
|
||
transform.DOScale(transform.localScale * 1.1f, 0.2f)
|
||
.SetEase(Ease.OutQuad)
|
||
.OnComplete(() =>
|
||
{
|
||
transform.DOScale(transform.localScale / 1.1f, 0.3f)
|
||
.SetEase(Ease.InOutQuad);
|
||
});
|
||
|
||
// 4. 播放粒子特效
|
||
if (completeEffect != null)
|
||
{
|
||
completeEffect.gameObject.SetActive(true);
|
||
completeEffect.Play();
|
||
}
|
||
|
||
// 5. 发光效果
|
||
if (glowEffect != null)
|
||
{
|
||
glowEffect.SetActive(true);
|
||
glowEffect.transform.localScale = Vector3.zero;
|
||
glowEffect.transform.DOScale(Vector3.one, 0.5f)
|
||
.SetEase(Ease.OutBack);
|
||
}
|
||
|
||
// 6. 光照效果
|
||
if (completeLight != null)
|
||
{
|
||
completeLight.enabled = true;
|
||
completeLight.intensity = 0;
|
||
DOTween.To(() => completeLight.intensity, x => completeLight.intensity = x, lightIntensity, 0.5f)
|
||
.SetEase(Ease.OutQuad);
|
||
}
|
||
|
||
// 7. 播放音效
|
||
GameManager.Ins?.PlaySound3D("雕像堆叠成功", transform,true);
|
||
|
||
// 8. 延迟后持续特效
|
||
DOVirtual.DelayedCall(1f, () =>
|
||
{
|
||
// 持续的微弱发光动画
|
||
if (glowEffect != null)
|
||
{
|
||
glowEffect.transform.DOScale(Vector3.one * 1.2f, 2f)
|
||
.SetLoops(-1, LoopType.Yoyo)
|
||
.SetEase(Ease.InOutSine);
|
||
}
|
||
GetCoin();
|
||
});
|
||
}
|
||
|
||
public void GetCoin()
|
||
{
|
||
GameObject pileGO = Instantiate(
|
||
GameManager.Ins.coinPilePre,
|
||
transform.position,
|
||
Quaternion.identity
|
||
);
|
||
|
||
pileGO.GetComponent<CoinPileController>()
|
||
.Init(
|
||
GameInit.Ins.self.RightHand,
|
||
10
|
||
);
|
||
GameInit.Ins.self.AddCoin(500);
|
||
GameInit.Ins.self.AddScore(500);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取收集进度
|
||
/// </summary>
|
||
public int GetProgress()
|
||
{
|
||
return collectedFragments.Count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 是否已完成
|
||
/// </summary>
|
||
public bool IsCompleted()
|
||
{
|
||
return isCompleted;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取碎片收集状态
|
||
/// </summary>
|
||
public bool HasFragment(int fragmentIndex)
|
||
{
|
||
return collectedFragments.Contains(fragmentIndex);
|
||
}
|
||
}
|