using UnityEngine;
|
using DG.Tweening;
|
|
public class BubbleFloat : MonoBehaviour
|
{
|
[Header("浮动范围设置")]
|
[SerializeField] private float minY = -20f; // 相对于初始位置的最低偏移
|
[SerializeField] private float maxY = 20f; // 相对于初始位置的最高偏移
|
|
[Header("动画设置")]
|
[SerializeField] private float duration = 2f; // 单程时间
|
[SerializeField] private Ease easeType = Ease.InOutSine;
|
[SerializeField] private bool useRandomDelay = true; // 是否开启随机延迟
|
|
private Vector3 initialPosition;
|
private Tween floatTween;
|
|
private void Awake()
|
{
|
// 记录 UI 挂载时的原始本地坐标
|
initialPosition = transform.localPosition;
|
}
|
|
private void OnEnable()
|
{
|
RestartAnimation();
|
}
|
|
private void RestartAnimation()
|
{
|
KillTween();
|
|
// 1. 确保回到初始参考点
|
transform.localPosition = initialPosition;
|
|
float startY = initialPosition.y + minY;
|
float endY = initialPosition.y + maxY;
|
|
// 2. 先设置初始位置(起始点)
|
transform.localPosition = new Vector3(initialPosition.x, startY, initialPosition.z);
|
|
// 3. 创建动画并记录
|
// 注意:我们将动画赋值给变量,并强制立即执行
|
floatTween = transform.DOLocalMoveY(endY, duration)
|
.SetEase(easeType)
|
.SetLoops(-1, LoopType.Yoyo)
|
.SetUpdate(true);
|
|
if (useRandomDelay)
|
{
|
// 关键修正:先让动画计算出初始状态,再跳转进度
|
// 否则在创建的第一帧,动画系统可能还没意识到它需要移动
|
float randomTime = Random.Range(0f, duration * 2f);
|
floatTween.Goto(randomTime, true); // true 表示立即执行回调和位移
|
}
|
}
|
|
private void OnDisable()
|
{
|
KillTween();
|
}
|
|
private void OnDestroy()
|
{
|
KillTween();
|
}
|
|
private void KillTween()
|
{
|
if (floatTween != null)
|
{
|
floatTween.Kill();
|
floatTween = null;
|
}
|
}
|
}
|