分类:Unity、C#、VS2015

创建日期:2016-04-20

一、简介

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

二、向量

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

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

1、向量相关概念

·模:向量的长度。

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

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

·零向量:各分量均为0的向量。

2、向量的运算

(1)加减

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

(2)数乘

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

(3)点乘

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

通过两个向量点乘结果的符号可以快速地判断两个向量的夹角情况:

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

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

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

(4)叉乘

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

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

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

三、Vector3类

在Unity中,和向量有关的类有Vector2、Vector3、Vector4,分别对应不同维度的向量,其中Vector3的使用最为广泛。

1、成员变量和方法

Vector3类的常用成员变量和方法如下:

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

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

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

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

Cross():向量叉乘。

Dot():向量点乘。

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

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

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

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

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

2、示例1(Demo7_1_DistanceTest.unity)

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

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

下面是该场景中使用的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);
}
}
}

3、示例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;
}
}

4、示例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("目标物体已靠近!");
}
}
}
}

5、示例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);
}
}

6、示例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;
}
}

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

四、矩阵

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

1、矩阵的概念

m× n的矩阵是一个具有m行、n列的矩形数组,行数和列数分别为矩阵的维度。在游戏引擎中使用的矩阵通常为4×4矩阵,因为它可以描述向量的平移、旋转、缩放等所有的线性变换。

2、矩阵的计算

自己看其他参考资料吧。

3、Matrix4x4类

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

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

五、奇次坐标

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

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

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

3、当分量w=0时可以用来表示无穷远的点。

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

【Unity】6.7 向量和Vector3类的更多相关文章

  1. Unity学习之路——主要类

    学习https://blog.csdn.net/VRunSoftYanlz/article/details/78881752 1.Component类gameObject:组件附加的游戏对象.组件总是 ...

  2. 【Unity】6.6 Random类

    分类:Unity.C#.VS2015 创建日期:2016-04-20 一.简介 Unity引擎提供的Random类可以用来生成随机数.随机点或旋转角度. 1.成员变量 seed:设置用于随机数生成器的 ...

  3. Unity协程(Coroutine)管理类——TaskManager工具分享

    博客分类: Unity3D插件学习,工具分享 源码分析   Unity协程(Coroutine)管理类——TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处 ...

  4. 【Unity】6.5 Time类、Mathf类、Coroutine类

    分类:Unity.C#.VS2015 创建日期:2016-04-20 一.Time类 Unity引擎提供的Time类可获取和时间有关的信息.计算帧速率.调整时间流逝速度等. 1.成员变量 2.示例 ( ...

  5. Unity 自动生成组件索引类工具

    Unity 自动生成组件索引类工具 需求由来 我们在写UI类时 需要获取预设中的组件 joystick = transform.Find("joystick"); backgrou ...

  6. 【转】【Unity】实现全局管理类的几种方式

    本文原作者未知,转载自:http://blog.csdn.net/ycl295644/article/details/42458477 如何在Unity中实现全局管理类?由于Unity脚本的运行机制和 ...

  7. Unity中实现全局管理类的几种方式

    (搬运自我在SegmentFault的博客) 如何在Unity中实现全局管理类?由于Unity脚本的运行机制和面向组件编程(COP)的思想,实现起来和普通的方式略有差别. 第一种方式是使用静态类.适合 ...

  8. Unity API 解析(13)—— Vector3 类

    三维向量或三维坐标点 normalized —— 单位化向量 返回方向相同模长为1的向量 sqrMagnitude —— 模长平方 Scale —— 向量缩放 Angle —— 两向量夹角 Cross ...

  9. 【Unity】6.8 Quaternion类(四元数)

    分类:Unity.C#.VS2015 创建日期:2016-04-20 一.四元数的概念 四元数包含一个标量分量和-个三维向量分量,四元数Q可以记作: Q=[w,(x,y,z)] 在3D数学中使用单位四 ...

随机推荐

  1. V-rep中的加速度计与陀螺仪

    加速度计(Accelerometer) VREP的模型浏览器components→sensors中可以找到加速度计的模型,用于测量物体沿着世界坐标系三个坐标轴的加速度值. VREP中没有直接测量加速度 ...

  2. V-rep学习笔记:并联机构正逆运动学

    Solving the FK problem of simple kinematic chains is trivial (just apply the desired joint values to ...

  3. mysql在字符串中查找模式

    查看以电话号码138开头的电话 select  id, phone   from user  where phone  like '138%'

  4. Chrome 好玩的插件

    1 Lastpass : 用来把往各个网址的密码云端存储. 2 EditThisCookie  : 查看网页的Cookie 3 Postman Interceptor :  用来配合Postman 进 ...

  5. C#让控制台程序不显示闪退窗口的方法

    新建一个控制台程序,然后编译为 窗体程序.即可........

  6. HDU - 4198 Quick out of the Harbour (BFS+优先队列)

    Description Captain Clearbeard decided to go to the harbour for a few days so his crew could inspect ...

  7. ThinkPHP学习(二)

    书接前文. 我想前台填写内容,然后在后台保存一下,规划了一下前台要录入的内容,主要包括title.content两大内容.然后简单设计了一个前台页面(复杂的我得会啊),就在上篇文章的基础上直接加了: ...

  8. 【LeetCode】215. Kth Largest Element in an Array (2 solutions)

    Kth Largest Element in an Array Find the kth largest element in an unsorted array. Note that it is t ...

  9. 树莓派进阶之路 (016) - 通过595驱动4位LED显示系统时间

    模块图片,4位共阳极数码管. 我们使用树莓派wiringPi的库来通过74HC595驱动4位数码管: C 代码如下: #include <wiringPi.h> #include < ...

  10. 解决servlet-api包冲突问题(maven)

    问题描述:本人的项目是用Maven管理,而且用到了servlet3.0的技术,但是项目中用到servlet3.0的地方,总提示找不到类中的方法.很奇怪,在网上找到好多解决办法,综合一下终于解决了.现将 ...