天天看點

向量旋轉

// 向量v0沿着Y軸旋轉45度得到v1

Vector3 v0;

Vector3 v1 = Quaternion.AngleAxis(45, Vector3.up) * v0;
      

  

// 某遊戲物體繞Y軸旋轉30度得到的新Quaternion
Quaternion rotation = Quaternion.Euler(0f,30f,0f) * Target.rotation;

// 沿着Target的X軸延伸10米求目标點的3D坐标
Vector3 newPos = Target.position + rotation * new Vector3(10f,0f,0f);
      
// 物體自身正前方5米距離的點的坐标
	private float distance = 5f;
	void Update () 
	{
		Quaternion r= transform.rotation;
		Vector3 f0 =  (transform.position  + (r *Vector3.forward) * distance);
		Debug.DrawLine(transform.position,f0,Color.red);
	}
      
// 某坐标vo沿着某個方向距離5米得到的新坐标v1

Vector3 vo;
Vector3 direction ;// 此為機關向量

Vector3 v1 = vo + direction * 5f;
      

學習連結 : http://www.xuanyusong.com/archives/1977

寫在前面的話,前兩天有個朋友在QQ上問我 如何擷取主角面朝方向一定區域中的敵人對象。這個命題看似簡單,其實裡面蘊含了很多數學方面的東西。今天剛好有時間我就徹底的把這個疑問寫在部落格中。希望可以幫助到他。

在上代碼之前請大家跟我先做幾個簡單的練習題,角度向量的計算一定要學會,不然後面的東西會很難懂。

1.已知3D坐标,和一個旋轉角度,以及一段距離,求目标點的3D坐标。

已知目前點為Target,目标點沿着Target的Y軸旋轉30度,沿着Target的X軸延伸10米求目标點的3D坐标?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

using UnityEngine;

using System.Collections;

public class Test : MonoBehaviour

{

public Transform Target;

void LateUpdate ()

{

Quaternion rotation = Quaternion.Euler(0f,30f,0f) * Target.rotation;

Vector3  newPos = rotation * new Vector3(10f,0f,0f);

Debug.DrawLine(newPos,Vector3.zero,Color.red);

Debug.Log("newpos " + newPos +" nowpos " + Target.position + " distance " + Vector3.Distance(newPos,Target.position));

}

}

 輸出結果 :新坐标 (8.7, 0.0, -5.0) 目前坐标 (0.0, 0.0, 0.0)兩點之間的距離 10。

 2.已知3D模型的角度求它的向量。

已知3D模型Target,Y軸旋轉30度後向前平移。

18

19

20

if(Input.GetMouseButton(0))

Vector3  newPos = rotation * Vector3.forward;

Target.Translate(newPos.x,newPos.y,newPos.z);

 3.已知一個目标點,讓模型朝着這個目标點移動。

這是一個比較簡單的例子,大家應該都能看明白。

Target.transform.LookAt(new Vector3 (100f,200f,300f));

Target.Translate(Vector3.forward);

這裡我要說的就是Vector3.forward ,它等價與 new Vector3(0,0,1);它并不是一個坐标,它是一個标準向量,方向是沿着Z軸向前。這樣平移一次的距離就是1米, 如果Vector3.forward * 100那麼一次平移的距離就是100米。 

在看看下面這段代碼

Vector3 vecn = (TargetCube.position - Target.position).normalized;

Target.Translate(vecn *0.1f);

 用向量減去一個向量求出它們的內插補點,normalized 是格式化向量,意思是把它們之間向量格式化到1米内。這樣就可以更加精确的計算一次平移的距離了 vecn *0.1f 就标示一次平移1分米,蛤蛤。

 向量不僅可以進行X Y Z軸的移動,同樣可以進行旋轉 ,下面這段代碼就是讓向量沿着Y軸旋轉30度。

vecn = Quaternion.Euler(0f,30f,0f) * vecn;

如果上述三道簡單的練習題 你都能了然于心的話,那麼本文最大的難題我相信也不會是什麼難事,繼續閱讀吧。

假設我們需要計算主角面前5米内所有的對象時。以主角為圓心計算面前5米外的一個點,為了讓大家看清楚我現将這條線繪制出來。

private float distance = 5f;

void Update ()

Quaternion r= transform.rotation;

Vector3 f0 =  (transform.position  + (r *Vector3.forward) * distance);

Debug.DrawLine(transform.position,f0,Color.red);

如下圖所,我們已經将這兩個點計算出來了。此時你可以動态的編輯主角Y軸的坐标,這個點永遠都是沿着主角目前角度面前5米以外的點。

接下來,我們需要計算主角面前的一個發散性的角度。假設主角看到的是向左30度,向右30度在這個區域。

Quaternion r0= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y - 30f,transform.rotation.eulerAngles.z);

Quaternion r1= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y + 30f,transform.rotation.eulerAngles.z);

Vector3 f1 =  (transform.position  + (r0 *Vector3.forward) * distance);

Vector3 f2 =  (transform.position  + (r1 *Vector3.forward) * distance);

Debug.DrawLine(transform.position,f1,Color.red);

Debug.DrawLine(transform.position,f2,Color.red);

Debug.DrawLine(f0,f1,Color.red);

Debug.DrawLine(f0,f2,Color.red);

如下圖所示,這時主角面前的區域就計算出來了。看起來就是兩個三角形之間的區域。

最後就是簡單的套用公式,計算一個點是否在三角形内,在本文中就是計算敵人的點是否在面前的這兩個三角形内。

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

public class MyTest : MonoBehaviour {

public Transform cube;

private float distance = 5f;

Vector3 point = cube.position;

if(isINTriangle(point,transform.position,f1,f0) || isINTriangle(point,transform.position,f2,f0) )

Debug.Log("cube in this !!!");

}else

Debug.Log("cube not in this !!!");

private  float triangleArea(float v0x,float v0y,float v1x,float v1y,float v2x,float v2y)

        return Mathf.Abs((v0x * v1y + v1x * v2y + v2x * v0y

            - v1x * v0y - v2x * v1y - v0x * v2y) / 2f);

    }

bool isINTriangle(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2)

float x = point.x;

float y = point.z;

float v0x = v0.x;

float v0y = v0.z;

float v1x = v1.x;

float v1y = v1.z;

float v2x = v2.x;

float v2y = v2.z;

float t = triangleArea(v0x,v0y,v1x,v1y,v2x,v2y);

float a = triangleArea(v0x,v0y,v1x,v1y,x,y) + triangleArea(v0x,v0y,x,y,v2x,v2y) + triangleArea(x,y,v1x,v1y,v2x,v2y);

if (Mathf.Abs(t - a) <= 0.01f)

return true;

return false;

如下圖所示,如果箱子對象是主角的視野中就會檢測到。 

注意,上圖中我的視野選擇了兩個三角形,如果你需要視野目标點是橢圓形的話,那麼可以多設定一些三角形。但是這樣就會非常消耗效率,我覺得這裡完全可以使用1個三角形,,隻是正對的目标點會出現一些偏差,影響其實并不會很大。如下圖所示

代碼簡單的修改一下即可。

Debug.DrawLine(f1,f2,Color.red);

if(isINTriangle(point,transform.position,f1,f2))

上面我們介紹了三角形判斷,當然也可以通過矩形來判斷是否相交。。

代碼:

Vector3 left =  (transform.position  + (r *Vector3.left) * distance);

Debug.DrawLine(transform.position,left,Color.red);

Vector3 right =  (transform.position  + (r *Vector3.right) * distance);

Debug.DrawLine(transform.position,right,Color.red);

Vector3 leftEnd = (left  + (r *Vector3.forward) * distance);

Debug.DrawLine(left,leftEnd,Color.red);

Vector3 rightEnd = (right  + (r *Vector3.forward) * distance);

Debug.DrawLine(right,rightEnd,Color.red);

Debug.DrawLine(leftEnd,rightEnd,Color.red);

if(isINRect(point,leftEnd,rightEnd,right,left))

     private float Multiply(float p1x , float p1y, float p2x,float p2y, float p0x,float p0y)

     {

        return ((p1x - p0x) * (p2y - p0y) - (p2x - p0x) * (p1y - p0y));

     }

bool isINRect(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2,Vector3 v3)

float v3x = v3.x;

float v3y = v3.z;

if (Multiply(x,y, v0x,v0y, v1x,v1y) * Multiply(x,y, v3x,v3y, v2x,v2y) <= 0 && Multiply(x,y, v3x,v3y, v0x,v0y) * Multiply(x,y, v2x,v2y, v1x,v1y) <= 0)

             return true;

else

            return false;

如果大家看了這篇文章後發現在你的項目中還有一些比較麻煩的角度與向量的算法,歡迎在下面留言給我,如果我有時間我會第一時間把方法貼在部落格中。互相學習互相進步,加油!哇咔咔。。

馬上過年了,雨松MOMO在這裡祝福大家2013年幸幸福福的過日子,嘿嘿。

2013年4月補充

感謝樓下朋友給我的留言。, 我在補充一下這篇部落格。

public class NewBehaviourScript : MonoBehaviour {

public Transform target;

void Update()

float distance = Vector3.Distance(target.position,transform.position);

Quaternion right = transform.rotation * Quaternion.AngleAxis(30,Vector3.up);

Quaternion left = transform.rotation * Quaternion.AngleAxis(30,Vector3.down);

Vector3 n = transform.position + (Vector3.forward * distance);

Vector3 leftPoint = left * n ;

Vector3 rightPoint =  right *n ;

Debug.DrawLine(transform.position,leftPoint,Color.red);

Debug.DrawLine(transform.position,rightPoint,Color.red);

Debug.DrawLine(rightPoint,leftPoint,Color.red);

這裡我以角色左右個30度。 這樣就可以根據兩個模型的距離以及角度來判斷了。。

效果很贊的表單線上制作工具推薦

作者:大表哥的筆記

出處:http://www.cnblogs.com/dabiaoge/

提示:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

如果覺得還有幫助的話,可以點一下右下角的【推薦】,希望能夠持續的為大家帶來好的技術文章!想跟我一起進步麼?那就【關注】我吧。

如果對文章有任何問題,都可以再評論中留言,我會盡可能的答複您,謝謝你的閱讀