ZhangZhouSpecialEquipment/Assets/Scripts/SBFJ/ThreeDModelFunctions.cs

174 lines
5.0 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 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);
}
}
}
}