EllipticalOrbit.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class EllipticalOrbit : MonoBehaviour
  5. {
  6. [Tooltip("要移动的物体")]
  7. public GameObject go;
  8. [Tooltip("长轴长")]
  9. public float Ellipse_a;
  10. [Tooltip("短轴长")]
  11. public float Ellipse_b;
  12. [Tooltip("角度")]
  13. float angle;
  14. [Tooltip("半径")]
  15. public float Circular_R;
  16. [Tooltip("原点")]
  17. public GameObject Point;
  18. public GameObject cube;
  19. public float checkTargetDirForMe(Transform target)
  20. {
  21. //xuqiTest: target.position = new Vector3(3, 0, 5);
  22. Vector3 dir = target.position - transform.position; //位置差,方向
  23. //方式1 点乘
  24. //点积的计算方式为: a·b =| a |·| b | cos < a,b > 其中 | a | 和 | b | 表示向量的模 。
  25. float dot = Vector3.Dot(transform.forward, dir.normalized);//点乘判断前后:dot >0在前,<0在后
  26. float dot1 = Vector3.Dot(transform.right, dir.normalized);//点乘判断左右: dot1>0在右,<0在左
  27. float angle = Mathf.Acos(Vector3.Dot(transform.forward.normalized, dir.normalized)) * Mathf.Rad2Deg;//通过点乘求出夹角
  28. //方式2 叉乘
  29. //叉乘满足右手准则 公式:模长|c|=|a||b|sin<a,b>
  30. Vector3 cross = Vector3.Cross(transform.forward, dir.normalized);//叉乘判断左右:cross.y>0在左,<0在右
  31. Vector3 cross1 = Vector3.Cross(transform.right, dir.normalized); //叉乘判断前后:cross.y>0在前,<0在后
  32. angle = Mathf.Asin(Vector3.Distance(Vector3.zero, Vector3.Cross(transform.forward.normalized, dir.normalized))) * Mathf.Rad2Deg;
  33. return angle;
  34. }
  35. private void Update()
  36. {
  37. //GetAngle();
  38. angle = checkTargetDirForMe(cube.transform)/90;
  39. //角度
  40. //angle += Time.deltaTime / 10f;
  41. //Debug.Log(angle);
  42. //椭圆运动
  43. Move(Ellipse_X(Ellipse_a, angle), Ellipse_Y(Ellipse_b, angle));
  44. }
  45. /// <summary>
  46. /// 移动
  47. /// </summary>
  48. /// <param name="x"></param>
  49. /// <param name="y"></param>
  50. private void Move(float x, float y)
  51. {
  52. go.transform.position = new Vector3(x + Point.transform.position.x, 0, y + Point.transform.position.z);
  53. }
  54. /// <summary>
  55. /// 椭圆x坐标
  56. /// </summary>
  57. /// <param name="a">长半轴</param>
  58. /// <param name="angle"></param>
  59. /// <returns></returns>
  60. private float Ellipse_X(float a, float angle)
  61. {
  62. return a * Mathf.Cos(angle * Mathf.Rad2Deg);
  63. }
  64. /// <summary>
  65. /// 椭圆y坐标
  66. /// </summary>
  67. /// <param name="b">短半轴</param>
  68. /// <param name="angle"></param>
  69. /// <returns></returns>
  70. private float Ellipse_Y(float b, float angle)
  71. {
  72. return b * Mathf.Sin(angle * Mathf.Rad2Deg);
  73. }
  74. // 关于点积
  75. private void Dot()
  76. {
  77. /*
  78. 点积
  79. 点积的计算方式为: a·b=|a|·|b|cos<a,b> 其中|a|和|b|表示向量的模,
  80. <a,b>表示两个向量的夹角。 通过点积判断当两个向量的方向向是否相同
  81. (大致相同即两个向量的夹角在 90 度范围内)
  82. 两个向量的 点积 大于 0 则两个向量夹角小于 90 度, 否则 两个向量的
  83. 夹角大于 90 度,
  84. */
  85. // 定义两个向量 a、b
  86. Vector3 a = new Vector3(1, 1, 1);
  87. Vector3 b = new Vector3(1, 5, 1);
  88. // 计算 a、b 点积结果
  89. float result = Vector3.Dot(a, b);
  90. // 通过向量直接获取两个向量的夹角(默认为 角度), 此方法范围 [0 - 180]
  91. float angle = Vector3.Angle(a, b);
  92. // 下面获取夹角的方法,只是展示用法,太麻烦不必使用
  93. // 通过向量点积获取向量夹角,需要注意,必须将向量转换为单位向量才行
  94. // 计算 a、b 单位向量的点积
  95. result = Vector3.Dot(a.normalized, b.normalized);
  96. // 通过反余弦函数获取 向量 a、b 夹角(默认为 弧度)
  97. float radians = Mathf.Acos(result);
  98. // 将弧度转换为 角度
  99. angle = radians * Mathf.Rad2Deg;
  100. }
  101. // 关于叉乘
  102. private void Cross()
  103. {
  104. /*
  105. 叉积
  106. 叉积的定义: c = a x b 其中a,b,c均为向量。两个向量的叉积是向量, 向量的模为 |c|=|a||b|sin<a,b>
  107. 且 向量 c 垂直于 a、b, c 垂直于 a、b 组成的平面, a x b = - b x a;
  108. */
  109. // 定义两个向量 a、b
  110. Vector3 a = new Vector3(1, 1, 1);
  111. Vector3 b = new Vector3(1, 5, 1);
  112. //计算向量 a、b 的叉积,结果为 向量
  113. Vector3 c = Vector3.Cross(a, b);
  114. // 下面获取夹角的方法,只是展示用法,太麻烦不必使用
  115. // 通过反正弦函数获取向量 a、b 夹角(默认为弧度)
  116. float radians = Mathf.Asin(Vector3.Distance(Vector3.zero, Vector3.Cross(a.normalized, b.normalized)));
  117. float angle = radians * Mathf.Rad2Deg;
  118. // 判断顺时针、逆时针方向,是在 2D 平面内的,所以需指定一个平面,下面以X、Z轴组成的平面为例(忽略 Y 轴)
  119. // 以 Y 轴为纵轴
  120. // 在 X、Z 轴平面上,判断 b 在 a 的顺时针或者逆时针方向
  121. if (c.y > 0)
  122. {
  123. // b 在 a 的顺时针方向
  124. }
  125. else if (c.y == 0)
  126. {
  127. // b 和 a 方向相同(平行)
  128. }
  129. else
  130. {
  131. // b 在 a 的逆时针方向
  132. }
  133. }
  134. // 获取两个向量的夹角 Vector3.Angle 只能返回 [0, 180] 的值
  135. // 如真实情况下向量 a 到 b 的夹角(80 度)则 b 到 a 的夹角是(-80)
  136. // 通过 Dot、Cross 结合获取到 a 到 b, b 到 a 的不同夹角
  137. private void GetAngle(Vector3 a, Vector3 b)
  138. {
  139. Vector3 c = Vector3.Cross(a, b);
  140. float angle = Vector3.Angle(a, b);
  141. // b 到 a 的夹角
  142. float sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(a.normalized, b.normalized)));
  143. float signed_angle = angle * sign;
  144. Debug.Log("b -> a :" + signed_angle);
  145. // a 到 b 的夹角
  146. sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(b.normalized, a.normalized)));
  147. signed_angle = angle * sign;
  148. Debug.Log("a -> b :" + signed_angle);
  149. }
  150. }