分类: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. 语法——原型prototype深入理解

    console.log('-----------------------------Object'); var obj = {}; console.log(obj.__proto__ === Obje ...

  2. java json与map互相转换(一)

      java json与map互相转换(一) CreationTime--2018年7月16日 Author:Marydon 1.准备工作 所需jar包:json-20180130.jar impor ...

  3. mysql从时间字符串中取出日期数据

    addtime='2016-09-03 18:12:44' substr(addtime,1,10)  as 创建日期 SUBSTR(string, string charcter, number o ...

  4. 在quartz的Job中获得Spring的WebApplicationContext或ServletContext

    有时候我们需要在web工程中定时器类里面获得spring的IOC容器,即WebApplicationContext,用它来获取实现了某接口的所有的bean,因为@Autowired貌似只能注入单个be ...

  5. mysql find_in_set

    select * from IpResourceInfo a where find_in_set(a.id,(SELECT group_concat(CAST(resourcesid AS char) ...

  6. 一个还不错的gridview 样式【Z】

    <style type="text/css"> <!-- .datable {background-color: #9FD6FF; color:#333333; ...

  7. Linux-静态库生成

    Linux上的静态库,其实是目标文件的归档文件.在Linux上创建静态库的步骤如下: 写源文件,通过 gcc -c xxx.c 生成目标文件. 用 ar 归档目标文件,生成静态库. 配合静态库,写一个 ...

  8. (原+转)使用anaconda遇到的问题

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6669434.html 使用anaconda怎么感觉都是问题啊.... 1. Intel MKL FAT ...

  9. tensorflow代码中的一个bug

    tensorflow-gpu版本号 pip show tensorflow-gpu Name: tensorflow-gpu Version: 1.11.0 Summary: TensorFlow i ...

  10. Oracle pl/sql导入sql文件,插入更新数据,中文乱码问题解决方案

    http://szh-java.iteye.com/blog/1869360 问题描述:用a.sql文件执行insert或update,不论是通过pl/sql还是sqlplus环境下执行,@文件名执行 ...