ベクトル
2次元ベクトル型
グラフィックスプログラミングでは、空間の座標や距離などを表すために、複数の数値要素を組み合わせた値を用います。Unity では 3DCG プログラミングに必要となる基本的な数学型を最初から提供しています。
物理学で大きさと向きを持った量のことをベクトルと呼び、この概念は数学や幾何学で広く応用されています。Unity を含め、線形代数学を扱う 3DCG プログラミングではベクトルに相当するデータが必要になります。しかし、難しく考える必要はありません。プログラミングの世界では、ベクトル型とは複数の数値要素からなるデータ型であり、技術者であれば配列と違いはありません。
Unity が提供するベクトル型は2つの要素からなる2次元ベクトル、3つの要素からなる3次元ベクトル、そして4つの要素からなる4次元ベクトルの3種類です。基本的に、他の一般的な 3DCG グラフィックス API で使われるベクトル型と共通しているでしょう。
X 要素と Y 要素からなる2次元ベクトルは UnityEngine.Vector2 構造体で表されます。
public struct Vector2
この構造体のコンストラクタはオーバーロードされており、各要素を初期化する値を指定できます。
public Vector2(float x, float y)
x パラメータには X 要素の値を、y パラメータには Y 要素の値を指定します。
各要素の値はフィールドで公開されています。X 要素の値は x フィールドから、Y 要素の値は y フィールドから設定または取得できます。
public float x
public float y
Vector2 構造体の値は、これらのフィールドを通して任意のタイミングで取得変更できます。各要素の値は float 型なので、コンストラクタやフィールドで浮動小数点数リテラルを指定する場合は F 接尾辞を忘れないでください。
using UnityEngine; public class Test : MonoBehaviour { void Start() { Vector2 v = new Vector2(765, 961); print("v=" + v); } }
コード1は Vector2 構造体の値をコンストラクタで初期化し、print() メソッドを使って「Console」ウィンドウに値を出力しています。このコードでは Vector2 型の v 変数を文字列で結合しているため、結果は v 変数の文字列表現、すなわち ToString() メソッドが返した文字列が使われます。実行結果を見れば、ベクトルの X 要素と Y 要素の値が出力されていることが確認できます。
3次元ベクトル型
X 要素、Y 要素、Z 要素からなる3次元ベクトルは UnityEngine.Vector3 構造体で表されます。機能的には Z 要素が増えた以外は Vector2 構造体と同じです。
public struct Vector3
この構造体のコンストラクタはオーバーロードされており、各要素を初期化する値を指定できます。
public Vector3(float x, float y, float z)
x パラメータには X 要素の値を、y パラメータには Y 要素の値を、z パラメータには Z 要素の値を指定します。
Vector2 構造体と同様、各要素の値はフィールドで公開されています。X 要素の値は x フィールドから、Y 要素の値は y フィールドから、Z 要素の値は z フィールドから設定または取得できます。
public float x
public float y
public float z
Vector3 構造体の値は、これらのフィールドを通して任意のタイミングで取得変更できます。
using UnityEngine; public class Test : MonoBehaviour { void Start() { Vector3 v = new Vector3(765, 961, 876); print("v=" + v); } }
コード2は Vector3 構造体の値をコンストラクタで初期化し、値を出力しています。実行結果を見れば、ベクトルの X 要素、Y 要素、Z 要素の値が出力されていることが確認できます。
4次元ベクトル型
X 要素、Y 要素、Z 要素、そして W 要素からなる4次元ベクトルは UnityEngine.Vector4 構造体で表されます。
public struct Vector4
この構造体のコンストラクタはオーバーロードされており、各要素を初期化する値を指定できます。
public Vector4(float x, float y, float z, float w)
x パラメータには X 要素の値を、y パラメータには Y 要素の値を、z パラメータには Z 要素の値、w パラメータには W 要素の値を、それぞれ指定します。
各要素の値はフィールドで公開されています。X 要素の値は x フィールドから、Y 要素の値は y フィールドから、Z 要素の値は z フィールドから、W 要素の値は w フィールドから設定または取得できます。
public float x
public float y
public float z
public float w
Vector4 構造体の値は、これらのフィールドを通して任意のタイミングで取得変更できます。
using UnityEngine; public class Test : MonoBehaviour { void Start() { Vector4 v = new Vector4(765, 961, 876, 1); print("v=" + v); } }
コード3は Vector4 構造体の値をコンストラクタで初期化し、値を出力しています。実行結果から、ベクトルの X 要素、Y 要素、Z 要素、そして W 要素の値が出力されていることが確認できます。
固定値の取得
ベクトルを表す各構造体は、ベクトルの初期値や基準値として用いられる標準的な値のいくつかを静的な読み取り専用プロパティで提供しています。コンストラクタで初期化するよりも、簡単かつ確実に値を取得できるため利用すると便利です。
全ての要素が 0 の状態のベクトルは zero プロパティで提供されています。これはパラメータを渡さない空のコンストラクタで作られる値と同じですが、ベクトルが 0 であるという意図をコード上で明示的に表すことができます。
public static Vector2 zero { get; }
public static Vector3 zero { get; }
public static Vector4 zero { get; }
zero プロパティは Vector2 構造体、Vector3 構造体、Vector4 構造体の、すべてのベクトル型で用意されています。ベクトルのすべての要素が 0 の状態の値を得られます。
using UnityEngine; public class Test : MonoBehaviour { void Start() { print("Vector2.zero=" + Vector2.zero); print("Vector3.zero=" + Vector3.zero); print("Vector4.zero=" + Vector4.zero); } }
同様に、すべての要素が 1 に設定されたベクトルは one プロパティから取得できます。
public static Vector2 one { get; }
public static Vector3 one { get; }
public static Vector4 one { get; }
one プロパティも、すべてのベクトル型で提供されています。
using UnityEngine; public class Test : MonoBehaviour { void Start() { print("Vector2.one=" + Vector2.one); print("Vector3.one=" + Vector3.one); print("Vector4.one=" + Vector4.one); } }
Vector2 構造体と Vector3 構造体には、これらのプロパティに加えて方向を表す単位ベクトルを返すプロパティも提供しています。
右(水平)方向を表すベクトルは right プロパティから取得できます。このプロパティから得られる値は X 要素の値が 1、それ以外が 0 のベクトルです。
public static Vector2 right { get; }
public static Vector3 right { get; }
同様に、上(垂直)方向を表すベクトルは up プロパティから取得できます。このプロパティから得られる値は Y 要素の値が 1、それ以外が 0 のベクトルです。
public static Vector2 up { get; }
public static Vector3 up { get; }
加えて3次元ベクトルでは前方向を表す forward プロパティが提供されています。このプロパティから得られる値は Z 要素の値が 1、それ以外が 0 のベクトルです。
public static Vector3 forward { get; }
これらの値は、しばしばベクトルの計算を行うときの基準となるため頻繁に利用される傾向があります。毎回 new 演算子を用いてコンストラクタから値を生成する必要はなく、上記の静的プロパティを使うと便利でしょう。
using UnityEngine; public class Test : MonoBehaviour { void Start() { print("right=" + Vector3.right); print("up=" + Vector3.up); print("forward=" + Vector3.forward); } }
コード6は Vector3 構造体の right プロパティ、up プロパティ、forward プロパティから得られたベクトルを出力しています。
ベクトルの大きさ
ベクトルの大きさは、すべてのベクトル型で共通して magnitude プロパティから取得できます。このプロパティは読み取り専用で、ベクトルに設定されている各要素の値からベクトルの大きさを計算して結果を返します。
public float magnitude { get; }
public float magnitude { get; }
public float magnitude { get; }
このプロパティから得られるベクトルの大きは、ベクトル要素の2乗和の平方根です。ベクトルは大きさと向きを情報として持っていますが、そこから大きさだけを取り出しすことができます。
using UnityEngine; public class Test : MonoBehaviour { void Start() { Vector2 v = new Vector2(3, 5); print(v + " Magnitude=" + v.magnitude); } }
コード7は Vector2 型のベクトルの大きさを出力しています。実行結果から X 要素の2乗と Y 要素の2乗を加算した結果(x * x + y * y)の平方根であることが確認できます。
ベクトルの大きさをどのように解釈し、何に利用するかはプログラム次第です。大きさ、長さ、強さなど、ベクトル型を使って表現するデータの種類によって意味は変わってきます。重要なのは、ベクトルの向きに関係なく、ベクトルの大きさだけを float 型の値として抽出できるという点です。例えば、異なる向きのベクトルを容易に比較できるようになります。
単位ベクトル
単位ベクトルは常にベクトルの大きさ、すなわち magnitude プロパティが 1 になるベクトルのことです。ベクトルの大きさを均一化することで、ベクトルの向きだけを抽出できます。単位ベクトルは、方向を表すベクトルとして利用できます。
任意のベクトルから単位ベクトルを取得するには、すべてのベクトル型で共通して normalized プロパティを用います。このプロパティは、現在のベクトルを単位ベクトルに変換した結果を返す読み取り専用プロパティです。
public Vector2 normalized { get; }
public Vector3 normalized { get; }
public Vector4 normalized { get; }
これらのプロパティから得られたベクトルの magnitude プロパティは常に 1 になります。
using UnityEngine; public class Test : MonoBehaviour { void Start() { Vector3 source = new Vector3(27, 34, 12); Vector3 normalized = source.normalized; float magnitude = normalized.magnitude; print("source=" + source); print("normalized=" + normalized); print("magnitude=" + magnitude); } }
コード8は適当な Vector3 構造体の値の normalized プロパティから単位ベクトルを取得し、その結果を出力しています。また、単位ベクトルの magnitude プロパティからベクトルの大きさを取得し、その結果が 1 であることも実行結果から確認できます。