371 lines
10 KiB
C#
371 lines
10 KiB
C#
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<Animator>();
|
||
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();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置物体到初始状态(位置、旋转、缩放)
|
||
/// </summary>
|
||
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
|
||
);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 动画开始正常播放
|
||
/// </summary>
|
||
public void StartPlayAnim()
|
||
{
|
||
if (animator != null)
|
||
{
|
||
IsStartBao = true;
|
||
animator.Play(clip.name, -1, explosionFactor);
|
||
animator.speed = 1;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 动画结束
|
||
/// </summary>
|
||
public void EndPlayAnim()
|
||
{
|
||
if(animator != null)
|
||
{
|
||
IsStartBao=false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 让当前动画跳转到指定时间(秒)
|
||
/// </summary>
|
||
/// <param name="timepercent">目标时间比</param>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前层正在播放的AnimationClip
|
||
/// </summary>
|
||
private AnimationClip GetCurrentAnimationClip(Animator anim)
|
||
{
|
||
AnimationClip[] animationClips = anim.runtimeAnimatorController.animationClips;
|
||
|
||
return animationClips[0];
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当滑动条值改变时调用(实时控制)
|
||
/// </summary>
|
||
public void OnSliderValueChanged(float value)
|
||
{
|
||
m_isSliderChange = true;
|
||
|
||
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 + 10, pos.z);
|
||
else
|
||
CanvasObj.transform.position = new Vector3(pos.x, pos.y - 10, pos.z);
|
||
}
|
||
}
|
||
}
|
||
}
|