123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class EllipticalOrbit : MonoBehaviour
- {
- [Tooltip("要移动的物体")]
- public GameObject go;
- [Tooltip("长轴长")]
- public float Ellipse_a;
- [Tooltip("短轴长")]
- public float Ellipse_b;
- [Tooltip("角度")]
- float angle;
- [Tooltip("半径")]
- public float Circular_R;
- [Tooltip("原点")]
- public GameObject Point;
- public GameObject cube;
- public float checkTargetDirForMe(Transform target)
- {
- //xuqiTest: target.position = new Vector3(3, 0, 5);
- Vector3 dir = target.position - transform.position; //位置差,方向
- //方式1 点乘
- //点积的计算方式为: a·b =| a |·| b | cos < a,b > 其中 | a | 和 | b | 表示向量的模 。
- float dot = Vector3.Dot(transform.forward, dir.normalized);//点乘判断前后:dot >0在前,<0在后
- float dot1 = Vector3.Dot(transform.right, dir.normalized);//点乘判断左右: dot1>0在右,<0在左
- float angle = Mathf.Acos(Vector3.Dot(transform.forward.normalized, dir.normalized)) * Mathf.Rad2Deg;//通过点乘求出夹角
- //方式2 叉乘
- //叉乘满足右手准则 公式:模长|c|=|a||b|sin<a,b>
- Vector3 cross = Vector3.Cross(transform.forward, dir.normalized);//叉乘判断左右:cross.y>0在左,<0在右
- Vector3 cross1 = Vector3.Cross(transform.right, dir.normalized); //叉乘判断前后:cross.y>0在前,<0在后
- angle = Mathf.Asin(Vector3.Distance(Vector3.zero, Vector3.Cross(transform.forward.normalized, dir.normalized))) * Mathf.Rad2Deg;
- return angle;
- }
- private void Update()
- {
- //GetAngle();
- angle = checkTargetDirForMe(cube.transform)/90;
- //角度
- //angle += Time.deltaTime / 10f;
- //Debug.Log(angle);
- //椭圆运动
- Move(Ellipse_X(Ellipse_a, angle), Ellipse_Y(Ellipse_b, angle));
- }
- /// <summary>
- /// 移动
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- private void Move(float x, float y)
- {
- go.transform.position = new Vector3(x + Point.transform.position.x, 0, y + Point.transform.position.z);
- }
- /// <summary>
- /// 椭圆x坐标
- /// </summary>
- /// <param name="a">长半轴</param>
- /// <param name="angle"></param>
- /// <returns></returns>
- private float Ellipse_X(float a, float angle)
- {
- return a * Mathf.Cos(angle * Mathf.Rad2Deg);
- }
- /// <summary>
- /// 椭圆y坐标
- /// </summary>
- /// <param name="b">短半轴</param>
- /// <param name="angle"></param>
- /// <returns></returns>
- private float Ellipse_Y(float b, float angle)
- {
- return b * Mathf.Sin(angle * Mathf.Rad2Deg);
- }
- // 关于点积
- private void Dot()
- {
- /*
- 点积
- 点积的计算方式为: a·b=|a|·|b|cos<a,b> 其中|a|和|b|表示向量的模,
- <a,b>表示两个向量的夹角。 通过点积判断当两个向量的方向向是否相同
- (大致相同即两个向量的夹角在 90 度范围内)
- 两个向量的 点积 大于 0 则两个向量夹角小于 90 度, 否则 两个向量的
- 夹角大于 90 度,
- */
- // 定义两个向量 a、b
- Vector3 a = new Vector3(1, 1, 1);
- Vector3 b = new Vector3(1, 5, 1);
- // 计算 a、b 点积结果
- float result = Vector3.Dot(a, b);
- // 通过向量直接获取两个向量的夹角(默认为 角度), 此方法范围 [0 - 180]
- float angle = Vector3.Angle(a, b);
- // 下面获取夹角的方法,只是展示用法,太麻烦不必使用
- // 通过向量点积获取向量夹角,需要注意,必须将向量转换为单位向量才行
- // 计算 a、b 单位向量的点积
- result = Vector3.Dot(a.normalized, b.normalized);
- // 通过反余弦函数获取 向量 a、b 夹角(默认为 弧度)
- float radians = Mathf.Acos(result);
- // 将弧度转换为 角度
- angle = radians * Mathf.Rad2Deg;
- }
- // 关于叉乘
- private void Cross()
- {
- /*
- 叉积
- 叉积的定义: c = a x b 其中a,b,c均为向量。两个向量的叉积是向量, 向量的模为 |c|=|a||b|sin<a,b>
- 且 向量 c 垂直于 a、b, c 垂直于 a、b 组成的平面, a x b = - b x a;
- */
- // 定义两个向量 a、b
- Vector3 a = new Vector3(1, 1, 1);
- Vector3 b = new Vector3(1, 5, 1);
- //计算向量 a、b 的叉积,结果为 向量
- Vector3 c = Vector3.Cross(a, b);
- // 下面获取夹角的方法,只是展示用法,太麻烦不必使用
- // 通过反正弦函数获取向量 a、b 夹角(默认为弧度)
- float radians = Mathf.Asin(Vector3.Distance(Vector3.zero, Vector3.Cross(a.normalized, b.normalized)));
- float angle = radians * Mathf.Rad2Deg;
- // 判断顺时针、逆时针方向,是在 2D 平面内的,所以需指定一个平面,下面以X、Z轴组成的平面为例(忽略 Y 轴)
- // 以 Y 轴为纵轴
- // 在 X、Z 轴平面上,判断 b 在 a 的顺时针或者逆时针方向
- if (c.y > 0)
- {
- // b 在 a 的顺时针方向
- }
- else if (c.y == 0)
- {
- // b 和 a 方向相同(平行)
- }
- else
- {
- // b 在 a 的逆时针方向
- }
- }
- // 获取两个向量的夹角 Vector3.Angle 只能返回 [0, 180] 的值
- // 如真实情况下向量 a 到 b 的夹角(80 度)则 b 到 a 的夹角是(-80)
- // 通过 Dot、Cross 结合获取到 a 到 b, b 到 a 的不同夹角
- private void GetAngle(Vector3 a, Vector3 b)
- {
- Vector3 c = Vector3.Cross(a, b);
- float angle = Vector3.Angle(a, b);
- // b 到 a 的夹角
- float sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(a.normalized, b.normalized)));
- float signed_angle = angle * sign;
- Debug.Log("b -> a :" + signed_angle);
- // a 到 b 的夹角
- sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(b.normalized, a.normalized)));
- signed_angle = angle * sign;
- Debug.Log("a -> b :" + signed_angle);
- }
- }
|