今週はスクリプトからゲームオブジェクトを動かす方法について学ぶ。
まず新規プロジェクトを作成する。
Cube を作成する。 Hierarchy ビュー上部にある Create メニューから Cube を選べばよい。
スクリプトを作成する。 Project ビュー上部にある Create メニューから Javascript を選べばよい。スクリプトファイルの名前は TestMotor としておこう。
スクリプトの内容は次のようにする。
function Update () {
transform.x = Mathf.Sin(Time.time * 2.0) * 5.0;
}
TestMortorスクリプトをドラッグ&ドロップで Cube に与える。
実行する。 Cube が左右に動けば成功。
「フレーム」とは……Unity におけるフレームと Update
Update 関数の中でゲームオブジェクトの状態を更新することで、動きを作りだすことができる。
動きを作り出す際に重要になるのが時間の概念。 Unity で時間を扱うには Time
クラスを使う。この中でも最も使用頻度が高いのが Time.time
と Time.deltaTime
.
Time.time - 開始時点からの時間(秒数)を得る。
Time.deltaTime - 前の Update から今の Update までの差分の時間(秒数)を得る。
何かを動かす場合、あるいは経過時間を計測する場合には、必ず Time.time
と Time.deltaTime
を使うようにしよう。
トランスフォーム (Transform) とは「変形」を意味する単語。 3D CG の文脈では、まあ単に変形の事を指して言うこともあるけど、たいていは位置・回転・スケーリングの3要素のことを指す。
Inspector 上ではこんな感じで表示されている。
これをスクリプトからアクセスする方法について解説する。
transform.position
経由でアクセスできる。いちばん簡単なのは、X, Y, Z のそれぞれの要素に別々にアクセスする方法。例えば次のコードのようにすると、秒間 1.5 の速度でX軸+方向へ移動する。
function Update () {
transform.position.x = Time.time * 1.5;
}
また Vector3
型の値を代入することでも更新できる(というかむしろこちらがスタンダードなアクセス方法)。上のコードと下のコードはまったく同じ動きをする。
function Update () {
transform.position = Vector3(Time.time * 1.5, 0, 0);
}
三角関数を使って縦にぴょんぴょん動かしてみよう。
function Update () {
transform.position.y = Mathf.Abs(Mathf.Sin(Time.time * 6.0));
}
transform.rotation
経由でアクセスできる……が、クオータニオンを使わなければならない。これがちょっと難しい。詳しくは次で解説する。
transform.localRotation
経由でアクセスできる。例えば次のようにすると横方向にブヨブヨと拡大縮小する。
function Update () {
transform.localScale.x = Mathf.Sin(Time.time * 6.0) + 1.5;
}
クオータニオンとは日本語で四元数とも呼ばれる数学上の概念。高校数学で虚数単位 i について習ったと思うけど(今は習わない?)、この虚数単位を i, j, k の3つにまで拡張したという恐ろしいもの。これは回転を表現するのに都合が良いということを、ちょっと昔の偉い人が見つけた。今では CG とか航空機の制御とか、そういう分野で必ず使われる概念になっている。
まあ数学的にどうこうという話はさておき、 Unity では Quaternion クラスに便利な道具が色々揃っているので、中身は知らなくても、どう使うのかさえ把握しておけばよい。
Quaternion.AngleAxis
を使うと、ある軸を中心にした回転を表現することができる。例えば次のようにするとY軸周りに秒間120度の角速度で回転する。
function Update () {
transform.rotation = Quaternion.AngleAxis(Time.time * 120.0, Vector3(0, 1, 0));
}
クオータニオンは掛け算によって回転を合成できるという便利な特性がある。例えば「Y軸周りに秒間120度の回転」と「X軸周りに秒間77度の回転」を合成するには次のようにする。
function Update () {
transform.rotation = Quaternion.AngleAxis(Time.time * 120.0, Vector3(0, 1, 0)) *
Quaternion.AngleAxis(Time.time * 77.0, Vector3(1, 0, 0));
}
回転というのは移動とは違って回転する順序によって結果が異なる(身近な物を手にとって、実際に回転させてみよう!)。なので、どういう順序で回転させるかがとても重要になる。
クオータニオンの掛け算によって回転を合成するとき、掛け算の右側が最初の回転、左側が次の回転として扱われる。例えば上の例では、X軸周りに回転してから、Y軸周りの回転が発生する。
回転の合成を使ったときに、イメージと異なる結果が得られたら、回転の順序が間違っていないかどうかを確かめるようにしよう。