Vector3 三维向量
结构体类型
表示 3D的 向量和点。
这个结构用于在 Unity 传递 3D 位置和方向。它包含向量运算的函数。
静态变量 | 值 |
---|---|
up | (0, 1, 0) |
down | (0, -1, 0) |
forward | (0, 0, 1) |
back | (0, 0, -1) |
left | (-1, 0, 0) |
right | (1, 0, 0) |
zero | (0, 0, 0) |
one | (1, 1, 1) |
变量 | 说明 |
---|---|
magnitude | 返回向量的长度(只读)。 |
normalized | 返回该向量方向上的长度为1的向量(只读)。 |
sqrMagnitude | 返回这个向量的长度的平方(只读)。 |
this[int] | 使用[0], [1], [2]分别访问该向量的 x, y, z 元素。 |
x | 向量的 x 元素 |
y | 向量的 y 元素 |
z | 向量的 z 元素 |
静态方法 | 说明 |
---|---|
Angle | 返回两个向量之间的夹角。 |
ClampMagnitude | 返回的向量的长度,最大不超过 maxLength 所指示的长度。 |
Distance | 返回两个点之间的距离。 |
Cross | 计算两个向量的叉乘。 |
Dot | 计算两个向量的点乘。 |
MoveTowards | 当前的地点移向目标。 |
Max | 返回一个由两个向量的最大元素组成的向量。 |
Min | 返回一个由两个向量的最小元素组成的向量。 |
Lerp | 两个点之间的线性插值。 |
LerpUnclamped | 两个向量之间的线性插值。该插值t在小于0或大于1时的返回值不会被限制。 |
Normalize | 使向量的长度为1。 |
Project | 投影一个向量到另一个向量。 |
ProjectOnPlane | 投影向量到一个平面上(由垂直到该平面的法线定义)。 |
Reflect | 沿着法线反射向量。 |
SmoothDamp | 随着时间的推移,逐渐改变一个向量朝向预期的目标。 |
RotateTowards | 当前的向量转向目标。 |
OrthoNormalize | 使向量规范化并且彼此相互垂直。 |
Scale | 两个矢量组件对应相乘。 |
Slerp | 在两个向量之间球形插值。 |
SlerpUnclamped | 在两个向量之间球形插值。该插值t在小于0或大于1时的返回值不会被限制。 |
Vector3.ClampMagnitude
返回原向量的拷贝,并且它的模最大不超过maxLength所指示的长度。也就是说,限制向量长度到一个特定的长度。
示例:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Vector3 centerPt;
public float radius;
void Update() {
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 newPos = transform.position + movement;
Vector3 offset = newPos - centerPt;
transform.position = centerPt + Vector3.ClampMagnitude(offset, radius);
}
}
Vector3.Dot 点乘
两个向量的点乘积。点积是一个浮点型的值,两个向量的长度相乘,然后乘以它们之间夹角的余弦值。对于normalized向量,如果他们指向在完全相同的方向,Dot返回1。如果他们指向完全相反的方向,返回-1。对于其他的情况返回一个数(例如:如果是垂直的Dot返回0)。
示例:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform other;
void Update() {
if (other) {
Vector3 forward = transform.TransformDirection(Vector3.forward);
Vector3 toOther = other.position - transform.position;
if (Vector3.Dot(forward, toOther) < 0)
print("The other transform is behind me!");
}
}
}
Vector3.Cross 叉乘
两个向量的交叉乘积。两个向量的叉积乘积结果在垂直于两个输入向量的三分之一个向量。结果的大小等于两个输入相乘,然后乘以输入向量之间的角度的正弦值。你可以确定的方向的结果向量使用“左手法则”。
示例:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
Vector3 GetNormal(Vector3 a, Vector3 b, Vector3 c) {
Vector3 side1 = b - a;
Vector3 side2 = c - a;
return Vector3.Cross(side1, side2).normalized;
}
}
Vector3.Lerp 线性差值
两个向量之间的线性插值。按照分数t在from到to之间插值。这是最常用的寻找一点沿一条线的两个端点之间一些分数的方式(例如,在那些点之间逐渐移动一个对象)。这分数是在范围[ 0…1]。t是夹在 [0…1]之间,当t = 0时,返回from,当t = 1时,返回to。当t = 0.5 返回from和to的中间点。
示例:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform startMarker;
public Transform endMarker;
public float speed = 1.0F;
private float startTime;
private float journeyLength;
void Start() {
startTime = Time.time;
journeyLength = Vector3.Distance(startMarker.position, endMarker.position);
}
void Update() {
float distCovered = (Time.time - startTime) * speed;
float fracJourney = distCovered / journeyLength;
transform.position = Vector3.Lerp(startMarker.position, endMarker.position, fracJourney);
}
}
Vector3.Slerp 球形差值
两个向量之间的弧形插值通过t数值在from和to之间插值。这与线性内插之间的不同(即, “线性插值” )是该向量被视为方向而不是空间中的点。返回的向量的方向是由角内插,其大小是from和to的幅度之间进行内插。
示例:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform sunrise;
public Transform sunset;
public float journeyTime = 1.0F;
private float startTime;
void Start() {
startTime = Time.time;
}
void Update() {
Vector3 center = (sunrise.position + sunset.position) * 0.5F;
center -= new Vector3(0, 1, 0);
Vector3 riseRelCenter = sunrise.position - center;
Vector3 setRelCenter = sunset.position - center;
float fracComplete = (Time.time - startTime) / journeyTime;
transform.position = Vector3.Slerp(riseRelCenter, setRelCenter, fracComplete);
transform.position += center;
}
}
Vector3.MoveTowards
当前的地点移向目标。这个函数的返回值是一个点maxdistancedelta单位更接近于目标/点沿着当前的和目标之间的线。如果目标是比maxdistancedelta /然后返回值将等于目标接近(即移动不会超过目标)。maxdistancedelta负值可以用来从目标推开该向量。
示例:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform target;
public float speed;
void Update() {
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(transform.position, target.position, step);
}
}
Vector3.SmoothDamp
随着时间的推移,逐渐改变一个向量朝向预期的目标。向量由一些像弹簧阻尼器函数平滑,这将永远不会超过。最常见的用途是相机平滑跟随。
示例:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform target;
public float smoothTime = 0.3F;
private Vector3 velocity = Vector3.zero;
void Update() {
Vector3 targetPosition = target.TransformPoint(new Vector3(0, 5, -10));
transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);
}
}
Vector3.RotateTowards 转向
当前的向量转向目标。
这个函数类似于MoveTowards除了将向量被视为一个方向,而不是一个位置上。当前向量将被旋转朝向目标方向由maxRadiansDelta的角度,虽然会恰好落在目标,而不是超过。如果当前的大小和目标的是不同的,那么结果的幅度将被线性地旋转过程中进行插值。如果一个负值用于maxRadiansDelta ,向量会转离目标/直到它指向完全相反的方向,然后停止。
示例:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Transform target;
public float speed;
void Update() {
Vector3 targetDir = target.position - transform.position;
float step = speed * Time.deltaTime;
Vector3 newDir = Vector3.RotateTowards(transform.forward, targetDir, step, 0.0F);
Debug.DrawRay(transform.position, newDir, Color.red);
transform.rotation = Quaternion.LookRotation(newDir);
}
}
源码
using System;
using System.Runtime.InteropServices;
using scm = System.ComponentModel;
using uei = UnityEngine.Internal;
namespace UnityEngine
{
// Representation of 3D vectors and points.
[StructLayout(LayoutKind.Sequential)]
public partial struct Vector3
{
public const float kEpsilon = 0.00001F;
// X component of the vector.
public float x;
// Y component of the vector.
public float y;
// Z component of the vector.
public float z;
// Linearly interpolates between two vectors.
public static Vector3 Lerp(Vector3 a, Vector3 b, float t)
{
t = Mathf.Clamp01(t);
return new Vector3(
a.x + (b.x - a.x) * t,
a.y + (b.y - a.y) * t,
a.z + (b.z - a.z) * t
);
}
// Linearly interpolates between two vectors without clamping the interpolant
public static Vector3 LerpUnclamped(Vector3 a, Vector3 b, float t)
{
return new Vector3(
a.x + (b.x - a.x) * t,
a.y + (b.y - a.y) * t,
a.z + (b.z - a.z) * t
);
}
// Moves a point /current/ in a straight line towards a /target/ point.
public static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta)
{
Vector3 toVector = target - current;
float dist = toVector.magnitude;
if (dist <= maxDistanceDelta || dist < float.Epsilon)
return target;
return current + toVector / dist * maxDistanceDelta;
}
[uei.ExcludeFromDocs]
public static Vector3 SmoothDamp(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime, float maxSpeed)
{
float deltaTime = Time.deltaTime;
return SmoothDamp(current, target, ref currentVelocity, smoothTime, maxSpeed, deltaTime);
}
[uei.ExcludeFromDocs]
public static Vector3 SmoothDamp(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime)
{
float deltaTime = Time.deltaTime;
float maxSpeed = Mathf.Infinity;
return SmoothDamp(current, target, ref currentVelocity, smoothTime, maxSpeed, deltaTime);
}
// Gradually changes a vector towards a desired goal over time.
public static Vector3 SmoothDamp(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime, [uei.DefaultValue("Mathf.Infinity")] float maxSpeed, [uei.DefaultValue("Time.deltaTime")] float deltaTime)
{
smoothTime = Mathf.Max(0.0001F, smoothTime);
float omega = 2F / smoothTime;
float x = omega * deltaTime;
float exp = 1F / (1F + x + 0.48F * x * x + 0.235F * x * x * x);
Vector3 change = current - target;
Vector3 originalTo = target;
float maxChange = maxSpeed * smoothTime;
change = Vector3.ClampMagnitude(change, maxChange);
target = current - change;
Vector3 temp = (currentVelocity + omega * change) * deltaTime;
currentVelocity = (currentVelocity - omega * temp) * exp;
Vector3 output = target + (change + temp) * exp;
if (Vector3.Dot(originalTo - current, output - originalTo) > 0)
{
output = originalTo;
currentVelocity = (output - originalTo) / deltaTime;
}
return output;
}
// Access the x, y, z components using [0], [1], [2] respectively.
public float this[int index]
{
get
{
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
default:
throw new IndexOutOfRangeException("Invalid Vector3 index!");
}
}
set
{
switch (index)
{
case 0: x = value; break;
case 1: y = value; break;
case 2: z = value; break;
default:
throw new IndexOutOfRangeException("Invalid Vector3 index!");
}
}
}
// Creates a new vector with given x, y, z components.
public Vector3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
// Creates a new vector with given x, y components and sets /z/ to zero.
public Vector3(float x, float y) { this.x = x; this.y = y; z = 0F; }
// Set x, y and z components of an existing Vector3.
public void Set(float newX, float newY, float newZ) { x = newX; y = newY; z = newZ; }
// Multiplies two vectors component-wise.
public static Vector3 Scale(Vector3 a, Vector3 b) { return new Vector3(a.x * b.x, a.y * b.y, a.z * b.z); }
// Multiplies every component of this vector by the same component of /scale/.
public void Scale(Vector3 scale) { x *= scale.x; y *= scale.y; z *= scale.z; }
// Cross Product of two vectors.
public static Vector3 Cross(Vector3 lhs, Vector3 rhs)
{
return new Vector3(
lhs.y * rhs.z - lhs.z * rhs.y,
lhs.z * rhs.x - lhs.x * rhs.z,
lhs.x * rhs.y - lhs.y * rhs.x);
}
// used to allow Vector3s to be used as keys in hash tables
public override int GetHashCode()
{
return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2);
}
// also required for being able to use Vector3s as keys in hash tables
public override bool Equals(object other)
{
if (!(other is Vector3)) return false;
Vector3 rhs = (Vector3)other;
return x.Equals(rhs.x) && y.Equals(rhs.y) && z.Equals(rhs.z);
}
// Reflects a vector off the plane defined by a normal.
public static Vector3 Reflect(Vector3 inDirection, Vector3 inNormal)
{
return -2F * Dot(inNormal, inDirection) * inNormal + inDirection;
}
// *undoc* --- we have normalized property now
public static Vector3 Normalize(Vector3 value)
{
float mag = Magnitude(value);
if (mag > kEpsilon)
return value / mag;
else
return zero;
}
// Makes this vector have a ::ref::magnitude of 1.
public void Normalize()
{
float mag = Magnitude(this);
if (mag > kEpsilon)
this = this / mag;
else
this = zero;
}
// Returns this vector with a ::ref::magnitude of 1 (RO).
public Vector3 normalized { get { return Vector3.Normalize(this); } }
// Dot Product of two vectors.
public static float Dot(Vector3 lhs, Vector3 rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; }
// Projects a vector onto another vector.
public static Vector3 Project(Vector3 vector, Vector3 onNormal)
{
float sqrMag = Dot(onNormal, onNormal);
if (sqrMag < Mathf.Epsilon)
return zero;
else
return onNormal * Dot(vector, onNormal) / sqrMag;
}
// Projects a vector onto a plane defined by a normal orthogonal to the plane.
public static Vector3 ProjectOnPlane(Vector3 vector, Vector3 planeNormal)
{
return vector - Project(vector, planeNormal);
}
// Returns the angle in degrees between /from/ and /to/. This is always the smallest
public static float Angle(Vector3 from, Vector3 to)
{
return Mathf.Acos(Mathf.Clamp(Vector3.Dot(from.normalized, to.normalized), -1F, 1F)) * Mathf.Rad2Deg;
}
// The smaller of the two possible angles between the two vectors is returned, therefore the result will never be greater than 180 degrees or smaller than -180 degrees.
// If you imagine the from and to vectors as lines on a piece of paper, both originating from the same point, then the /axis/ vector would point up out of the paper.
// The measured angle between the two vectors would be positive in a clockwise direction and negative in an anti-clockwise direction.
public static float SignedAngle(Vector3 from, Vector3 to, Vector3 axis)
{
Vector3 fromNorm = from.normalized, toNorm = to.normalized;
float unsignedAngle = Mathf.Acos(Mathf.Clamp(Vector3.Dot(fromNorm, toNorm), -1F, 1F)) * Mathf.Rad2Deg;
float sign = Mathf.Sign(Vector3.Dot(axis, Vector3.Cross(fromNorm, toNorm)));
return unsignedAngle * sign;
}
// Returns the distance between /a/ and /b/.
public static float Distance(Vector3 a, Vector3 b)
{
Vector3 vec = new Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
return Mathf.Sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
}
// Returns a copy of /vector/ with its magnitude clamped to /maxLength/.
public static Vector3 ClampMagnitude(Vector3 vector, float maxLength)
{
if (vector.sqrMagnitude > maxLength * maxLength)
return vector.normalized * maxLength;
return vector;
}
// *undoc* --- there's a property now
public static float Magnitude(Vector3 vector) { return Mathf.Sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z); }
// Returns the length of this vector (RO).
public float magnitude { get { return Mathf.Sqrt(x * x + y * y + z * z); } }
// *undoc* --- there's a property now
public static float SqrMagnitude(Vector3 vector) { return vector.x * vector.x + vector.y * vector.y + vector.z * vector.z; }
// Returns the squared length of this vector (RO).
public float sqrMagnitude { get { return x * x + y * y + z * z; } }
// Returns a vector that is made from the smallest components of two vectors.
public static Vector3 Min(Vector3 lhs, Vector3 rhs)
{
return new Vector3(Mathf.Min(lhs.x, rhs.x), Mathf.Min(lhs.y, rhs.y), Mathf.Min(lhs.z, rhs.z));
}
// Returns a vector that is made from the largest components of two vectors.
public static Vector3 Max(Vector3 lhs, Vector3 rhs)
{
return new Vector3(Mathf.Max(lhs.x, rhs.x), Mathf.Max(lhs.y, rhs.y), Mathf.Max(lhs.z, rhs.z));
}
static readonly Vector3 zeroVector = new Vector3(0F, 0F, 0F);
static readonly Vector3 oneVector = new Vector3(1F, 1F, 1F);
static readonly Vector3 upVector = new Vector3(0F, 1F, 0F);
static readonly Vector3 downVector = new Vector3(0F, -1F, 0F);
static readonly Vector3 leftVector = new Vector3(-1F, 0F, 0F);
static readonly Vector3 rightVector = new Vector3(1F, 0F, 0F);
static readonly Vector3 forwardVector = new Vector3(0F, 0F, 1F);
static readonly Vector3 backVector = new Vector3(0F, 0F, -1F);
static readonly Vector3 positiveInfinityVector = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
static readonly Vector3 negativeInfinityVector = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
// Shorthand for writing @@Vector3(0, 0, 0)@@
public static Vector3 zero { get { return zeroVector; } }
// Shorthand for writing @@Vector3(1, 1, 1)@@
public static Vector3 one { get { return oneVector; } }
// Shorthand for writing @@Vector3(0, 0, 1)@@
public static Vector3 forward { get { return forwardVector; } }
public static Vector3 back { get { return backVector; } }
// Shorthand for writing @@Vector3(0, 1, 0)@@
public static Vector3 up { get { return upVector; } }
public static Vector3 down { get { return downVector; } }
public static Vector3 left { get { return leftVector; } }
// Shorthand for writing @@Vector3(1, 0, 0)@@
public static Vector3 right { get { return rightVector; } }
// Shorthand for writing @@Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity)@@
public static Vector3 positiveInfinity { get { return positiveInfinityVector; } }
// Shorthand for writing @@Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity)@@
public static Vector3 negativeInfinity { get { return negativeInfinityVector; } }
// Adds two vectors.
public static Vector3 operator+(Vector3 a, Vector3 b) { return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z); }
// Subtracts one vector from another.
public static Vector3 operator-(Vector3 a, Vector3 b) { return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z); }
// Negates a vector.
public static Vector3 operator-(Vector3 a) { return new Vector3(-a.x, -a.y, -a.z); }
// Multiplies a vector by a number.
public static Vector3 operator*(Vector3 a, float d) { return new Vector3(a.x * d, a.y * d, a.z * d); }
// Multiplies a vector by a number.
public static Vector3 operator*(float d, Vector3 a) { return new Vector3(a.x * d, a.y * d, a.z * d); }
// Divides a vector by a number.
public static Vector3 operator/(Vector3 a, float d) { return new Vector3(a.x / d, a.y / d, a.z / d); }
// Returns true if the vectors are equal.
public static bool operator==(Vector3 lhs, Vector3 rhs)
{
// Returns false in the presence of NaN values.
return SqrMagnitude(lhs - rhs) < kEpsilon * kEpsilon;
}
// Returns true if vectors are different.
public static bool operator!=(Vector3 lhs, Vector3 rhs)
{
// Returns true in the presence of NaN values.
return !(lhs == rhs);
}
public override string ToString()
{
return UnityString.Format("({0:F1}, {1:F1}, {2:F1})", x, y, z);
}
public string ToString(string format)
{
return UnityString.Format("({0}, {1}, {2})", x.ToString(format), y.ToString(format), z.ToString(format));
}
[System.Obsolete("Use Vector3.forward instead.")]
public static Vector3 fwd { get { return new Vector3(0F, 0F, 1F); } }
[System.Obsolete("Use Vector3.Angle instead. AngleBetween uses radians instead of degrees and was deprecated for this reason")]
public static float AngleBetween(Vector3 from, Vector3 to) { return Mathf.Acos(Mathf.Clamp(Vector3.Dot(from.normalized, to.normalized), -1F, 1F)); }
[System.Obsolete("Use Vector3.ProjectOnPlane instead.")]
public static Vector3 Exclude(Vector3 excludeThis, Vector3 fromThat) { return ProjectOnPlane(fromThat, excludeThis); }
}
}
?