找回密码
 立即注册
查看: 5293|回复: 65

[基础] Unity3D 中Transform,Physics,Vector3,Quaternion教程

[复制链接]
发表于 2012-12-17 12:33 | 显示全部楼层 |阅读模式
资源信息 Tutorial Information
教程名称: Unity3D 中Transform,Physics,Vector3,Quaternion教程(发帖教程)
适用引擎:   (适用引擎,为空默认为Unity)
教程语种: 中文
教程等级: 1
教程格式: 图文(请用IE9以上浏览器访问本版块)
教程作者: 转载自互联网 (如有问题请短消息联系作者或发表回复)
下载地址: (兑换积分)
点击查看原图
美丽分割线
Transform 变换,是场景中最常打交道的类,用于控制物体的位移,旋转,缩放等功能。


Transform
Class, inherits from Component, IEnumerable

Position, rotation and scale of an object.
控制物体的位置,旋转和缩放。

Every object in a scene has a Transform. It's used to store and manipulate the position, rotation and scale of the object. Every Transform can have a parent, which allows you to apply position, rotation and scale hierachically. This is the hierarchy seen in the Hierarchy pane. They also support enumerators so you can loop through children using:

// Moves
all transform children 10 units upwards!
for (var child
: Transform in transform) {

child.position += Vector3.up *
10.0;

}


每一个场景中的物体都有Transform这个类,他是用来储存和处理物体的位移,旋转和缩放的。每一个Transform都可以有一个父物体,这可以让你得到下游节点的位移旋转和缩放。这个层次结构关系可以从Hierarchy面板中看到。他还支持enumerators,以使用循环来遍寻所有的子节点。

Variables

position: Vector3  物体在世界坐标中的位置。 transform.position=Vector3(10,10,10)//把物体放到(x=10,y=10,z=10)的位置

localPosition: Vector3  相对位置,或自身位置,物体相对于父物体的位置。

eulerAngles: Vector3  轴向旋转角度,相对于世界坐标。单位为度(°)

localPosition: Vector3 相对轴向旋转角度,或自身的旋转角度,物体相对于父物体的旋转。一般使用和处理物体的旋转角度时都会使用到这个数值。

right: Vector3  物体自身的红色轴向(X轴)在世界坐标中所指向的位置。注意在maya中x轴指向物体的左边,而unity中的x轴则指向物体的右边。rigidbody.velotity=transform.right*moveSpeed;//向物体的右侧以moveSpeed的速度移动

up: Vector3  物体自身的绿色轴向(Y轴)在世界坐标中所指向的位置。

forward: Vector3  物体自身的蓝色轴向(Z轴)在世界坐标中所指向的位置。

rotation: Quaternion  以四元数来表达的物体自身的旋转。四元数可以快速的处理物体的旋转方向的计算,搭配Quaternion可以用来计算各种需要的旋转方案。具体应用方法参见Quaternion篇

localRotation: Quaternion 相对于父物体的用四元数来表达的旋转。

localScale: Vector3 物体相对于父物体的缩放

parent: Transform 物体的父物体。 如果没有则返回null。 如果改变父物体的位置,旋转和缩放,会同时影响并改变子物体的位置,旋转和缩放,但是保持相对位置,相对旋转和相对缩放。

worldToLocalMatrix: Matrix4x4 一个表达从世界坐标到相对坐标位置的四维矩阵,Read Only。 如果你对矩阵不是很了解,请使用Transform.InverseTransformPoint。

LocalToWorldMatrix: Matrix4x4 一个表达从相对坐标到世界坐标位置的四维矩阵,Read Only。 如果你对矩阵不是很了解,请使用Transform.TransformPoint。

root: Transform  返回物体的最高层的父物体。如果物体本身就是最高层,则返回物体本身。

childCount: Int   返回物体的子物体数量。

lossyScale:Vector3 返回物体相对于世界坐标的缩放值。 Read Only。没什么用的一个属性,当子物体被旋转后也不是特别精确,也不推荐大家用。如果想要计算物体的世界坐标缩放,最好自己写计算公式。


Functions
1)Translate, 用来移动物体的函数,非常常用的一个函数。
function Translate (translation : Vector3, relativeTo : Space = Space.Self) : void
把物体向translation方向移动,距离为translation.magnitude。 relativeTo表示这个移动的参考坐标系。
function Translate (x : float, y : float, z : float, relativeTo : Space = Space.Self) : void
同上
function Translate (translation : Vector3, relativeTo : Transform) : void
如果relativeTo 不是null, 则以目标物体relativeTo的自身轴向作为参考坐标系。
function Translate (x : float, y : float, z : float, relativeTo : Transform) : void
同上

脚本:
var speed=30;

//将物体以30米每秒的速度向前移动。
trasform.Translate(Vector3.forward*speed*Time.deltaTime);


2)Rotate,用来旋转物体的函数,非常常用,在知道需要旋转的角度的情况下。如果要让物体旋转到指定位置,需要搭配Quaternion来使用。
function Rotate (eulerAngles : Vector3, relativeTo : Space = Space.Self) : void
旋转eulerAngles度(3个轴向分别旋转),以relativeTo为参考坐标系
function Rotate (xAngle : float, yAngle : float, zAngle : float, relativeTo : Space = Space.Self) : void
同上
function Rotate (axis : Vector3, angle : float, relativeTo : Space = Space.Self) : void
以axis为轴旋转angle度,以relativeTo为参考坐标系

3)RotateAround 让物体以某一点为轴心成圆周运动。
function RotateAround (point : Vector3, axis : Vector3, angle : float) : void
让物体以point为中心,绕axis为轴向旋转angle度。 保持原来与point的距离。

4)LookAt 让物体的z轴看向目标物体
function LookAt (target : Transform, worldUp : Vector3 = Vector3.up) : void
让物体的z轴看向target的位置,并以worldUp为y轴指向方向。
function LookAt (worldPosition : Vector3, worldUp : Vector3 = Vector3.up) : void
让物体看向worldPosition

5)TransformDirection
function TransformDirection (direction : Vector3) : Vector3
返回以物体自身为坐标轴的向量direction在世界坐标中的朝向向量。
function TransformDirection (x : float, y : float, z : float) : Vector3
同上

6)InverseTransformDirection
function InverseTransformDirection (direction : Vector3) : Vector3
function InverseTransformDirection (x : float, y : float, z : float) : Vector3
与TransformDirection相反,从世界坐标转换到自身相对坐标。

7)TransformPoint
function TransformPoint (position : Vector3) : Vector3
function TransformPoint (x : float, y : float, z : float) : Vector3
把一个点从自身相对坐标转换到世界坐标

8)InverseTransformPoint
function InverseTransformPoint (position : Vector3) : Vector3
function InverseTransformPoint (x : float, y : float, z : float) : Vector3
把一个点从时间坐标转换到自身坐标的位置。

9)DetachChildren
function DetachChildren () : void
把自身所有的子物体的父物体都设成世界,也就是跟自己的所有子物体接触父子关系。

10)Find
function Find (name : string) : Transform
找到一个名字是name的物体并返回
如果没有找到则返回null。 如果字符串被/隔离,函数则会像文件路径一样逐级下查。


// The
magical rotating finger
function Update() {

aFinger = transform.Find("LeftShoulder/Arm/Hand/Finger");

aFinger.Rotate(Time.deltaTime*20,
0, 0);

}

11)IsChildOf
function IsChildOf (parent : Transform) : bool
如果物体是parent的父子层级关系下的一员,返回true;

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

评分

参与人数 1 +1 收起 理由
force0512 + 1 赞一个!

查看全部评分

 楼主| 发表于 2012-12-17 12:35 | 显示全部楼层
Physics
Class
Global physics properties and helper methods.

Physics 类包括整个场景的物理运算需要使用到的常量,还提供一些很有用的函数。



Class Variables
gravity   场景中所有刚体(rigidbody)所受到的重力加速度,也就是引力。默认应该是9.81好像。
rigidbody的移动速度可以使用rigidbody.AddForce()之类的函数来实现,AddForce就是给刚体增加一个力使它移动。力的公式为 F=ma。 大家要注意的两点就是很多人都在括号里填上的长度为5的向量就以为可以得到每秒5米的加速度,其实不然。 加速度要乘以刚体本身的重量rigidbody.mass才能得到相应的力。 而且这个加速度要记得加上9.81的加速度以抵消重力的影响,否则也无法移动物体。 也就是说如果你想给一个重量为50千克的刚体一个5米每秒的加速度,应该用一个5+9.81=14.81长度的向量乘以rigidbody.mass。 也就是说应该给一个长度为740.5的向量写在AddForce里。

minPenetrationForPenalty 最低的力的影响值,低于这个值的力将不会产生作用,必须为正数,默认值0.05

bounceThreshold 两个碰撞的物体(colliding objects)的相对速度如果低于这个值将不会产生反弹,必须为正数,默认值 2

sleepVelocity 默认的直线速度,小于这个速度的物体将会进入休眠状态,必须为正数,默认值 0.15

sleepAngularVelocity 默认的角速度,低于这个值的物体会进入休眠状态,必须为正数,默认值0.14

maxAngularVelocity 所有刚体的默认最大角速度,必须为正数, 默认值 7

solverterationCount 所有刚体默认求解的迭代次数,跟计算刚体移动的精确度有关系,必须为证,默认值 7

Class Functions
1)static function Raycast (origin : Vector3, direction : Vector3, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
在origin坐标上建立一个方向为direction,距离为distance的射线,可以与layerMask(层遮罩)之外的所有的collider碰撞;
返回true如果碰撞到任何物体,否则返回false。 distance默认为无限远,layerMast默认为kDefaultRaycastLayers
只与第一个接触到的物体产生碰撞。

static function Raycast (origin : Vector3, direction : Vector3, out hitInfo : RaycastHit, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
多了一个out hitInfo: RaycastHit, 如果碰撞到物体,具体碰撞数据和被碰撞体都会被记录在RaycastHit上,包括碰撞位置,碰撞位置法线,被碰撞体的Transform节点等信息。其他一样。

脚本:
var explosionPosition: Vector3;
var hit: RaycastHit;
if(Physics.Raycast(transform.position,target.position,hit,100)){
explosionPosition=hit.point;
}

static function Raycast (ray : Ray, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
static function Raycast (ray : Ray, out hitInfo : RaycastHit, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : bool
直接由一个射线ray来指示位置和方向。其他一样。

2)static function RaycastAll (ray : Ray, distance : float = Mathf.Infinity, layerMask : int = kDefaultRaycastLayers) : RaycastHit[]
static function RaycastAll (origin : Vector3, direction : Vector3, distance : float = Mathf.Infinity, layermask : int = kDefaultRaycastLayers) : RaycastHit[]

与所有在ray这条射线上的物体碰撞并返回所有被碰撞体,RaycastHit[]。 其他同RaycastAll一样。


3)static function Linecast (start : Vector3, end : Vector3, layerMask : int = kDefaultRaycastLayers) : bool
static function Linecast (start : Vector3, end : Vector3, out hitInfo : RaycastHit, layerMask : int = kDefaultRaycastLayers) : bool
从start到end画一条直线,其他与Raycast和RaycastAll类似。 这个通常可以用于检测AI是否能看到目标物体等功能。

4)static function OverlapSphere (position : Vector3, radius : float, layerMask : int = kAllLayers) : Collider[]
检测在position位置的半径radius的球形范围内是否存在可碰撞体并返回所有检测到的collider

5)static function CheckSphere (position : Vector3, radius : float, layerMask : int = kDefaultRaycastLayers) : bool
当任何物体碰到position位置的半径为radius的球形范围时返回true;

6)static function CheckCapsule (start : Vector3, end : Vector3, radius : float, layermask : int = kDefaultRaycastLayers) : bool

当任何物体碰到定义的胶囊体范围时返回true;

7)static function IgnoreCollision (collider1 : Collider, collider2 : Collider, ignore : bool = true) : void
控制collider1和collider2 是否可以碰撞。 ignore=true 两者将不会计算是否碰撞, ignore=false 则计算两者是否有碰撞。
 楼主| 发表于 2012-12-17 12:37 | 显示全部楼层

今天的目标是Vector3 和部分 Transform。 先说Vector3。

Vector3向量既可以用来表示位置,也可以用来表示方向。在数学与物理中,既有大小又有方向的量叫做向量(亦称矢量),与标量相对。

在立体三维坐标系中,分别取与x轴、y轴,z轴方向相同的3个单位向量i,j, k作为一组基底。若a为该坐标系内的任意向量,以坐标原点O为起点作向量OP=a。由空间基本定理知,有且只有一组实数(x,y, z),使得 a=向量OP=xi+yj+zk,因此把实数对(x,y, k)叫做向量a的坐标,记作a=(x,y, z)。这就是向量a的坐标表示。其中(x,y, k),也就是点P的坐标。向量OP称为点P的位置向量。

更多向量知识请参考 www.google.com

另外Vector2的函数Vector3都有了,而且作用基本一致,就不另说了。

向量Vector3 是我们最常打交道的一个类了。

首先是Vector3的变量
1)x,y,z  this[int index]
三个轴向,也可以用Vector3 i=[0,2]的整数来表示。

2)normalized (Read Only)
返回从坐标轴原点(0,0,0)到点P(x,y,z)的方向,向量的长度为 1。 也就是说返回的向量的点P(x,y,z)到原点(0,0,0)的距离为1。 这个很多时候被用来指示一个方向,然后再乘以想要的距离就可以得到我们想要的位置坐标。只能读取。

3)magnitude (Read Only)
返回向量的长度,也就是点P(x,y,z)到原点(0,0,0)的距离。 最常用的是用来返回物体的移动速度
speed=rigidbody.velocity.magnitude;

只能读取。如果想自行规定距离可以先normalized然后乘以距离
speed=speed.normalized*objSpeed;

4)sqrMagnitude (Read Only)
返回向量的长度的两次方。 大家知道向量的长度是用勾股定理计算出来的,计算机计算两次方和开跟的运算量比加减法要费时的多。所以如果是想比较两个向量的长度的话,用sqrMagnitude可以快很多。

函数
1)function Scale (scale : Vector3) : void
Description
Multiplies every component of this vector by the same component of scale.

所有的轴向都乘以scale

static function Scale (a : Vector3, b : Vector3) : Vector3
Description
Multiplies two vectors component-wise.

Every component in the result is a component of a multiplied by the same component of b.

把a的所有轴向都乘以b

2)function Normalize () : void
Description
Makes this vector have a magnitude of 1.

让向量的长度变成1

When normalized, a vector keeps the same direction but its length is 1.0.

当normalized, 向量的方向不会变但是长度会变成1,0

Note that this function will change the current vector. If you want to keep the current vector unchanged, use normalized variable.

这个函数会改变使用这个函数的向量,如果你不想改变这个向量,应该使用normalized

If this vector is too small to be normalized it will be set to zero

如果这个向量太小了,他不适合normalized并会被设置成zero (0,0,0)

3)function ToString () : string
Description
Returns a nicely formatted string for this vector

返回x,y,z的值,一般到小数点后一位。(0.0, 0.0, 0.0)

Class Variables

zero=(0,0,0)

one=(1,1,1)

forward=(0,0,1)

up=(0,1,0)

right=(1,0,0)

还有一个文档没写但也可以用的 left=(-1,0,0)

Class Functions

1)static function Lerp (from : Vector3, to : Vector3, t : float) : Vector3

Description
Linearly interpolates between two vectors.

Interpolates from towards to by amount t.

t is clamped between [0...1]. When t = 0 returns from. When t = 1 returns to. When t = 0.5 returns the average of from and to.

跟Quaternion里的lerp一样,返回from 和to之间的一个Vector3 点p  p=form+(to-form)*t    t[0,1]

2)static function Slerp (from : Vector3, to : Vector3, t : float) : Vector3

Description
Spherically interpolates between two vectors.

Interpolates from towards to by amount t. The returned vector's magnitude will be interpolated between magnitudes of from and to.

t is clamped between [0...1].

作用跟lerp差不多,但是不是呈直线靠近。

脚本:
var obj1: Transform;
var obj2: Transform;
var a: Vector3;
var b: Vector3;
var c=0.0;

a=Vector3.Lerp(obj1.position,obj2.position,c);
b=Vector3.Slerp(obj1.position,obj2.position,c);

if(Input.GetKeyDown("w"))
c+=0.1;
if(Input.GetKeyDown("s"))
c-=0.1;

输入: obj1.position=(0,0,0) obj2.position=(0,0,10)
输出:
c=0, a=(0,0,0), b=(0,0,0)
c=0.1 a=(0,0,1), b=(0,0,1)
c=0.5, a=(0,0,5), b=(0,0,5)
c=1, a=(0,0,10), b=(0,0,10)

当from在(0,0,0)的时候,两个函数的效果差不多。但是当from和to都不在原点的时候

输入: obj1.position=(0,10,0) obj2.position=(0,10,10)
输出:
c=0, a=(0,10,0), b=(0,10,0)
c=0.1 a=(0,10,1), b=(0,10.4,0.8)
c=0.5, a=(0,10,5), b=(0,11.2,4.6)
c=1, a=(0,10,10), b=(0,10,10)

我们可以看到两者之间出现了差异。
右图是两者移动轨迹的区别。

3)static function OrthoNormalize (ref normal : Vector3, ref tangent : Vector3) : void

Description
Makes vectors normalized and orthogonal to each other.

Normalizes normal. Normalizes tangent and makes sure it is orthogonal to normal (that is, angle between them is 90 degrees).

See Also: Normalize function.

这个函数读入两个向量normal和tangent, 使tangent 在由tangent 和normal构成的平面上,并与normal垂直。两个向量都被Normalize,也就是长度为1。大家可以用这个脚本在编辑器中看出这个函数是如何工作的。

脚本:
var obj1: Transform;
var obj2: Transform;
var a: Vector3;
var b: Vector3;
var c:Vector3;
var d: Vector3;

a=obj1.position;
b=obj2.position;
c=a;
d=b;
Vector3.OrthoNormalize(a,b);
Debug.DrawLine(Vector3.zero,c,Color.blue);
Debug.DrawLine(Vector3.zero,d,Color.white);
Debug.DrawLine(Vector3.zero,a,Color.red);
Debug.DrawLine(Vector3.zero,b,Color.green);


static function OrthoNormalize (ref normal : Vector3, ref tangent : Vector3, ref binormal : Vector3) : void
Description
Makes vectors normalized and orthogonal to each other.

Normalizes normal. Normalizes tangent and makes sure it is orthogonal to tangent. Normalizes binormal and makes sure it is orthogonal to both normal and tangent.

See Also: Normalize function.

这个用法多了一个向量binormal,这个向量同时垂直于normal和tangent,三者关系类似三维的直角坐标轴。其中binormal的方向决定binormal在那边垂直于normal和tangent。
脚本:
var obj1: Transform;
var obj2: Transform;
var a: Vector3;
var b: Vector3;
var c:Vector3;
var d: Vector3;

a=obj1.position;
b=obj2.position;
e=transform.position;
c=a;
d=b;
f=e;
Vector3.OrthoNormalize(a,b,e);
Debug.DrawLine(Vector3.zero,c,Color.yellow);
Debug.DrawLine(Vector3.zero,d,Color.white);
Debug.DrawLine(Vector3.zero,f,Color.black);
Debug.DrawLine(Vector3.zero,a,Color.red);
Debug.DrawLine(Vector3.zero,b,Color.green);
Debug.DrawLine(Vector3.zero,e,Color.blue);

4)static function RotateTowards (from : Vector3, to : Vector3, maxRadiansDelta : float, maxMagnitudeDelta : float) : Vector3
Description
Rotates a vector/from/ towards to.

The vector will be rotated on an arc instead of being interpolated linearly. This is essentially the same as Vector3.Slerp but instead the function will ensure that the angular speed and change of magnitude never exceeds maxRadiansDelta and maxMagnitudeDelta.

产生一个向量从from旋转并移动到 to,跟Vector3.Slerp类似,但是可以用maxRadiansDelta和max MagnitudeDelta分别控制向量的旋转方向和长度。当maxRadiansDelta=0时,向量指向from, 1则指向to。 当maxMagnitudeDelta=0时,向量的长度=from.magnitude,1则=to.magnitude。 向量的最大有效取值范围为1, 但是最小取值范围可以小于0

maxMagnitudeDelta, maxRadiansDelta [0,-∞]

当maxRadiansDelta和maxMagnitudeDelta为负时,向量会向相反方向旋转和延长。

5)function Scale (scale : Vector3) : void

Description
Multiplies every component of this vector by the same component of scale.

将两个向量的对应轴相乘。

a,b ∈Vector3

a.Scale(b);

a.x=a.x * b.x      a.y=a.y*b.y    a.z=a.z*b.z

static function Scale (a : Vector3, b : Vector3) : Vector3
Description
Multiplies two vectors component-wise.

Every component in the result is a component of a multiplied by the same component of b.

跟上一个差不多

a,b,c ∈Vector3

a=Vector3.Scale(b,c);

a.x=b.x * c.x    a.y=b.y*c.y    a.z=b.z*c.z

6)static function Cross (lhs : Vector3, rhs : Vector3) : Vector3

Description
Cross Product of two vectors.

Returns lhs x rhs.

两个向量的叉积,具体关于叉积的解释大家可以自己去网上搜搜,或点击传送门。

http://zh.wikipedia.org/zh/向量积

http://baike.baidu.com/view/865221.htm

a = a1i + a2j + a3k = [a1, a2, a3]
b = b1i + b2j + b3k = [b1, b2, b3]

a × b = [a2b3 − a3b2, a3b1 − a1b3, a1b2 − a2b1]

7)static function Reflect (inDirection : Vector3, inNormal : Vector3) : Vector3

Description
Reflects the vector along the normal.

The returned value is inDirection reflected from a surface with a normal inNormal.

又一个很常用的函数,返回一个向量,让这个向量与另一个向量inDirection以坐标轴inNormal为准镜像。

脚本:
var obj1: Transform;
var obj2: Transform;
var a: Vector3;
var d: Vector3;
var e: Vector3;
var f: Vector3;

a=obj1.position;
b=obj2.position;
e=Vector3.Reflect(a,Vector3.right);//以y轴,z轴组成的面为分割线,让a和e在x轴上镜像。
f=Vector3.Reflect(b,Vector3.right);
Debug.DrawLine(Vector3.zero,f,Color.black);
Debug.DrawLine(Vector3.zero,e,Color.blue);
Debug.DrawLine(Vector3.zero,a,Color.red);
Debug.DrawLine(Vector3.zero,b,Color.green);

8)static function Dot (lhs : Vector3, rhs : Vector3) : float
Description
Dot Product of two vectors.

Returns lhs . rhs.

For normalized vectors Dot returns 1 if they point in exactly the same direction; -1 if they point in completely opposite directions; and a number in between for other cases (e.g. Dot returns zero if vectors are perpendicular).

For vectors of arbitrary length the Dot return values are similar: they get larger when the angle between vectors decreases.

点积,跟quaternion里的用法一样。对于normalized后的lhs和rhs,如果指向相同的方向,返回1。返回-1如果他们指向完全相反的方向。其他情况下根据角度返回两者之间的小数。如果两个向量互相垂直,返回0;

  
点积
两个向量u,v的点积是一个标量,用u · v表示。通用公式:|u||v|cos<u,v>。在三维空间中代数公式:uxvx + uyvy + uzvz。(该公式可以先由二维证明,再推广到多维。二维中的证明:利用点线距公式和勾股定理推出|u|*cos<u,v>的表达式,再根据定义化简即可。)
点积的值由以下三个值确定:
u的大小v的大小u,v夹角的余弦。在u,v非零的前提下,点积如果为负,则u,v形成的角大于90度;如果为零,那么u,v垂直;如果为正,那么u,v形成的角为锐角。
点积得到两个向量的夹角的cos值,通过它可以知道两个向量的相似性,利用点积可判断一个多边形是否面向摄像机还是背向摄像机
一般情况下还是Vector3.Angle()这个函数用的比较多,两者的功能基本是一样的。

9)static function Project (vector : Vector3, onNormal : Vector3) : Vector3
Description
Projects a vector onto another vector.

Returns vector projected onto onNormal. Returns zero vector if onNormal is almost zero.

投射一个向量到另一个。

返回一个向量,这个向量由vector投射到onNormal。 返回0如果onNormal几乎等于或等于0;

具体工作原理可以通过这个脚本了解到

脚本:
var obj1: Transform;
var obj2: Transform;
var a: Vector3;
var b: Vector3;
var c: Vector3;

a=obj1.position;
b=obj2.position;
c=Vector3.Project(a,b);

Debug.DrawLine(Vector3.zero,c,Color.yellow);
Debug.DrawLine(a,c,Color.white);
Debug.DrawLine(Vector3.zero,a,Color.red);
Debug.DrawLine(Vector3.zero,b,Color.green);

当把obj2的位置设定为(0,1,0)的时候,大家就很容易看出这个函数是如何工作的了


10)static function Angle (from : Vector3, to : Vector3) : float

Description
Returns the angle in degrees between from and to.

这个基本上是我用的非常多的一个函数,用来确定两个向量指向的位置间的夹角

返回从from到to的夹角,单位为度。

我一般用这个来测量坦克之类的车辆的y轴和空间坐标y轴之间的夹角,阻止其登上大于固定角度的斜坡。或者ai只会看见正前方多少度内的敌人,因为他不应该拥有360度的视野。

11)static function Distance (a : Vector3, b : Vector3) : float

Description
Returns the distance between a and b.

Vector3.Distance(a,b) is the same as (a-b).magnitude

返回从a到b的距离

使用这个函数Vector3.Distance(a,b)的结果跟直接在两个向量间作减法(a-b)后求出的向量的长度是一样的。

也是非常非常常用到的一个函数。

12)static function Min (lhs : Vector3, rhs : Vector3) : Vector3

Description
Returns a vector that is made from the smallest components of lhs and rhs.

返回lhs和rhs中最小的那个向量

13)static function Max (lhs : Vector3, rhs : Vector3) : Vector3

Description
Returns a vector that is made from the largest components of lhs and rhs.

返回lhs和rhs中最大的那个向量

这两个也是很常用的。

14)operators

+ 和-

两个向量相加和相减

*和/

一个向量的所有轴乘以或除以一个float或int, 得到一个新的向量

==和!=

不知道的该打屁股

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
 楼主| 发表于 2012-12-17 12:38 | 显示全部楼层

今天准备学习和研究下unity3d的四元数 Quaternion

四元数在电脑图形学中用于表示物体的旋转,在unity中由x,y,z,w 表示四个值。

四元数是最简单的超复数。 复数是由实数加上元素 i 组成,其中i^2 = -1 \,。 相似地,四元数都是由实数加上三个元素 i、j、k 组成,而且它们有如下的关系: i^2 = j^2 = k^2 = ijk = -1 \, 每个四元数都是 1、i、j 和 k 的线性组合,即是四元数一般可表示为a + bi + cj + dk \,。

具体的四元数知识可从百度、维基等网站了解。

http://baike.baidu.com/view/319754.htm

现在只说说在unity3D中如何使用Quaternion来表达物体的旋转。

基本的旋转我们可以用脚本内置旋转函数transform.Rotate()来实现。

function Rotate (eulerAngles : Vector3, relativeTo : Space = Space.Self) : void

但是当我们希望对旋转角度进行一些计算的时候,就要用到四元数Quaternion了。我对高等数学来说就菜鸟一个,只能用最朴素的方法看效果了。

Quaternion的变量比较少也没什么可说的,大家一看都明白。唯一要说的就是x\y\z\w的取值范围是[-1,1],物体并不是旋转一周就所有数值回归初始值,而是两周。

初始值: (0,0,0,1)

沿着y轴旋转:180°(0,1,0,0) 360°(0,0,0,-1)540°(0,-1,0,0) 720°(0,0,0,1)

沿着x轴旋转:180°(-1,0,0,0) 360°(0,0,0,-1)540°(1,0,0,0) 720°(0,0,0,1)

无旋转的写法是Quaternion.identify

现在开始研究Quaternion的函数都有什么用。

函数

1)function ToAngleAxis (out angle : float, out axis : Vector3) : void

Description

Converts a rotation to angle-axis representation

这个函数的作用就是返回物体的旋转角度(物体的z轴和世界坐标z轴的夹角)和三维旋转轴的向量到变量out angle 和out axis

脚本:

var a=0.0;

var b=Vector3.zero;

transform.rotation.ToAngleAxis(a,b);

输入:transform.localEularAngles=(0,0,0);

输出: a=0, b=(1,0,0);

输入:transform.localEularAngles=(0,90,0);

输出:a=90, b=(0,1,0);

输入:transform.localEularAngles=(270,0,0);

输出:a=90, b=(-1,0,0)

2)function SetFromToRotation (fromDirection : Vector3, toDirection : Vector3) : void

Description

Creates a rotation which rotates from fromDirection to toDirection.

这个函数的作用是把物体的fromDirection旋转到toDirection

脚本:

var a:Vector3;

var b:Vector3;

var q:Quaternion;

var headUpDir:Vector3;

q.SetFromToRotation(a,b);

transform.rotation=q;

headUpDir=transform.TransformDirection(Vector3.Forward);

输入:a=Vector3(0,0,1); b=Vector3(0,1,0)//把z轴朝向y轴

输出: q=(-0.7,0,0,0.7); headUpDir=(0,1,0)

输入:a=Vector3(0,0,1); b=Vector3(1,0,0)//把z轴朝向x轴

输出: q=(0,0.7,0,0.7); headUpDir=(1,0,0)

输入:a=Vector3(0,1,0); b=Vector3(1,0,0)//把y轴朝向x轴

输出: q=(0,0,-0.7,0.7); headUpDir=(0,0,1)

3)function SetLookRotation (view : Vector3, up : Vector3 = Vector3.up) : void

Description

Creates a rotation that looks along forward with the the head upwards along upwards

Logs an error if the forward direction is zero.

这个函数建立一个旋转使z轴朝向view  y轴朝向up。这个功能让我想起了Maya里的一种摄像机lol,大家自己玩好了,很有趣。

脚本:

var obj1: Transform;

var obj2: Transform;

var q:Quaternion;

q.SetLookRotation(obj1.position, obj2.position);

transform.rotation=q;

然后大家拖动obj1和obj2就可以看到物体永远保持z轴朝向obj1, 并且以obj2的位置来保持y轴的倾斜度。

傻逗我玩了半天 哈哈^^ 这个功能挺实用的。

4)function ToString () : string

Description

Returns a nicely formatted string of the Quaternion

这个一般用不着吧?看不懂的一边查字典去~

Class Functions

1)四元数乘法 *

建议非特别了解的人群就不要用了。

作用很简单,c=a*b (c,a,b∈Quaternion)可以理解为 ∠c=∠a+∠b

但是a*b 和b*a效果不一样的。

2) == 和 !=

不解释了

3)static function Dot (a : Quaternion, b : Quaternion) : float

Description

The dot product between two rotations

点积,返回一个float. 感觉用处不大。Vector3.Angle()比较常用。

4)static function AngleAxis (angle : float, axis : Vector3) : Quaternion

Description

Creates a rotation which rotates angle degrees around axis.

物体沿指定轴向axis旋转角度angle, 很实用的一个函数也是。

脚本:

var obj1: Transform;

var obj2: Transform;

var q:Quaternion;

//物体沿obj2的z轴旋转,角度等于obj1的z轴。

q=Quaternion.AngleAxis(obj1.localEularAngle.z, obj2.TransformDirection(Vector3.forward));

transform.rotation=q;

5)static function FromToRotation (fromDirection : Vector3, toDirection : Vector3) : Quaternion

Description

Creates a rotation which rotates from fromDirection to toDirection.

Usually you use this to rotate a transform so that one of its axes eg. the y-axis - follows a target direction toDirection in world space.

跟SetFromToRotation差不多,区别是可以返回一个Quaternion。通常用来让transform的一个轴向(例如 y轴)与toDirection在世界坐标中同步。

6)static function LookRotation (forward : Vector3, upwards : Vector3 = Vector3.up) : Quaternion

Description

Creates a rotation that looks along forward with the the head upwards along upwards

Logs an error if the forward direction is zero.

跟SetLootRotation差不多,区别是可以返回一个Quaternion。

7)static function Slerp (from : Quaternion, to : Quaternion, t : float) : Quaternion

Description

Spherically interpolates from towards to by t.

从from 转换到to,移动距离为t。 也是很常用的一个函数,用法比较多,个人感觉比较难控制。当两个quaternion接近时,转换的速度会比较慢。

脚本:

var obj1: Transform;

var t=0.1;

var q:Quaternion;

//让物体旋转到与obj1相同的方向

q=Quaternion.Slerp(transform.rotation, obj1.rotation,t);

transform.rotation=q;

根据我个人推测,可能t 代表的是from 和to 之间距离的比例。 为此我做了实验并证明了这一点即:

q=Quaternion.Slerp(a,b,t);

q,a,b∈Quaternion

t[0,1]

q=a+(b-a)*t

并且t最大有效范围为0~1

脚本:

var obj1: Transform;

var obj2:Transform;

var t=0.1;

var q:Quaternion;

//让物体obj1和obj2 朝向不同的方向,然后改变t

q=Quaternion.Slerp(obj1.rotation, obj2.rotation,t);

transform.rotation=q;

t+=Input.GetAxis("horizontal")*0.1*Time.deltaTime;

7)static function Lerp (a : Quaternion, b : Quaternion, t : float) : Quaternion

Description

Interpolates from towards to by t and normalizes the result afterwards.

This is faster than Slerp but looks worse if the rotations are far apart

跟Slerp相似,且比Slerp快,.但是如果旋转角度相距很远则会看起来很差。

8)static function Inverse (rotation : Quaternion) : Quaternion

Description

Returns the Inverse of rotation.

返回与rotation相反的方向

9)static function Angle (a : Quaternion, b : Quaternion) : float

Description

Returns the angle in degrees between two rotations a and b.

计算两个旋转之间的夹角。跟Vector3.Angle() 作用一样。

10)static function Euler (x : float, y : float, z : float) : Quaternion

Description

Returns a rotation that rotates z degrees around the z axis, x degrees around the x axis, and y degrees around the y axis (in that order).

把旋转角度变成对应的Quaternion

以上就是Quaternion的所有函数了。

关于应用,就说一个,其他的有需要再补充。

Slerp 函数是非常常用的一个函数,用来产生旋转。

static function Slerp (from : Quaternion, to : Quaternion, t : float) : Quaternion

对于新手来说,最难的莫过于如何用它产生一个匀速的旋转。如果想用它产生匀速转动,最简单的办法就是把form和to固定,然后匀速增加t

脚本:

var obj1: Transform;

var obj2:Transform;

var speed:float;

var t=0.1;

var q:Quaternion;

q=Quaternion.Slerp(obj1.rotation, obj2.rotation,t);

transform.rotation=q;

t+=Time.deltaTime;

但是这并不能解决所有情况。 很多时候from 和to都不是固定的,而且上一个脚本也不能保证所有角度下的旋转速度一致。所以我写了这个脚本来保证可以应付大多数情况。

脚本:

var target: Transform;

var rotateSpeed=30.0;

var t=float;

var q:Quaternion;

var wantedRotation=Quaternion.FromToRotation(transform.position,target.position);

t=rotateSpeed/Quaternion.Angle(transform.rotation,wantedRotation)*Time.deltaTime;

q=Quaternion.Slerp(transform.rotation, target.rotation,t);

transform.rotation=q;

这个脚本可以保证物体的旋转速度永远是rotateSpeed。

第七行用旋转速度除以两者之间的夹角得到一个比例。

如果自身坐标和目标之间的夹角是X度,我们想以s=30度每秒的速度旋转到目标的方向,则每秒旋转的角度的比例为s/X。 再乘以每次旋转的时间Time.deltaTime我们就得到了用来匀速旋转的t值


发表于 2012-12-30 21:42 | 显示全部楼层
帮你顶一个  这些差不多  很基础啊  不错
发表于 2013-2-19 22:51 | 显示全部楼层
大大受益,感谢楼主啊
发表于 2013-4-15 23:31 | 显示全部楼层
谢谢楼主的分享
发表于 2013-5-3 10:58 | 显示全部楼层
mark一下~~ 很不错的内容 适合初学者
发表于 2014-3-6 21:29 | 显示全部楼层
顶一下,学习了,感谢楼主。。。。。。。。
发表于 2014-3-16 15:24 | 显示全部楼层
好文!很好,很强大;顶楼主了。。。。。。
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-12-22 17:07 , Processed in 0.109464 second(s), 32 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表