【Unity】6.7 向量和Vector3类

分类:Unity、C#、VS2015 数组

建立日期:2016-04-20 学习

1、简介

在虚拟的游戏世界中,与3D有关的数学知识决定了游戏引擎如何计算和模拟出开发者以及玩家看到的每一帧画面。学习或者回想一下基础的3D有关的数学知识,能够帮助开发者对游戏引擎产生更深入的了解。 动画

2、向量

在数学中向量的定义是:既有大小又有方向的量叫做向量。在空间中,向量能够用一段有方向的线段来表示。 spa

向量在游戏开发过程当中的应用十分普遍,可用于描述具备大小和方向两个属性的物理量,例如物体运动的速度、加速度、摄像机观察方向、刚体受到的力等都是向量,所以向量是物理、动画、三维图形的基础。 设计

一、向量相关概念

·模:向量的长度。 3d

·标准化(Normalizing):保持方向不变,将向量的长度变为1。 code

·单位向量:长度为1的向量。 orm

·零向量:各份量均为0的向量。 对象

二、向量的运算 blog

(1)加减

向量的加法(减法)为各份量分别相加(相减)。在物理上能够用来计算两个力的台力,或者几个速度份量的叠加。

image

(2)数乘

向量与一个标量相乘称为数乘。数乘能够对向量的长度进行缩放,若是标量大于0,那么向量的方向不变;若标量小于0,则向量的方向会变为反方向。

(3)点乘

两个向量点相乘获得一个标量,数值等于两个向量长度相乘后再乘以两者夹角的余弦值。若是两个向量a,b均为单位向量,那么a.b等于向量b在向量a方向上的投影的长度(也等于向量a在向量b方向的投影)

image

经过两个向量点乘结果的符号能够快速地判断两个向量的夹角状况:

若u·v = 0,则向量u、v相互垂直。

若u·v > 0,则向量u、v夹角小于90°。

若u·v <0,则向量u、v夹角大于90°。

(4)叉乘

两个向量的叉乘获得一个新的向量,新向量垂直于原来的两个向量,并旦长度等于原向量长度相乘后再乘夹角的正弦值。

image

能够经过左手摆出上图所示的手势来判断叉乘结果的方向(使用左手是由于Unity里用的是左手坐标系)。假设有向量Result=a×b,将拇指朝向a的方向,食指指向b的方向,则中指指向的方向为叉乘结果的方向。

注意:叉乘不知足交换律,即a× b≠ b× a。

3、Vector3类

在Unity中,和向量有关的类有Vector二、Vector三、Vector4,分别对应不一样维度的向量,其中Vector3的使用最为普遍。

一、成员变量和方法

Vector3类的经常使用成员变量和方法以下:

x、y、z:向量的X份量、Y份量、Z份量。

normalized:获取单位化后的向量(只读)。

magnitude:获取向量长度(只读)。

sqrMagnitude获取向量长度的平方(只读)。

Cross():向量叉乘。

Dot():向量点乘。

Project():计算向量在另外一向量上的投影。

Angle():返回两个向量之间的夹角。

Distance():返回两个向量之间的距离。

运算符:+、-、*、/、==、!=

下面是Vector3类的—些应用示例。

二、示例1(Demo7_1_DistanceTest.unity)

该例子演示了如何计算两个位置之间的距离。其中other变量绑定的游戏对象的坐标为(50,50,50),脚本绑定的目标对象的坐标为(-2,-3.3,-10)。

在Distance.unity场景中使用了本示例的源文件,运行效果以下:

image

下面是该场景中使用的C#脚本代码(DistanceTest.cs文件):

using UnityEngine;
using System.Collections;
public class DistanceTest : MonoBehaviour
{
    public Transform other;
    void Start()
    {
        if (other != null)
        {
            var dist = Vector3.Distance(other.position, transform.position);
            print("Distance to other: " + dist);
        }
    }
}

三、示例2(Demo7_2_DirectionMove.unity)

该例子演示如何让游戏对象沿着指定的方向移动。

DirectionMove.cs的代码以下:

using UnityEngine;
using System.Collections;
public class DirectionMove : MonoBehaviour
{
    public Vector3 direction = Vector3.forward;//移动方向
    public float speed = 5.0f;//速度

    void Update()
    {
        transform.position += direction * speed * Time.deltaTime;
    }
}

四、示例3(Demo7_3_SqrMagnitude.unity)

该例子演示如何利用Vector3.sqrMagnitude来判断目标对象的距离是否小于触发距离,其中other变量的坐标为(-2,-3,-10),该脚本绑定的游戏对象的坐标为(-2,-3.3,-10)。

使用的脚本(SqrMagnitude.cs文件)代码以下:

using UnityEngine;
using System.Collections;
public class SqrMagnitude : MonoBehaviour
{
    public Transform other;   //目标物体的Transform
    public double closeDistance = 5.0;  // 触发距离
    void Update()
    {
        if (other)
        {
            var sqrLen = (other.position - transform.position).sqrMagnitude;
            // 使用Vector3.sqrMagnitude比Vector3.magnitude计算速度要快
            if (sqrLen < closeDistance * closeDistance)
            {
                print("目标物体已靠近!");
            }
        }
    }
}

五、示例4(Demo7_4_MoveToTarget.unity)

该例子演示对象从初始点平滑移动到目标点的动画,其中start变量绑定的对象坐标为(-3,-3,-10),end变量绑定的坐标为(-3,-3,20)。

使用的脚本(MoveToTarget.cs文件)代码以下:

using UnityEngine;
using System.Collections;
public class MoveToTarget : MonoBehaviour
{
    public Transform start; //初始位置
    public Transform end; //终点位置
    void Update()
    {
        transform.position = Vector3.Lerp(start.position, end.position, Time.time);
    }
}

六、示例5(Demo7_5_SunRiseAndDown.unity)

该例子演示如何利用Slerp插值方法模拟太阳升起和落下的过程。

使用的脚本(SunRiseAndDown.cs文件)代码以下:

using UnityEngine;
using System.Collections;
public class SunAndRise : MonoBehaviour
{
    public Transform sunrise;//升起位置
    public Transform sunset; //落下位置 
    public float journeyTime = 10.0f; //从升起到落下须要的时间,以秒为单位
    private float startTime; //用于记录开始的时间

    void Start()
    {
        startTime = Time.time; // 设置开始的时间
    }

    void Update()
    {
        var center = (sunrise.position + sunset.position) * 0.5f;//计算运行轨迹的圆心点
        center -= new Vector3(0, 1, 0);
        var riseRelCenter = sunrise.position - center;//升起位置到圆心的向量
        var setRelCenter = sunset.position - center; //落下位置到圆心的向量
        var fracComplete = (Time.time - startTime) / journeyTime;//计算用于插值的系数
        transform.position = Vector3.Slerp(riseRelCenter, setRelCenter, fracComplete);//Slerp插值
        transform.position += center;
    }
}

下面是该例子的运行效果:

image

4、矩阵

相向量同样,矩阵也是3D数学中十分重要基础。

一、矩阵的概念

m× n的矩阵是一个具备m行、n列的矩形数组,行数和列数分别为矩阵的维度。在游戏引擎中使用的矩阵一般为4×4矩阵,由于它能够描述向量的平移、旋转、缩放等全部的线性变换。

二、矩阵的计算

本身看其余参考资料吧。

三、Matrix4x4类

Unity使用Matrix4x4类来描述4×4矩阵。

更多介绍请参看其余参考资料。

5、奇次坐标

在3D数学中,齐次坐标就是将本来3维的向量(x,y,z)用4维向量(wx,wy,wz,w)来表示。引入齐次坐标的主要有以下目的:

一、可更好地区分向量和点。在三维空间中, (x,y,z)既能够表示点也能够表示份量,不便于区分,若是引入齐次坐标,则可使用(x,y,z,1)来表示坐标点,使用(x,y,z,0)来表示向量。

二、统—用矩阵乘法表示平移、旋转、缩放变换。若是使用3×3的矩阵,矩阵乘法只能表示旋转和缩放变换,没法表示平移变换。而在4D齐次空间中,可使用4×4的齐次矩阵来统一表示平移、旋转、缩放变换。

三、当份量w=0时能够用来表示无穷远的点。

齐次坐标是计算机图形学中一个很是重要的概念,可是在Unity中不多须要直接和它打交道,在编写一些shader可能会用到它,平时在脚本中主要仍是使用三维向量Vector3。Unity经过便利的接口设计将这一重要概念隐藏在了引擎后面。

相关文章
相关标签/搜索