174 lines
5.0 KiB
C#
174 lines
5.0 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using TMPro;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
|
||
// 定义一个可序列化的子网格类
|
||
[Serializable]
|
||
public class SubMeshes
|
||
{
|
||
// 网格渲染器
|
||
public MeshRenderer meshRenderer;
|
||
// 原始位置
|
||
public Vector3 originalPosition;
|
||
// 展开后的位置
|
||
public Vector3 explodedPosition;
|
||
}
|
||
|
||
// 定义一个三维模型功能类,继承自MonoBehaviour
|
||
public class ThreeDModelFunctions : MonoBehaviour
|
||
{
|
||
public static ThreeDModelFunctions Instance;
|
||
public Material m;
|
||
public Camera MainCamera;
|
||
|
||
#region Variables
|
||
public List<SubMeshes> childMeshRenderers;
|
||
public bool isInExplodedView = false; // 当前是否在爆炸视图
|
||
public bool isMoving = false; // 是否正在动画中
|
||
public float explosionSpeed = 0.1f; // 移动插值速度
|
||
#endregion
|
||
|
||
[Header("Canvas 管理")]
|
||
public GameObject[] AllCanvas;
|
||
|
||
[Header("UI 控制")]
|
||
public Slider explosionSlider;
|
||
|
||
// 当前爆炸程度 (0~1)
|
||
[Range(0, 1)]
|
||
public float explosionFactor = 0f;
|
||
|
||
private void Awake()
|
||
{
|
||
Instance = this;
|
||
Init();
|
||
|
||
// 注册滑动条事件
|
||
if (explosionSlider != null)
|
||
explosionSlider.onValueChanged.AddListener(OnSliderValueChanged);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化函数
|
||
/// </summary>
|
||
public void Init()
|
||
{
|
||
foreach (GameObject CanvasObj in AllCanvas)
|
||
CanvasObj.SetActive(false);
|
||
|
||
childMeshRenderers = new List<SubMeshes>();
|
||
|
||
foreach (var item in GetComponentsInChildren<MeshRenderer>())
|
||
{
|
||
SubMeshes mesh = new SubMeshes();
|
||
mesh.meshRenderer = item;
|
||
mesh.originalPosition = item.transform.position;
|
||
// 设置展开后位置(原逻辑保留)
|
||
Vector3 vector3 = Math.Abs(item.bounds.center.x) > 4 ? item.bounds.center * 1.5f : item.bounds.center * 5f;
|
||
mesh.explodedPosition = vector3;
|
||
|
||
childMeshRenderers.Add(mesh);
|
||
}
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
// Q键触发自动展开/收起动画
|
||
if (Input.GetKeyDown(KeyCode.Q))
|
||
{
|
||
ToggleExplodedView();
|
||
// 同步滑动条初值
|
||
if (explosionSlider != null)
|
||
explosionSlider.value = isInExplodedView ? 1f : 0f;
|
||
}
|
||
|
||
// 如果正在移动,执行动画过渡
|
||
if (isMoving)
|
||
{
|
||
float target = isInExplodedView ? 1f : 0f;
|
||
// 插值控制 explosionFactor
|
||
explosionFactor = Mathf.Lerp(explosionFactor, target, Time.deltaTime * 2f);
|
||
|
||
// 当接近目标值时,停止动画
|
||
if (Mathf.Abs(explosionFactor - target) < 0.01f)
|
||
{
|
||
explosionFactor = target;
|
||
isMoving = false;
|
||
}
|
||
|
||
if (explosionSlider != null)
|
||
explosionSlider.value = explosionFactor;
|
||
}
|
||
|
||
// 根据 explosionFactor 计算每个子物体位置
|
||
foreach (var item in childMeshRenderers)
|
||
{
|
||
Vector3 target = Vector3.Lerp(item.originalPosition, item.explodedPosition, explosionFactor);
|
||
item.meshRenderer.transform.position = Vector3.Lerp(item.meshRenderer.transform.position, target, explosionSpeed);
|
||
}
|
||
|
||
// 控制 Canvas 状态
|
||
UpdateCanvasState();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换展开视图(由 Q 键触发)
|
||
/// </summary>
|
||
public void ToggleExplodedView()
|
||
{
|
||
isInExplodedView = !isInExplodedView;
|
||
isMoving = true;
|
||
|
||
// 展开时先隐藏 Canvas
|
||
if (isInExplodedView)
|
||
{
|
||
foreach (GameObject CanvasObj in AllCanvas)
|
||
CanvasObj.SetActive(false);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当滑动条值改变时调用(实时控制)
|
||
/// </summary>
|
||
public void OnSliderValueChanged(float value)
|
||
{
|
||
explosionFactor = value;
|
||
|
||
// 如果是手动滑动,就认为是用户控制状态
|
||
isInExplodedView = explosionFactor >= 0.5f;
|
||
isMoving = false;
|
||
|
||
UpdateCanvasState();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 控制 Canvas 显示/隐藏与浮动
|
||
/// </summary>
|
||
private void UpdateCanvasState()
|
||
{
|
||
// 当爆炸程度大于 0.8 时显示 Canvas,否则隐藏
|
||
bool shouldShow = explosionFactor > 0.8f;
|
||
|
||
foreach (GameObject CanvasObj in AllCanvas)
|
||
{
|
||
if (CanvasObj.activeSelf != shouldShow)
|
||
{
|
||
CanvasObj.SetActive(shouldShow);
|
||
|
||
TextMeshProUGUI name = CanvasObj.GetComponentInChildren<TextMeshProUGUI>();
|
||
if (name != null)
|
||
name.text = CanvasObj.name;
|
||
|
||
// 上下浮动动画
|
||
Vector3 pos = CanvasObj.transform.position;
|
||
if (shouldShow)
|
||
CanvasObj.transform.position = new Vector3(pos.x, pos.y + 1f, pos.z);
|
||
else
|
||
CanvasObj.transform.position = new Vector3(pos.x, pos.y - 1f, pos.z);
|
||
}
|
||
}
|
||
}
|
||
}
|