Files
TEngine/Assets/GameScripts/DotNet/Hotfix/Share/Module/Move/MoveComponentSystem.cs
ALEXTANG 336d4b2eb9 [+] 接入ET8服务端
[+] 接入ET8服务端
2023-07-13 12:23:48 +08:00

294 lines
8.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using Unity.Mathematics;
namespace ET
{
[EntitySystemOf(typeof(MoveComponent))]
[FriendOf(typeof(MoveComponent))]
public static partial class MoveComponentSystem
{
[Invoke(TimerInvokeType.MoveTimer)]
public class MoveTimer: ATimer<MoveComponent>
{
protected override void Run(MoveComponent self)
{
try
{
self.MoveForward(true);
}
catch (Exception e)
{
Log.Error($"move timer error: {self.Id}\n{e}");
}
}
}
[EntitySystem]
private static void Destroy(this MoveComponent self)
{
self.MoveFinish(false);
}
[EntitySystem]
private static void Awake(this MoveComponent self)
{
self.StartTime = 0;
self.StartPos = float3.zero;
self.NeedTime = 0;
self.MoveTimer = 0;
self.tcs = null;
self.Targets.Clear();
self.Speed = 0;
self.N = 0;
self.TurnTime = 0;
}
public static bool IsArrived(this MoveComponent self)
{
return self.Targets.Count == 0;
}
public static bool ChangeSpeed(this MoveComponent self, float speed)
{
if (self.IsArrived())
{
return false;
}
if (speed < 0.0001)
{
return false;
}
Unit unit = self.GetParent<Unit>();
using ListComponent<float3> path = ListComponent<float3>.Create();
self.MoveForward(false);
path.Add(unit.Position); // 第一个是Unit的pos
for (int i = self.N; i < self.Targets.Count; ++i)
{
path.Add(self.Targets[i]);
}
self.MoveToAsync(path, speed).Coroutine();
return true;
}
// 该方法不需要用cancelToken的方式取消因为即使不传入cancelToken多次调用该方法也要取消之前的移动协程,上层可以stop取消
public static async ETTask<bool> MoveToAsync(this MoveComponent self, List<float3> target, float speed, int turnTime = 100)
{
self.Stop(false);
foreach (float3 v in target)
{
self.Targets.Add(v);
}
self.IsTurnHorizontal = true;
self.TurnTime = turnTime;
self.Speed = speed;
self.tcs = ETTask<bool>.Create(true);
EventSystem.Instance.Publish(self.Scene(), new EventType.MoveStart() {Unit = self.GetParent<Unit>()});
self.StartMove();
bool moveRet = await self.tcs;
if (moveRet)
{
EventSystem.Instance.Publish(self.Scene(), new EventType.MoveStop() {Unit = self.GetParent<Unit>()});
}
return moveRet;
}
// ret: 停止的时候,移动协程的返回值
private static void MoveForward(this MoveComponent self, bool ret)
{
Unit unit = self.GetParent<Unit>();
long timeNow = self.Fiber().TimeInfo.ClientNow();
long moveTime = timeNow - self.StartTime;
while (true)
{
if (moveTime <= 0)
{
return;
}
// 计算位置插值
if (moveTime >= self.NeedTime)
{
unit.Position = self.NextTarget;
if (self.TurnTime > 0)
{
unit.Rotation = self.To;
}
}
else
{
// 计算位置插值
float amount = moveTime * 1f / self.NeedTime;
if (amount > 0)
{
float3 newPos = math.lerp(self.StartPos, self.NextTarget, amount);
unit.Position = newPos;
}
// 计算方向插值
if (self.TurnTime > 0)
{
amount = moveTime * 1f / self.TurnTime;
if (amount > 1)
{
amount = 1f;
}
quaternion q = math.slerp(self.From, self.To, amount);
unit.Rotation = q;
}
}
moveTime -= self.NeedTime;
// 表示这个点还没走完,等下一帧再来
if (moveTime < 0)
{
return;
}
// 到这里说明这个点已经走完
// 如果是最后一个点
if (self.N >= self.Targets.Count - 1)
{
unit.Position = self.NextTarget;
unit.Rotation = self.To;
self.MoveFinish(ret);
return;
}
self.SetNextTarget();
}
}
private static void StartMove(this MoveComponent self)
{
self.BeginTime = self.Fiber().TimeInfo.ClientNow();
self.StartTime = self.BeginTime;
self.SetNextTarget();
self.MoveTimer = self.Fiber().TimerComponent.NewFrameTimer(TimerInvokeType.MoveTimer, self);
}
private static void SetNextTarget(this MoveComponent self)
{
Unit unit = self.GetParent<Unit>();
++self.N;
// 时间计算用服务端的位置, 但是移动要用客户端的位置来插值
float3 v = self.GetFaceV();
float distance = math.length(v);
// 插值的起始点要以unit的真实位置来算
self.StartPos = unit.Position;
self.StartTime += self.NeedTime;
self.NeedTime = (long) (distance / self.Speed * 1000);
if (self.TurnTime > 0)
{
// 要用unit的位置
float3 faceV = self.GetFaceV();
if (math.lengthsq(faceV) < 0.0001f)
{
return;
}
self.From = unit.Rotation;
if (self.IsTurnHorizontal)
{
faceV.y = 0;
}
if (Math.Abs(faceV.x) > 0.01 || Math.Abs(faceV.z) > 0.01)
{
self.To = quaternion.LookRotation(faceV, math.up());
}
return;
}
if (self.TurnTime == 0) // turn time == 0 立即转向
{
float3 faceV = self.GetFaceV();
if (self.IsTurnHorizontal)
{
faceV.y = 0;
}
if (Math.Abs(faceV.x) > 0.01 || Math.Abs(faceV.z) > 0.01)
{
self.To = quaternion.LookRotation(faceV, math.up());
unit.Rotation = self.To;
}
}
}
private static float3 GetFaceV(this MoveComponent self)
{
return self.NextTarget - self.PreTarget;
}
public static bool FlashTo(this MoveComponent self, float3 target)
{
Unit unit = self.GetParent<Unit>();
unit.Position = target;
return true;
}
// ret: 停止的时候,移动协程的返回值
public static void Stop(this MoveComponent self, bool ret)
{
if (self.Targets.Count > 0)
{
self.MoveForward(ret);
}
self.MoveFinish(ret);
}
private static void MoveFinish(this MoveComponent self, bool ret)
{
if (self.StartTime == 0)
{
return;
}
self.StartTime = 0;
self.StartPos = float3.zero;
self.BeginTime = 0;
self.NeedTime = 0;
self.Targets.Clear();
self.Speed = 0;
self.N = 0;
self.TurnTime = 0;
self.IsTurnHorizontal = false;
self.Fiber().TimerComponent?.Remove(ref self.MoveTimer);
if (self.tcs != null)
{
var tcs = self.tcs;
self.tcs = null;
tcs.SetResult(ret);
}
}
}
}