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 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); } /// /// 初始化函数 /// public void Init() { foreach (GameObject CanvasObj in AllCanvas) CanvasObj.SetActive(false); childMeshRenderers = new List(); foreach (var item in GetComponentsInChildren()) { 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(); } /// /// 切换展开视图(由 Q 键触发) /// public void ToggleExplodedView() { isInExplodedView = !isInExplodedView; isMoving = true; // 展开时先隐藏 Canvas if (isInExplodedView) { foreach (GameObject CanvasObj in AllCanvas) CanvasObj.SetActive(false); } } /// /// 当滑动条值改变时调用(实时控制) /// public void OnSliderValueChanged(float value) { explosionFactor = value; // 如果是手动滑动,就认为是用户控制状态 isInExplodedView = explosionFactor >= 0.5f; isMoving = false; UpdateCanvasState(); } /// /// 控制 Canvas 显示/隐藏与浮动 /// 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(); 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); } } } }