読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

Unityでベクトルを扱おう

今回の担当、大橋です。

Unityでのベクトル(Vector3)の扱い方をまとめてみました。
基礎的なことが中心になってます。
スクリプトはC#です。

ベクトルの作成

まずはベクトルの作成です。
引数にx、y、z各成分の値を指定して作成できます。
引数を省略すると、長さ0の(0, 0, 0)のベクトルになります。

// ベクトル(0, 0, 0)  
var vec1 = new Vector3 ();  
// ベクトル(1, 2, 3)  
var vec2 = new Vector3 (1f, 2f, 3f);  

ベクトルの足し算、引き算

ベクトルも足し算と引き算が出来ます。
2つのベクトルの各成分同士がそれぞれ加算、減算されます。

var vec1 = new Vector3 (1f, 2f, 3f);  
var vec2 = new Vector3 (1f, -1f, 2f);  
  
// 足し算  
var res1 = vec1 + vec2;  
Debug.Log (res1.ToString ());  
  
// 引き算  
var res2 = vec1 - vec2;  
Debug.Log (res2.ToString ());  

結果

res1:(2.0, 1.0, 5.0)  
res2:(0.0, 3.0, 1.0)  

ベクトルの長さを取得

ベクトルには「長さ」の概念があります。
長さはmagnitudeで取得できます。

var vec1 = new Vector3 (1f, 2f, 3f);  
  
float len = vec1.magnitude;  
Debug.Log ("len:" + len);  

結果

len:3.741657

ベクトルの長さを比較

複数のベクトルのVector3.magnitudeを比較することで、ベクトルの長さを比較できますが、
magnitudeの代わりにsqrMagnitudeを使った方が高速です。

ベクトルの長さを求める計算式には平方根(ルート)が含まれていますが、
sqrMagnitudeは平方根を求める前の値を取得できます。

平方根は比較的重い処理なので、平方根を求める前の値で比較した方が高速というわけです。
長さの大小の比較であれば、平方根を求める前の値でも問題ありません。
ただし、sqrMagnitudeの差が、そのまま長さの差ではないので注意です。

var vec1 = new Vector3 (1f, 2f, 3f);  
var vec2 = new Vector3 (1f, 1f, 2f);  
  
// magnitudで比較  
bool res1 = vec1.magnitude > vec2.magnitude;  
Debug.Log ("res1:" + res1);  
  
// sqrMagnitudeで比較(こちらの方が高速)  
bool res2 = vec1.sqrMagnitude > vec2.sqrMagnitude;  
Debug.Log ("res2:" + res2);  

結果

res1:True  
res2:True

ベクトルの長さを変える

ベクトルに対してfloat値を掛けたり、float値で割ったりすることで、
ベクトルの向きはそのままに、長さを変えることができます。

また、normalizedに対してfloat値を掛けることで、
ベクトルの長さがそのfloat値と同じになります。
normalizedは、そのベクトルの長さを1にしたベクトルです。

var vec1 = new Vector3 (1f, 2f, 3f);  
  
// 長さを2倍にする  
var res1 = vec1 * 2f;  
Debug.Log("res:" + res1 + ", len:" + vec1.magnitude + "->" + res1.magnitude);  
  
// 長さを1/2にする  
var res2 = vec1 / 2f;  
Debug.Log("res:" + res2 + ", len:" + vec1.magnitude + "->" + res2.magnitude);  
  
// 長さ5にする  
var res3 = vec1.normalized * 5;  
Debug.Log("res:" + res3 + ", len:" + vec1.magnitude + "->" + res3.magnitude);  

結果

res:(1.3, 2.7, 4.0), len:3.741657->5  
res:(1.3, 2.7, 4.0), len:3.741657->7.483315  
res:(1.3, 2.7, 4.0), len:3.741657->1.870829

2つのベクトルの角度差を求める

Vector3.Angle関数で2つのベクトル間の角度を求めることができます。
これによって求められる角度は0〜180です。

var vec1 = new Vector3 (1f, 0f, 0f);  
var vec2 = new Vector3 (-1f, 1f, 0f);  
  
float angle = Vector3.Angle (vec1, vec2);  
Debug.Log ("angle:" + angle);  

結果

angle:135

ベクトルを指定角度だけ回転させる

Quaternionをベクトルに掛けることで、ベクトルを回転させることができます。
回転の方向は、回転軸の向きに対してネジを締めるのとは逆方向に回転します。

var vec = new Vector3 (1f, 0f, 0f);  
  
// Y軸周りに45度だけ回転  
var res1 = Quaternion.Euler (0f, 45f, 0f) * vec;  
Debug.Log ("res1:" + res1);  

結果

res1:(0.7, 0.0, -0.7)

ベクトルを別のベクトルに向かって指定角度だけ回転させる

2つのベクトルがあり、一方のベクトルを、もう一方のベクトルに向かって指定角度だけ回転させたい場合、次のようなプログラムになります。

まず、Vector3.Crossで2つのベクトルに直交するベクトルを求め、
そのベクトルを軸にして、回転させたいベクトルを指定角度だけ回転させます。

var vec1 = new Vector3 (0f, 1f, 0f);  
var vec2 = new Vector3 (1f, 0f, 0f);  
  
// vec2をvec1に向かって30度回転させる  
var axis = Vector3.Cross (vec2, vec1);  
var res = Quaternion.AngleAxis (30f, axis) * vec2;  
  
Debug.Log ("res:" + res + ", angle:" + Vector3.Angle(vec1, vec2) + " -> " + Vector3.Angle(vec1, res));  

結果

res:(0.9, 0.5, 0.0), angle:90 -> 60