using TMPro; using Unity.VisualScripting; using UnityEngine; using UnityEngine.UI; using static UnityEngine.GraphicsBuffer; public class FuTiBaoZhang : MonoBehaviour { public static FuTiBaoZhang Instance; //是否开始爆发 public bool IsStartBao = false; private Animator animator; private AnimationClip clip; [Header("UI 控制")] public Slider explosionSlider; // 当前爆炸程度 (0~1) [Range(0, 1)] public float explosionFactor = 0f; //是否手动介入 private bool m_isPlayChange=false; private bool m_isSliderChange = false; public float HuanYuanSpeed = 0f; [Header("Canvas 管理")] public GameObject[] AllCanvas; [Header("旋转设置")] [Tooltip("旋转灵敏度")] public float rotationSensitivityX = 3f; public float rotationSensitivityY = 3f; [Tooltip("垂直旋转限制 - 最小角度")] public float minVerticalAngle = -60f; [Tooltip("垂直旋转限制 - 最大角度")] public float maxVerticalAngle = 60f; [Tooltip("旋转平滑度")] public float rotationSmoothness = 10f; [Header("缩放设置")] [Tooltip("缩放灵敏度")] public float scaleSensitivity = 0.1f; [Tooltip("最小缩放比例")] public Vector3 minScale = new Vector3(0.5f, 0.5f, 0.5f); [Tooltip("最大缩放比例")] public Vector3 maxScale = new Vector3(3f, 3f, 3f); [Tooltip("缩放平滑度")] public float scaleSmoothness = 10f; [Tooltip("重置动画的平滑度")] public float resetSmoothness = 15f; // 初始状态变量 private Vector3 initialPosition; private Quaternion initialRotation; private Vector3 initialScale; // 当前目标状态变量 private Vector3 targetScale; private float currentXRotation; private float currentYRotation; private float targetXRotation; private float targetYRotation; private Vector3 targetPosition; private void Awake() { Instance = this; foreach (GameObject CanvasObj in AllCanvas) CanvasObj.SetActive(false); // 注册滑动条事件 if (explosionSlider != null) explosionSlider.onValueChanged.AddListener(OnSliderValueChanged); } void Start() { // 获取Animator组件(确保挂载在目标物体上) animator = GetComponent(); clip= GetCurrentAnimationClip(animator); animator.speed = 0; // 保存初始状态 initialPosition = transform.localPosition; initialRotation = transform.localRotation; initialScale = transform.localScale; // 初始化当前状态为初始状态 targetPosition = initialPosition; Vector3 initialRotationAngles = initialRotation.eulerAngles; currentXRotation = targetXRotation = initialRotationAngles.y; currentYRotation = targetYRotation = initialRotationAngles.x; targetScale = initialScale; } private void Update() { if(IsStartBao) { if (Input.GetMouseButton(0)) { if (m_isSliderChange) { m_isPlayChange = true; } } else { m_isSliderChange= false; } if (Input.GetMouseButtonUp(0) && m_isPlayChange) { m_isPlayChange = false; } //在没有手动介入的情况下,进度条数值跟随模型动画改变 if (!m_isPlayChange) { // 获取当前动画状态信息 AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0); float animtime= Mathf.Clamp(stateInfo.normalizedTime, 0, 1); // 获取当前动画的归一化时间,即已播放百分比 if (explosionFactor!= animtime) { explosionFactor = animtime; explosionSlider.value = explosionFactor; } } else { //有手动介入的情况下,模型动画跟随进度条数值改变 if(explosionFactor != explosionSlider.value) { explosionFactor = explosionSlider.value; JumpToTime(explosionFactor); } } } else { if(explosionFactor>0) { explosionFactor -= HuanYuanSpeed; explosionSlider.value = explosionFactor; JumpToTime(explosionFactor); } } } void LateUpdate() { // 处理旋转和缩放输入 if (FuTiManager.Instance.IsCanMove) // 重置时忽略其他输入 { HandleRotationInput(); HandleScaleInput(); } // 应用平滑变换 ApplySmoothRotation(); ApplySmoothScaling(); ApplySmoothPosition(); } /// /// 重置物体到初始状态(位置、旋转、缩放) /// public void ResetToInitialState() { // 设置目标状态为初始状态 targetPosition = initialPosition; targetScale = initialScale; Vector3 initialRotationAngles = initialRotation.eulerAngles; targetXRotation = initialRotationAngles.y; targetYRotation = initialRotationAngles.x; } void HandleRotationInput() { // 当按住指定的鼠标按钮时处理旋转 if (Input.GetMouseButton(1)) { float mouseX = Input.GetAxis("Mouse X") * rotationSensitivityX; float mouseY = Input.GetAxis("Mouse Y") * rotationSensitivityY; targetXRotation += mouseX; targetYRotation -= mouseY; // 限制垂直旋转角度 targetYRotation = Mathf.Clamp(targetYRotation, minVerticalAngle, maxVerticalAngle); } } void HandleScaleInput() { //if (useMouseWheelForScale) //{ float scrollInput = Input.GetAxis("Mouse ScrollWheel"); if (scrollInput != 0) { Vector3 scaleChange = Vector3.one * (scrollInput > 0 ? 1 : -1) * scaleSensitivity; Vector3 newScale = targetScale + scaleChange; targetScale = new Vector3( Mathf.Clamp(newScale.x, minScale.x, maxScale.x), Mathf.Clamp(newScale.y, minScale.y, maxScale.y), Mathf.Clamp(newScale.z, minScale.z, maxScale.z) ); } //} //else //{ // // 备选方案:使用左右键同时按下缩放(如果不使用滚轮) // if (Input.GetMouseButton(0) && Input.GetMouseButton(1)) // { // float mouseY = Input.GetAxis("Mouse Y") * scaleSensitivity; // Vector3 newScale = targetScale + Vector3.one * (mouseY > 0 ? 1 : -1) * scaleSensitivity; // targetScale = new Vector3( // Mathf.Clamp(newScale.x, minScale.x, maxScale.x), // Mathf.Clamp(newScale.y, minScale.y, maxScale.y), // Mathf.Clamp(newScale.z, minScale.z, maxScale.z) // ); // } //} } void ApplySmoothRotation() { currentXRotation = Mathf.Lerp(currentXRotation, targetXRotation, rotationSmoothness* Time.deltaTime); currentYRotation = Mathf.Lerp(currentYRotation, targetYRotation, rotationSmoothness * Time.deltaTime); transform.localRotation = Quaternion.Euler(currentYRotation, currentXRotation, 0); } void ApplySmoothScaling() { transform.localScale = Vector3.Lerp( transform.localScale, targetScale, scaleSmoothness * Time.deltaTime ); } void ApplySmoothPosition() { // 处理位置平滑过渡(主要用于重置时) transform.localPosition = Vector3.Lerp( transform.localPosition, targetPosition, resetSmoothness * Time.deltaTime ); } /// /// 动画开始正常播放 /// public void StartPlayAnim() { if (animator != null) { IsStartBao = true; animator.Play(clip.name, -1, explosionFactor); animator.speed = 1; } } /// /// 动画结束 /// public void EndPlayAnim() { if(animator != null) { IsStartBao=false; } } /// /// 让当前动画跳转到指定时间(秒) /// /// 目标时间比 public void JumpToTime(float timepercent) { if (animator == null) return; if (clip == null) { Debug.LogError("未找到当前播放的动画片段!"); return; } // 2. 检查目标时间是否在动画长度范围内(循环动画可忽略) if (timepercent < 0 || timepercent > 1) { Debug.LogWarning("目标时间超出动画长度!"); timepercent = Mathf.Clamp(timepercent, 0, 1); } // 3. 跳转到目标时间(通过Play方法强制设置归一化时间) // 注意:需传入当前动画状态的名称(或哈希值),确保精准控制 animator.Play(clip.name, -1, timepercent); // 可选:若需要暂停在目标时间,可设置speed为0 animator.speed = 0; } /// /// 获取当前层正在播放的AnimationClip /// private AnimationClip GetCurrentAnimationClip(Animator anim) { AnimationClip[] animationClips = anim.runtimeAnimatorController.animationClips; return animationClips[0]; } /// /// 当滑动条值改变时调用(实时控制) /// public void OnSliderValueChanged(float value) { m_isSliderChange = true; 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 + 10, pos.z); else CanvasObj.transform.position = new Vector3(pos.x, pos.y - 10, pos.z); } } } }