Unityのゲーム作成時に、スクリプトでよく使う便利な標準関数について書いていきます。
わたくしが個人的によく使う関数だけという可能性もありますが・・・・(^_^;)
ランダムな値を作りたい時はRandomクラス
Random.Range
まずは最小値と最大値を指定してランダム値を作成するRandom.Rangeメソッドです。
Random.Range(最小値, 最大値)
最小値から最大値までのランダム値を取得出来ます。
値がint型だった場合は最大値の値は含めずそれより下の数値になります。
float型だった場合は最大値も含みます。
1 2 3 4 5 6 | // 1が取得出来る Random.Range(0, 2); // 0.0~1.0の値が取得出来る Random.Range(0.0f, 1.0f); |
Random.value
Random.valueを使用すると0.0~1.0のランダム値を得られます。
0.0と1.0も取得出来ます。
1 2 3 4 | var randomValue = Random.value; Debug.Log (randomValue); |
Random.insideUnitCircle
Random.insideUnitCircleは半径1の円内部のランダムな点を取得出来ます。
取得出来るのはVector2の値になります。
1 2 3 4 | Vector2 randomValue = Random.insideUnitCircle; Debug.Log (randomValue); |
Random.insideUnitSphere
Random.insideUnitSphereは半径1の球内部のランダムな点を取得出来ます。
取得出来るのはVector3の値です。
1 2 3 4 | Vector3 randomValue = Random.insideUnitSphere; Debug.Log (randomValue); |
Random.rotation
Random.rotationはランダムな角度(Quaternion)を取得出来ます。
1 2 3 4 | Quaternion randomRot = Random.rotation; Debug.Log (randomRot.eulerAngles); |
滑らかに値を補間する時はMathf.Lerp
Mathf.Lerp(最初の値、次の値、割合)
最初の値と次の値との間での割合を指定し、その値を返します。
割合は0から1の間の小数点で指定します。
1 2 3 | Mathf.Lerp(0.0, 1.0, 0.5); |
であれば0.5を取得出来ます。
似たものとしてVector3.Lerpがあります。
3D空間の位置を滑らかに補間する場合はVector3.Lerp
Vector3.Lerp(Vector3, Vector3, 割合)
これを使うと、現在の位置から目的地までの距離を補間して、徐々に移動する事が出来ます。
1 2 3 | Vector3.Lerp(new Vector3(0, 0, 0), new Vector3(0, 5, 0), Time.deltaTime); |
であれば、Vector3(0, 0, 0)からVector3(0, 5, 0)まで1秒間で位置が変更されます。
割合は0~1の値で指定するので、Time.deltaTimeを指定すると0秒後はVector3(0, 0, 0)、1秒後にVector3(0, 5, 0)に完全になるので、Time.deltaTimeで少しづつ割合が増えるとその間が補間され、徐々に値が変わるという仕組みです。
1秒後ではなく0.5秒後にしたい場合は、割合に2をかけ
1 2 3 | Vector3.Lerp(new Vector3(0, 0, 0), new Vector3(0, 5, 0), Time.deltaTime * 2); |
とします。2倍の早さで割合が1になるので、その分早くVector3(0, 5, 0)に近づく事になります。
Vector3.Lerpは線形補間なのに対して、Vector3.Slerpは球状補間になるので、最初と最後がより緩やかになります。
Lerpで指定している所をSlerpに変えて実行時に確認するとわかりやすいです。
レイを飛ばし、ぶつかったゲームオブジェクトの情報を得るにはPhysics.Raycast
Physics.Raycast(レイ, レイが当たった先の情報, レイを飛ばす距離, レイヤーマスク)
見えない線を飛ばして、その先に指定したレイヤーのゲームオブジェクトがあるか?を調べる時に使用します。
レイは線を飛ばす最初の位置と方向を指定します。
レイが当たっていれば戻り値としてtrueを返します。
1 2 3 4 5 6 | // JavaScript var ray : Ray = new Ray(new Vector3(0, 0, 0), new Vector3(0, 1, 0)); // C# Ray ray = new Ray(new Vector3(0, 0, 0), new Vector3(0, 1, 0)); |
レイはRay型で作成し第1引数に最初の位置、第2引数に方向を指定します。
Physics.Raycastのレイの部分はRay型の引数ではなく、最初の位置と方向を別の引数として指定する事も出来ます。
例: Physics.Raycast(new Vector3(0, 0, 0), new Vector3(0, 1, 0), レイが当たった先の情報, レイを飛ばす距離, レイヤーマスク)
レイの当たった先の情報はRaycastHit型の変数を与えます。
Physics.Raycastで何らかのゲームオブジェクトにレイが当たっていた時はこの変数に情報が入ります。
RaycastHit型の変数をhitとしていた場合、当たった先の位置は
hit.point
当たった先の面の角度(表面の向いている方向)は
hit.normal
で取得でき、この二つの値をよく使います。
レイヤーを指定せず、何らかのゲームオブジェクトがあるかどうかは
Physics.Raycast(レイ, レイが当たった先の情報, レイを飛ばす距離)
だけで調べる事が出来ます。
1のレイヤーだけをレイの当たる対象とする場合は
Physics.Raycast(レイ, レイが当たった先の情報, レイを飛ばす距離, 1 << 1)
とレイヤー番号を1をレイヤー番号ビット数分左にシフトします。
8のレイヤーだけをレイの当たる対象とする場合は
Raycast(レイ, レイが当たった先の情報, レイを飛ばす距離, 1 << 8)
とします。
数字で指定すると解り辛いですね。
番号で指定するとわからないから名前でレイヤーを取得する場合はレイヤー番号1の名前をTestという名前にしていた場合は
LayerMask.NameToLayer(“Test”)
でTestレイヤーのレイヤーマスクを取得出来ます。
逆にレイヤー番号からレイヤー名を取得するには
LayerMask.LayerToName(1)
とします。
レイヤーマスクに指定するのは、対象外のレイヤーなのか対象のレイヤーなのかわからなくなってきました・・(^_^;)
レイヤーマスクなので、実際は対象のレイヤーでも対象外のレイヤーでもなく、それぞれのレイヤー番号を使用して作ったint値が入ります。
ここら辺は情報処理的な勉強してないと解り辛いかも・・・・。
上のやり方ではわかりづらいので、わかりやすいやり方をします。
Physics.Raycast(レイ, レイが当たった先の情報, レイを飛ばす距離, LayerMask.GetMask(“Test”))
とするとTestレイヤーのみをレイの対象にします。
Testレイヤーの他にTest2レイヤーも対象にする場合は
Physics.Raycast(レイ, レイが当たった先の情報, レイを飛ばす距離, LayerMask.GetMask(“Test”, “Test2”))
とします。
こちらで指定すればレイが当たった対象を指定すればいいのでわかりやすいですね。
Physics.Raycastと似たようなものに
Physics.Linecast(始点, 終点, レイが当たった先の情報, レイヤーマスク)
があります。
こちらは始点から終点までレイを飛ばし、目的のレイヤーのゲームオブジェクトがあるかどうかを調べます。
当たっていたら戻り値としてtrueを返します。
Physics.Raycastは始点と方向
Physics.Linecastは始点と終点
という違いがあるので注意してください。
また、C#で記述する場合
Physics.Raycast(レイ, out レイが当たった先の情報, レイを飛ばす距離, レイヤーマスク)
と『レイが当たった先の情報』の前に、『out』という記述が必要になりますので注意してください。
これはLinecastのRaycastHit型の変数の前にも必要になります。
オイラー角からクォータニオン型へ変換するならQuaternion.Euler
Quaternion.Euler(X軸, Y軸, Z軸)
Quaternion型で指定しなければいけないけれど、使う側としてはオイラー角がわかりやすいので、
オイラー角をクォータニオン型へ変換したい時に使います。
1 2 3 | transform.rotation = Quaternion.Euler(10, 10, 10); |
上の例では、ゲームオブジェクトの角度rotation(Quaternion型)を変更したいので、オイラー角で指定しクォータニオン型に変換しています。
キャラクターのオイラー角を直接変更するにはQuaternion.eulerAngles
Quaternion.eulerAngles = new Vector3(X軸, Y軸, Z軸)
1 2 3 | Quaternion.eulerAngles = new Vector3(10, 10, 10); |
上の例ではX軸、Y軸、Z軸の回転を10度にしています。
現在地から目的地に移動させるならVector3.MoveTowards
Vector3.MoveTowards(現在地, 目的地, 移動速度)
Vector3.Lerp等は現在地から目的地まで滑らかに移動させましたが、Vector3.MoveTowardsは一定速度で移動します。
その為、滑らかに移動させる場面ではない時はこちらを使った方が便利です。
現在地、目的地はVector3で指定します。
1 2 3 | Vector3.MoveTowards(new Vector3(1, 0, 0), new Vector3(5, 0, 2), Time.deltaTime); |
上の場合はVector3(1, 0, 0)からVector3(5, 0, 2)の地点に移動します。
キャラクターの向きを回転させるならQuaternion.RotateTowards
Quaternion.RotateTowards(現在の向き, 向かせたい向き, 回転速度)
現在向いている方向から、向かせたい方向に回転速度で回転していきます。
現在の向き、向かせたい向きはQuaternion型で指定します。
1 2 3 | Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(0, 30, 0), 45 * Time.deltaTime); |
上の例ではキャラクターの角度をY軸を30度に、1秒間に45度の回転速度で回転させます。
Y軸は上下の軸なので、そこを軸にして30度回転するのでキャラクターが30度横を向くように回転していきます。
特定のキャラクターの方向を向かせたいならTransform.LookAt
transform.LookAt(向かせたいキャラクターのTransform)
例えば敵を攻撃する場合に攻撃対象の敵の方向を向いてから剣を振る。
というような処理を作りたい場合、手っ取り早く敵の方向を向かせるなら敵のゲームオブジェクトが入っている参照変数をenemyとした場合。
1 2 3 | transform.LookAt(enemy.transform); |
とします。
また、向く方向だけでなくキャラクターの上向きの方向を指定したい場合は、第2引数を指定します。
例えば、地面のゲームオブジェクトのTransformをjimenとしていて、地面の向いている方向(Z軸)を上向きとして作っていた場合、地面の向いている方向はjimen.forward(Vector3)なので
1 2 3 | transform.LookAt(enemy.transform, jimen.forward); |
とすれば、敵の方向を向きつつ、体の上向きを地面の向いている方向jimen.forwardの向きにする事が出来ます。
その為、地面の傾きとキャラクターの傾きを合わせる事が出来ます。
特定の方向の角度を取得したい場合はQuaternion.LookRotation
Quaternion.LookRotation(特定の方向)
主人公キャラクターを敵の方向に向かせたい場合は、Transform.LookAtを使えば簡単に敵の方向を向かせる事が出来ますが、一気にそちらの方向を向いてしまいます。
徐々に敵の方向を向かせたい場合は、主人公キャラクターから敵の方向の角度をLookRotationで算出する必要があります。
敵のゲームオブジェクトをenemyとしていた場合は
1 2 3 | Quaternion.LookRotation(enemy.transform.position - transform.position); |
で、主人公からみた敵キャラクターの角度を取得します。
敵キャラクターの方向に主人公を向かせる方法は、以下のQuaternion.FromToRotationも参照してください。
主人公キャラと敵キャラとの角度を計算したい時はQuaternion.FromToRotation
Quaternion.FromToRotation(こちらの方向, 相手方の方向)
Unityのスクリプトリファレンスを見ると、こちらの方向から相手方の方向への回転を作成しますというように書いてあるんですが、
個人的な解釈では、こちらの方向を主人公キャラの向いている方向、相手方の方向を敵の向いている方向とした場合
向いている方向の差の角度を計算できるのかなと思います
例えば主人公キャラクターと敵キャラクターの角度を計算したい場合、敵キャラクターのゲームオブジェクトをenemyとして
Quaternion.RotateTowardsを使おうとすると
1 2 3 | Quaternion.RotateTowards(transform.rotation, enemy.transform.rotation, Time.deltaTime); |
で出来そうな気がしますが、enemy.transform.rotationは敵キャラクター自体の角度であり、
主人公キャラクターが敵キャラクターの角度になるだけで、敵キャラクターの方を向かせる事は出来ません。
そんな時にQuaternion.FromToRotationを使うと
1 2 3 4 5 6 | // JavaScript var : targetRot : Quaternion = Quaternion.FromToRotation(transform.forward, enemy.transform.position - transform.position); // C# Quaternion targetRot = Quaternion.FromToRotation(transform.forward, enemy.transform.position - transform.position); |
Quaternion.LookRotationを使うと
1 2 3 | Quaternion targetRot = Quaternion.LookRotation (enemy.transform.position - transform.position); |
で主人公と敵の角度が計算できるので
1 2 3 | transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRot, Time.deltaTime); |
で、主人公が敵キャラクターの方へ段々と向いていくようになります。
自分で書いていていまだに混乱していますが・・・(^_^;)
float値が同じかどうか判定する場合はMathf.Approximately
floatの値が同じかどうか判定したい時に==を使って、
1 2 3 4 5 6 7 | float test = 0.1f; if(test == (10f / 100f)) { Debug.Log("testは10/100と同値"); } |
とやりたくなりますが(わたくしは結構やってたかも?)、float値同士の比較をする時は正確な判定が出来ない事があるようです。
そんな時はMathf.Approximatelyを使って、
1 2 3 4 5 | if(Mathf.Approximately(test, (10f / 100f)) { Debug.Log("testは10/100と同値"); } |
とします。
便利な関数があれば追加していきます
Unityでスクリプトを組む時に便利でよく使うものを載せました。
便利な関数があれば追加していきます。