企画記事
【完全図解】超初心者でも大丈夫。話題のゲームエンジン「Unity」での3Dゲーム作成入門
●Index |
・UIと基本操作(物理エンジン) |
・物体を動かしてみる(スクリプト,入力処理) |
・インスタンスを生成する(プレファブ) |
・当たり判定と爆発処理 |
・敵の発生と文字表示 |
インスタンスの生成(下準備)
さて,ここまでの部分で,球が落ちて,立方体をキー操作で動かせるというところまでできました。
ただ,これがなにかのゲームになるかというと,ちょっと難しいものがあります。
多少はゲームっぽい雰囲気を出すため,上から落ちるだけだった球を,立方体から発射するように変更してみましょう。
下準備として,球が飛んでいくようにスクリプトを加えます。具体的には,毎フレーム前進するようなものになりますが,すでにキー操作のところで必要な処理はすべて出てきていますので,簡単にまとめましょう。
「Assets」メニューから,JavaScriptを生成して,moveBulletという名前を付けておきます。
中身には,
var translation =0.1;
function Update () {
transform.Translate (0, 0, translation);
}
というものを記述してMonoDevelopでセーブしておいてください。
先ほどと同様に,Projectビューにあるこのスクリプトをつまんで,HierarchyビューにあるSphereの上にドロップしてやります。これでSphereに関連付けられました。
実行すると,ポトリと落ちてきていた球体が画面の奥に向かって転がっていくようになります。
実行の様子:球体の移動
プレファブの作成
弾の処理などはインスタンスでなくても実現可能ですが,その場で使いたいオブジェクトをインスタンスとして作り出す方法は,今後あらゆる処理で使われるものですので覚えておく必要のあるものです。
さて,通常「インスタンス」というと「クラス」が対になるものですが,Unityでのクラスに相当するものがプレファブとなります。ここで,ようやく「Unityのキモ」となる「プレファブ」(Prefab)を使っていきます。
プレファブの作り方は簡単です。
AssetsメニューのCreateにプレファブの指定がありますので,そこから新しいプレファブを生成してください。名前はbulletにしておきましょう。
だいたい察しが付いている人も多いでしょうが,先ほど作ったSphereを,ここにドロップしてやります。
これで「bullet」というプレファブに,先ほど作ったような「飛んでいく赤い球」が定義されました。
あとは必要に応じて,このプレファブからインスタンスを生成してやればよいのですが,「必要に応じ」の部分を決めていませんでした。ここでは,「Spaceバーを押すと弾が出る」という仕様にしておきましょう。
ということで,キー入力部分を先に作ります。
キー入力を行う
すでにキー入力については,前の項目で実装しました。そこで使ったGetAxisはジョイスティック入力を模したものでした。PCでも方向キー(W/A/S/Dでも可)で操作できるものです。
同様に,ジョイスティックのボタンを模した入力オブジェクトも用意されているのですが,PC向けの標準キーアサインでは,トリガーボタンがCtrlキーに割り振られているなど,少々使いにくいので,今回のサンプルではキー入力(GetKey)を直接使うことにします。
とはいえ,公式のリファレンスでは,GetButtonのサンプルのほうが使いやすいので,そちらを参考にしつつ,入力部分だけ書き換えます。
公式リファレンスのスクリプトは以下のとおりです。
// Instantiates a projectile every 0.5 seconds,
// if the Fire1 button (default is Ctrl) is pressed.
var projectile : GameObject;
var fireRate : float = 0.5;
private var nextFire : float = 0.0;
function Update () {
if (Input.GetButton ("Fire1") && Time.time > nextFire) {
nextFire = Time.time + fireRate;
var clone : GameObject =
Instantiate(projectile, transform.position, transform.rotation) as GameObject;
}
}
ボタン入力だけでなく,ちゃんとクールタイムも考慮した実用的なサンプルになっていることが分かります。この例では,弾の発射から0.5秒経たないと次の弾が撃てないように設定されています。
このクールタイム処理では,「Time.time」という部分が目に付きますが,ここには,ゲームが開始されてからの時間が秒数で入っています。ボタンが押された時点での時間が,前の発射から0.5秒以上経過しているかどうかを調べて処理を進めているわけです。
ついでに,「Instantiate」という部分で弾のインスタンスを生成していることも分かります。まったく今回使うにはもってこいのサンプルです。
Instantiate(projectile, transform.position, transform.rotation) as GameObject;
という部分は,「projectile」で示されるプレファブからインスタンスを作成する命令です。後ろのパラメータで生成位置と角度を指定していることが分かります。
これを,walkPlayerスクリプトと組み合わせます。function Update()の内外で処理を書き写してください。
Input.GetButton ("Fire1")
の部分は,
Input.GetKey ("space")
に置き換えます。具体的には,以下のようになります(赤字が追加部分)。
// A very simplistic car driving on the x-z plane.
var speed : float = 10.0;
var rotationSpeed : float = 100.0;
var projectile : GameObject;
var fireRate : float = 0.5;
private var nextFire : float = 0.0;
function Update () {
// Get the horizontal and vertical axis.
// By default they are mapped to the arrow keys.
// The value is in the range -1 to 1
var translation : float = Input.GetAxis ("Vertical") * speed;
var rotation : float = Input.GetAxis ("Horizontal") * rotationSpeed;
// Make it move 10 meters per second instead of 10 meters per frame...
translation *= Time.deltaTime;
rotation *= Time.deltaTime;
// Move translation along the object's z-axis
transform.Translate (0, 0, translation);
// Rotate around our y-axis
transform.Rotate (0, rotation, 0);
if (Input.GetKey ("space") && Time.time > nextFire) {
nextFire = Time.time + fireRate;
var clone : GameObject =
Instantiate(projectile, transform.position, transform.rotation) as GameObject;
}
}
実行可能なサンプルは省略しますが,Unity Editorで入力している人はぜひ実行して試してみてください(なにも起きませんけど)。
先ほど追加したスクリプトを見ると,ちょっと気になる部分があったかと思うのですが,
var projectile : GameObject;
という部分はなにをしているのでしょうか。そもそも,プレファブはどうやって指定するのでしょうか。ここでは先ほど作った「bullet」を指定したいのですがどうすればいいのでしょう。
ここで,Unity Editorに戻って,HierarchyビューでPlayerを選択したうえでInspector部分を見ると,walkPlayerの部分に変化があることが分かります。スクリプト内のグローバル変数が表に出てきているのですが,そのなかで「Projective」の部分がありますね。値は,Noneになっていますが,横に選択肢を開く○ボタンも見えます。ここを押すと選択ウィンドウが表示され,bulletが指定できます。
これを指定して実行すると,ちゃんと「弾は」出てくるようになりました。
実行の様子:Spaceバーで弾の発射
……とはいうものの,弾が発生してはいても,明らかに予想どおりの動きをしていません。
ここで,先ほどローカル座標を絶対座標に変換する際に使った「Translate」を思い起こす人がいるかもしれません。ただ,Translateは,そのオブジェクトの位置自体を変更するものですので,今回は使えません。代わりに変換後の値だけを返すものとして,「TransformPoint」というものが用意されていますので,今回はそれを使用します。
自分の前方は,前にも出てきたとおりZ軸方向ですので,ローカル座標(0,0,1)の地点から弾を発射することにしましょう。
該当部分は,
Instantiate(projectile, transform.TransformPoint(0,0,1), transform.rotation) as GameObject;
のような指定になります。
実行の様子:Spaceバーで弾の発射(修正版)
これで,ちゃんと弾が発射されるようになりました。弾の反射率などがおかしくて,異様な挙動も見られるのですが,これはあとでPhysic MaterialのBounce2を調整してやることにしましょう。
- 関連タイトル:
Unity
- この記事のURL:
キーワード