MoveComponent.cs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using System.Threading;
  2. using System.Threading.Tasks;
  3. using PF;
  4. namespace ETModel
  5. {
  6. public class MoveComponent: Component
  7. {
  8. public Vector3 Target;
  9. // 开启移动协程的时间
  10. public long StartTime;
  11. public long lastFrameTime;
  12. // 开启移动协程的Unit的位置
  13. public Vector3 StartPos;
  14. // 移动的方向标准化
  15. public Vector3 DirNormalized;
  16. // 当前的移动速度
  17. public float Speed = 5;
  18. public void Awake()
  19. {
  20. this.Target = this.GetParent<Unit>().Position;
  21. }
  22. // 开启协程移动,每100毫秒移动一次,并且协程取消的时候会计算玩家真实移动
  23. // 比方说玩家移动了2500毫秒,玩家有新的目标,这时旧的移动协程结束,将计算250毫秒移动的位置,而不是300毫秒移动的位置
  24. public async Task StartMove(CancellationToken cancellationToken)
  25. {
  26. Unit unit = this.GetParent<Unit>();
  27. this.StartPos = unit.Position;
  28. this.StartTime = TimeHelper.Now();
  29. this.DirNormalized = (this.Target - unit.Position).normalized;
  30. TimerComponent timerComponent = Game.Scene.GetComponent<TimerComponent>();
  31. // 协程如果取消,将算出玩家的真实位置,赋值给玩家
  32. cancellationToken.Register(() =>
  33. {
  34. // 算出当前玩家的位置
  35. long timeNow = TimeHelper.Now();
  36. unit.Position = StartPos + this.DirNormalized * this.Speed * (timeNow - this.StartTime) / 1000f;
  37. });
  38. while (true)
  39. {
  40. Vector3 willPos = unit.Position + this.DirNormalized * this.Speed * 0.05f;
  41. if ((willPos - this.StartPos).magnitude > (this.Target - this.StartPos).magnitude - 0.1f)
  42. {
  43. unit.Position = this.Target;
  44. break;
  45. }
  46. await timerComponent.WaitAsync(50, cancellationToken);
  47. long timeNow = TimeHelper.Now();
  48. lastFrameTime = timeNow;
  49. unit.Position = StartPos + this.DirNormalized * this.Speed * (timeNow - this.StartTime) / 1000f;
  50. }
  51. }
  52. public async Task MoveToAsync(Vector3 target, CancellationToken cancellationToken)
  53. {
  54. // 新目标点离旧目标点太近,不设置新的
  55. if ((target - this.Target).sqrMagnitude < 0.01f)
  56. {
  57. return;
  58. }
  59. // 距离当前位置太近
  60. if ((this.GetParent<Unit>().Position - target).sqrMagnitude < 0.01f)
  61. {
  62. return;
  63. }
  64. this.Target = target;
  65. // 开启协程移动
  66. await StartMove(cancellationToken);
  67. }
  68. }
  69. }