247 lines
6.8 KiB
C#
247 lines
6.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace ET
|
|
{
|
|
[ObjectSystem]
|
|
public class MoveComponentDestroySystem : DestroySystem<MoveComponent>
|
|
{
|
|
public override void Destroy(MoveComponent self)
|
|
{
|
|
self.Clear();
|
|
}
|
|
}
|
|
|
|
[ObjectSystem]
|
|
public class MoveComponentAwakeSystem : AwakeSystem<MoveComponent>
|
|
{
|
|
public override void Awake(MoveComponent self)
|
|
{
|
|
self.StartTime = 0;
|
|
self.StartPos = Vector3.zero;
|
|
self.NeedTime = 0;
|
|
self.MoveTimer = 0;
|
|
self.Callback = null;
|
|
self.Targets.Clear();
|
|
self.Speed = 0;
|
|
self.N = 0;
|
|
}
|
|
}
|
|
|
|
public static class MoveComponentSystem
|
|
{
|
|
public static bool IsArrived(this MoveComponent self)
|
|
{
|
|
return self.Targets.Count == 0;
|
|
}
|
|
|
|
public static async ETTask<bool> MoveToAsync(this MoveComponent self, List<Vector3> targets, float speed, ETCancellationToken cancellationToken = null)
|
|
{
|
|
self.Stop();
|
|
|
|
foreach (Vector3 item in targets)
|
|
{
|
|
self.Targets.Add(item);
|
|
}
|
|
|
|
self.IsTurnHorizontal = true;
|
|
|
|
self.Speed = speed;
|
|
ETTaskCompletionSource<bool> tcs = new ETTaskCompletionSource<bool>();
|
|
self.Callback = (ret) => {tcs.SetResult(ret); };
|
|
|
|
Game.EventSystem.Publish(new EventType.MoveStart() { unit = self.GetParent<Unit>() }).Coroutine();
|
|
|
|
self.StartMove();
|
|
|
|
void CancelAction()
|
|
{
|
|
self.Stop();
|
|
}
|
|
|
|
bool moveRet;
|
|
try
|
|
{
|
|
cancellationToken?.Add(CancelAction);
|
|
moveRet = await tcs.Task;
|
|
}
|
|
finally
|
|
{
|
|
cancellationToken?.Remove(CancelAction);
|
|
}
|
|
|
|
if (moveRet)
|
|
{
|
|
Game.EventSystem.Publish(new EventType.MoveStop() { unit = self.GetParent<Unit>() }).Coroutine();
|
|
}
|
|
return moveRet;
|
|
}
|
|
|
|
public static void MoveForward(this MoveComponent self, bool needCancel)
|
|
{
|
|
Unit unit = self.GetParent<Unit>();
|
|
|
|
long timeNow = TimeHelper.ClientNow();
|
|
long moveTime = timeNow - self.StartTime;
|
|
|
|
while (true)
|
|
{
|
|
if (moveTime <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 计算位置插值
|
|
if (moveTime >= self.NeedTime)
|
|
{
|
|
unit.Position = self.NextTarget;
|
|
unit.YAngle = self.To;
|
|
}
|
|
else
|
|
{
|
|
// 计算位置插值
|
|
float amount = moveTime * 1f / self.NeedTime;
|
|
if (amount > 0)
|
|
{
|
|
Vector3 newPos = Vector3.Lerp(self.StartPos, self.NextTarget, amount);
|
|
unit.Position = newPos;
|
|
}
|
|
|
|
// 计算方向插值
|
|
unit.YAngle = self.To;
|
|
}
|
|
|
|
moveTime -= self.NeedTime;
|
|
|
|
// 表示这个点还没走完,等下一帧再来
|
|
if (moveTime < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 到这里说明这个点已经走完
|
|
|
|
// 如果是最后一个点
|
|
if (self.N >= self.Targets.Count - 1)
|
|
{
|
|
unit.Position = self.NextTarget;
|
|
unit.YAngle = self.To;
|
|
|
|
Action<bool> callback = self.Callback;
|
|
self.Callback = null;
|
|
|
|
self.Clear();
|
|
callback?.Invoke(!needCancel);
|
|
return;
|
|
}
|
|
|
|
self.SetNextTarget();
|
|
}
|
|
}
|
|
|
|
private static void StartMove(this MoveComponent self)
|
|
{
|
|
Unit unit = self.GetParent<Unit>();
|
|
|
|
self.BeginTime = TimeHelper.ClientNow();
|
|
self.StartTime = self.BeginTime;
|
|
self.SetNextTarget();
|
|
|
|
self.MoveTimer = TimerComponent.Instance.NewFrameTimer(() =>
|
|
{
|
|
try
|
|
{
|
|
self.MoveForward(false);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.Error($"move timer error: {unit.Id}\n{e}");
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
private static void SetNextTarget(this MoveComponent self)
|
|
{
|
|
|
|
Unit unit = self.GetParent<Unit>();
|
|
|
|
++self.N;
|
|
|
|
// 时间计算用服务端的位置, 但是移动要用客户端的位置来插值
|
|
Vector3 v = self.GetFaceV();
|
|
float distance = v.magnitude;
|
|
|
|
// 插值的起始点要以unit的真实位置来算
|
|
self.StartPos = unit.Position;
|
|
|
|
self.StartTime += self.NeedTime;
|
|
|
|
self.NeedTime = (long)(distance / self.Speed * 1000);
|
|
|
|
unit.YAngle = self.To;
|
|
}
|
|
|
|
private static Vector3 GetFaceV(this MoveComponent self)
|
|
{
|
|
return self.NextTarget - self.PreTarget;
|
|
}
|
|
|
|
public static bool FlashTo(this MoveComponent self, Vector3 target)
|
|
{
|
|
Unit unit = self.GetParent<Unit>();
|
|
unit.Position = target;
|
|
return true;
|
|
}
|
|
|
|
public static bool MoveTo(this MoveComponent self, Vector3 target, float speed, bool isTurnHorizontal = false)
|
|
{
|
|
if (speed < 0.001)
|
|
{
|
|
Log.Error($"speed is 0 {self.GetParent<Unit>().Id} {speed}");
|
|
return false;
|
|
}
|
|
|
|
self.Stop();
|
|
|
|
self.IsTurnHorizontal = isTurnHorizontal;
|
|
self.Targets.Add(self.GetParent<Unit>().Position);
|
|
self.Targets.Add(target);
|
|
self.Speed = speed;
|
|
|
|
self.StartMove();
|
|
return true;
|
|
}
|
|
|
|
public static void Stop(this MoveComponent self)
|
|
{
|
|
if (self.Targets.Count > 0)
|
|
{
|
|
self.MoveForward(true);
|
|
}
|
|
|
|
self.Clear();
|
|
}
|
|
|
|
public static void Clear(this MoveComponent self)
|
|
{
|
|
self.StartTime = 0;
|
|
self.StartPos = Vector3.zero;
|
|
self.BeginTime = 0;
|
|
self.NeedTime = 0;
|
|
TimerComponent.Instance.Remove(ref self.MoveTimer);
|
|
self.Targets.Clear();
|
|
self.Speed = 0;
|
|
self.N = 0;
|
|
self.IsTurnHorizontal = false;
|
|
|
|
if (self.Callback != null)
|
|
{
|
|
Action<bool> callback = self.Callback;
|
|
self.Callback = null;
|
|
callback.Invoke(false);
|
|
}
|
|
}
|
|
}
|
|
} |