Unity で組んでみる


ゲームエンジン Unity の使い方の説明です (2011/10/3 新規作成)。

Unity / インストール / GameObject と Component / JavaScript / 戻る / トップページ


Unity

Unity は有名なゲームエンジンの一つで、 ワンソースから iOS, Android, PC, Web プレイヤー (Flash も対応予定)、 PS3、Wii、Xbox360 へと出力でき、物理演算や 3D グラフィック機能、 エディタも包括しています。 始めは iOS 向けがメインでしたが、使いやすさや 商用のゲームエンジンでは破格の安さなどで、 2010年あたりからゲーム機向けも含めて急速にシェアを拡大してきました。
 
Unity は基本機能は無料で使うことができ、誰でも簡単に短時間で 相応のクオリティのゲームを作ることができます。 無料版は制限がきつすぎて実質あまり使えないと言うことも ありません (モバイル機への出力は有料になってしまいますが)。 また、Assert Store を介して、グラフィックデータや プログラムモジュールを得られることも便利です。
 
なお、有償版は Unity Pro と呼ばれ、Unity に機能がプラスされたものに なります。Pro 版はプラグインを書くことで、特定のプラットフォーム向けに Unity にはない機能を補ったり、リアルな影描画ができるようになったりします。
 
まだまだ国内の Unity 情報が Web 上には少ないようなので、 自分が知ったことや調べたことを書き留めていこうと思います。

インストール

Unity の公式サイトは unity3d.com です。 日本語版のページ も 一応ありますが、更新があまり追いついていないようです (すでに 正式版になっている 3.0 系がリリース前の情報のまま)。
 
開発は Windows XP か Mac OS X Leopard 10.5 (Intel CPU) で 総合環境 (エディタ) である Unity Editor を使って行いますが、 スクリプトは通常のテキストエディタを使うこともできます。 スクリプトは .NET のオープンソースによる再実装である「Mono」を ベースにしており、標準では C# か JavaScript でコードを記述します ( 共通中間言語に変換して実行するので、iOS 上で動くアプリであっても)。
 
Unity の最新版は 3.4.1 で、 こちら から ダウンロードしたインストールプログラムを実行します。

GameObject と Component

プレイヤーキャラクターや敵キャラ、地形などは「GameObject」として Scene に配置します。
 
その GameObject は「Component」と呼ばれる機能部品が集まってできており、 自由に足すことができます。 どこにあるかを表す Transform は 全ての GameObject が持っている「Component」、 物理計算をさせるなら Rigidbody という「Component」を付けますし、 スクリプトさえも Component として「GameObject」に付けます。 この考え方は Unity の特徴でもあり、高い汎用性を誇っている点でも あるので忘れないようにしましょう。
 
ちなみに、見た目情報のない空っぽの「GameObject」もあるので、 スクリプトだけ置く場合はその Empty GameObject を作って、 スクリプト Component を付けます。

JavaScript での実装

C# でも実装できるのですが、私は JavaScript を使ったので、 ここでは JavaScript で説明を書いていきます。
 
Unity で使われる JavaScript 言語は JavaScript と呼ばれてはいますが、 実際は ECMAScript の独自拡張といったおもむきで、 Flash の開発言語である ActionScript に実は近いようです。 型宣言が可能で、標準関数は似た違う書き方を要し ( Math.sin ではなく Mathf.Sin、Math.random はなく Random.Range を使うなど)、 多次元配列の書き方が違い、動的な処理は弱めです。 また、GameObject などがインスタンスとなる、 オブジェクト指向的な処理になります。
 
スクリプトも GameObject と Component を基本に考えます。 GameObject も Component もクラスで定義されており、 様々な関数やフィールドがあらかじめ定義されています (クラスのドキュメントは こちら)。 Component の種類にスクリプトを自由に書けるものがあり、 1 つの .js ファイルがそのような 1 つのクラスとなります。 これを定義して GameObject に Component として足すことで、 各 GameObject にスクリプトを加えていきます。 なお、複数のスクリプト (複数の Component になる) を 1 つの GameObject に足すことも可能です。
 
GameObject インスタンスが複数の Component インスタンスを保持しており、 GameObject インスタンスから、GetComponent メソッドで Component の インスタンスを取得してそれに指示を与えることになります。 ですが、毎回インスタンスの取得をするのは非効率で面倒なので、 基本的な Component に関しては、GameObject インスタンスの フィールド値で参照できるようになっており、こちらを使うのが普通です。
	function Start () {
		// GameObject の参照
		print(gameObject);
		
		// その GameObject が持っている Transform の参照 (2つは同じ結果)
		print("gameObject.GetComponent(Transform)="+gameObject.GetComponent(Transform));
		print("gameObject.transform              ="+gameObject.transform);
	}
スクリプト自身も Component なので、スクリプトで宣言したり、 インスタンスを明示せずに (this. を書かずに) 参照する対象は、 そのスクリプトの Component インスタンスです。 GameObject インスタンスではない点に注意です。
	var field=3;
	
	function Start () {
		// フィールド値の参照 (2つは同じ結果)
		print("field     ="+field);
		print("this.field="+this.field);
		
		// メソッドの呼び出し (2つは同じ結果)
		MyFunction ();
		this.MyFunction ();
		
		// スクリプト Component (=this) が属している GameObject を取得する定義済みフィールド値 (2つは同じ結果)
		print("gameObject     ="+gameObject);
		print("this.gameObject="+this.gameObject);
	}
	
	function MyFunction () {
		print("function called");
	}
GameObject インスタンスからその保持する Component インスタンスを 取得する方法が Component クラスにも全く同様に用意されており、 スクリプト (Script Component インスタンス) から、その GameObject の 保持する他の Component インスタンスを直接引っ張ってこれます。 そのため便利なのですが、this が GameObject インスタンスと間違って 理解してしまうことが多いので、ご注意を。
	function Start () {
		// Transform の参照 (4つは同じ結果)
		print("this.gameObject.transform="+this.gameObject.transform);
		print("gameObject.transform     ="+gameObject.transform);
		print("this.transform           ="+this.transform);
		print("transform                ="+transform);
	}
スクリプトの Component クラスは、MonoBehaviour クラスを継承しており、 その定義済み関数をオーバーライドすることで、各機能を実現していきます。 オーバーライドはスクリプト上では単純にその名称で定義するだけで良いです。 インスタンス生成時に呼ばれる Awake()、毎フレーム呼ばれる Update()、 衝突発生時に呼ばれる OnCollisionEnter() などが良くオーバーライドされます。
	function Update () {
		if (Input.GetButtonDown ("Jump"))			// ジャンプボタンを押したら
		{
			rigidbody.AddForce (0.0, 300.0, 0.0);	// 高さ方向に力をかける
		}
	}

戻る