using DG.Tweening; using System; using UnityEngine; using XGame.Framework.Interfaces; using XGame.Framework.Time; namespace FL.Battle.Actions { /// /// 贝塞尔移动 /// 中心点位置随机 /// internal class MoveBezierAction : IAction, IPauseable, ITimeScalable { public MoveActionArgs args; private Tween _tween; private bool _paused; float ITimeScalable.TimeScale { get => _tween?.timeScale ?? 1; set { if (_tween == null) { return; } _tween.timeScale = value; } } void IReference.Clear() { _tween?.Kill(); _tween = null; args = default; _paused = false; } public void Start(Transform transform, bool isFoword) { //transform.DOPlayForward(); // 贝塞尔曲线运动 transform.position = args.from; var timeScale = UnityEngine.Random.Range(0.2f, 0.8f); var linePoint = Vector3.Lerp(args.from, args.to, timeScale); var dir = Vector3.Cross(args.to - args.from, Vector3.forward).normalized; //运动方向的法线 // 沿Y轴上下运动时算出来z值为零,直接把x值赋值给z进行偏移 if (dir.z == 0) dir.z = dir.x; var disOffset = UnityEngine.Random.Range(-3f, 3f); var center = linePoint + dir * disOffset; var totalTime = args.duration * 0.001f; var timeTween = DOTween.To(() => 0, (t) => { var tNormal = t / totalTime; var pos = args.from.BezierPoint(center, args.to, tNormal); transform.position = pos; if (isFoword) { var tempDir = (args.to - pos).normalized; var rot = Vector3.zero; rot.z = Vector3.Angle(tempDir, Vector3.up); transform.localEulerAngles = rot; //if (tempDir != Vector3.zero) //{ // transform.forward = tempDir; //} } args.onUpdate.SafeInvoke(pos); }, totalTime, totalTime); if (args.delay > 0) timeTween.SetDelay(args.delay * 0.001f); timeTween.SetEase(args.ease == Ease.Unset ? Ease.OutQuad : args.ease); _tween = timeTween; timeTween.onComplete = () => { var callback = args.onComplete; _tween = null; args = default; callback?.Invoke(); }; } void IAction.Start(Transform transform) { Start(transform, true); } void IPauseable.Pause() { if (_tween == null || _paused) { return; } _paused = true; _tween.Pause(); } void IPauseable.Resume() { if (_paused) { _paused = false; _tween?.Play(); } } } }