Instantiating Prefabs at runtime
Manual     Reference     Scripting   
Unityマニュアル > ユーザガイド > ゲームプレイの作成 > 実行時のプレハブ生成

このドキュメントは有志により翻訳されたもので、オフィシャルではありません。オリジナルのページはこちら
This document is unofficially translated by users.Please see the original document here.

翻訳に関する修正など、ご連絡はこちらまで。
Please send e-mail to here, when you have any question about the translation.

実行時のプレハブ生成(Instantiating Prefabs at runtime)

Prefabsのコンセプトについて基本的なレベルを理解してから読み進めて ください。いくつかの既に定義されたゲームオブジェクト(GameObjects)コンポーネント(Components) はあなたのゲームで再利用可能です。プレハブが何かが解らない場合はプレハブの ページを読むことをお勧めします。

プレハブは複雑なゲームオブジェクトを実行時に生成したい場合、とても有効です。もうひとつの方法はプレハブをゲー ムオブジェクトからプログラムを用いて作り出す方法です。プレハブをインスタンス化することは後者の方法に対して多くの利点を持っています:

よくあるシナリオ(Common Scenarios)

プレハブの利点を説明するために、いくつかの基本的な場面を考えてみることにしましょう:

  1. 壁を1つの"レンガ"プレハブからなんども異なる位置に生成し作成する場合。
  2. ロケットランチャが発射した際に飛んでいくロケットプレハブを作成する。プレハブはメッシュ、リジッドボディ、コライダと、尻尾にパー ティクルシステムを持っています。
  3. 多くの場所を探索するロボット。完全に操作可能なロボットは破壊され壊れたロボットプレハブと差し替えられます。このプレハブはロボットの様 々な部品からなり、リジッドボディとパーティクルシステムが設定されます。この滴ニックによりロボットを多くの部品に分解し散らばらせることが、1行のプ ログラムで行えるようになります。

壁の生成(Building a wall)

ここではプレハブを使う利点を、プログラムでオブジェクト生成する場合と対比して説明します。

はじめにレンガの壁をプログラムで作ります。

function Start () {
for (var y = 0; y < 5; y++) {
for (var x = 0; x < 5; x++) {
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.AddComponent(Rigidbody);
cube.transform.position = Vector3 (x, y, 0);
}
}
}

このコードを実行すると、Play Modeに 入った瞬間に完全な壁が構築されることが確認できます。それぞれのレンガには2行の関連する命令があります: CreatePrimitive()の行と、AddComponent()の 行です。いまのところ、それほど悪く有りませんが、それぞれのレンガにはテクスチャが貼られていません。この先全てのアクション(テクスチャの変更、摩擦 や、リジッドボディの重さ設定など)はプログラム業を追加していかなければなりません。

プレハブを作りそれらの設定を事前に行っていた場合はどうでしょう。たった1行のコードを書けば生成と設定がそれぞ れの煉瓦について完了します。これは、多くのコード変更からあなたを開放します。プレハブを使うと、変更を行ってすぐ実行できます。コードの変更は必要あ りません。

プレハブをそれぞれのレンガに使用していれば、次のようなコードで壁を作成できます。

var cube : Transform;
function Start () {
for (var y = 0; y < 5; y++) {
for (var x = 0; x < 5; x++) {
var cube = Instantiate(cube, Vector3 (x, y, 0), Quaternion.identity);
}
}
}

これは、シンプルであるだけでなく、再利用も可能です。立方体を作っているや、リジッドボディであるなどといったこ とは、一切書かれていません。全てはプレハブで定義されています。プレハブはエディタで素早く作ることが可能です。

では、プレハブを作りましょう。エディタで次のようにして行ないます:

  1. GameObject->Create Other->Cube を 選びます。
  2. Component->Physics->Rigidbody を選びます。
  3. Assets->Create Prefab を選びます。
  4. Project Viewで名前を"Brick"に変更します。
  5. Hierarchy中の作成した立方体をドラッグし"Brick"プレハブの上にProject Viewでドロップします。
  6. プレハブを作成したら、Cubeを階層から削除しても大丈夫です。(WIndowsはDelete、 MacはCommand-Backspace)

これでレンガのプレハブが出来ました。これをcubeの 変数にスクリプト中で追加しましょう。スクリプトが付加されている空のゲームオブジェクトを選択します。新しい変数がインスペクタに"cube"という名 前で出現していることを確認してください。


変数はゲームオブジェクトかプレハブを受け付けます

次に"Brick"プレハブをプロジェクトビューからcube変数にドロップします。Playを押して壁がプレハブによって構成され ることを確認しましょう。

これは、Unityにおいてなんども繰り返す作業パターンです。これが何故それほどいいのか、はじめは不思議に思う でしょう。スクリプトで生成する場合と比べてコードは2行しか短く有りません。

しかし、プレハブを使っている今、あなたはプレハブを数秒で調整できます。インスタンス全部の質量(mass)を変 更したいとき、リジッドボディをプレハブで一度調整するだけです。異なるマテリアル (Material)をインスタンスに適用したければ、マテリアルをプレハブ上にドラッグするだけです。frictionを変更したけれ ば、異なる物理マテリアル(Physic Material)をプレハブの古来だで 選択します。パーティクルシステムを追加したい場合は、プレハブに子要素として1度追加するだけです。

ロケットと爆発のインスタンス化(Instantiating rockets & explosions)

プレハブは次のようにシナリオに適します:

  1. ロケットランチャは、ユーザが発射ボタンを押したときに、ロケットプレハブをインスタンス化します。
  2. ロケットは衝突すると爆発プレハブをインスタンス化します。この爆発プレハブはパーティクルシステム、徐々に消えていくライト、周りのゲーム オブジェクトにダメージを与えるスクリプトを含んでいます。

ロケットゲームオブジェクトを完全にコードから作成できるとしても、コンポーネントを追加したり属性を設定したりす ることは、プレハブで行うほうが遥かに簡単です。ロケットは1行のコードで初期化することが出来ます。ロケットのプレハブがどれほど複雑でも関係有りませ ん。インスタンス化したプレハブの属性を編集することも可能です(例えば、ロケットのリジッドボディに速度を設定するなど)

使い方を簡単にするだけでなく、プレハブは後で更新できます。もし、ロケットを作っているときに、すぐにパーティク ルを追加する必要はありません。後で行えばよいのです。ロケットプレハブの子要素にパーティクルを追加すれば、全てのロケットインスタンスはパーティクル を含むようになります。最後に、ロケットプレハブの属性はインスペクタで簡単に変更できます。これであなたのゲームをチューニングすることがとても簡単に なります。

このスクリプトはロケットをInstantiate()関 数でどのように発射するかを示します。

// Require the rocket to be a rigidbody.
// This way we the user can not assign a prefab without rigidbody
var rocket : Rigidbody;
var speed = 10.0;

function FireRocket () {
var rocketClone : Rigidbody = Instantiate(rocket, transform.position, transform.rotation);
rocketClone.velocity = transform.forward * speed;
// You can also acccess other components / scripts of the clone
rocketClone.GetComponent(MyRocketScript).DoSomething();
}

// Calls the fire method when holding down ctrl or mouse
function Update () {
if (Input.GetButtonDown("Fire1")) {
FireRocket();
}
}

キャラクタをラグドールや壊れたものに置き換える(Replacing a character with a ragdoll or wreck)

いま、あなたが敵を倒したと仮定しましょう。死のアニメーションを単純にキャラクタ上で再生し、敵のロジックを扱う全てのスクリプトを無効化するこ とが出来ます。おそらくいくつかのスクリプトを正しく取り除き、死んだ敵に誰も攻撃を加えないように、新たなロジックを追加しなければならないでしょう。 その他のクリーンアップも必要かもしれません。

よりよい方法は、敵を即座に消してしまい、壊れた敵プレハブと入れ替えてしまうことです。これは、非常に柔軟です。 死んだ敵キャラクタに異なるマテリアルを使用することが出来ます。全く違うスクリプトで、オブジェクトがバラバラに散らばる様子をシミュレートするプレハ ブを含めたり、ただの壊れたバージョンのオブジェクトと入れ替えたりが可能です。

これらのオプションはInstantiate()関 数を呼び出すだけで可能です。正しいプレハブを引っ張ってきてそれをセットするだけなのです!

覚えておくべき重要なことは、 Instantiate()に より作られた壊れたオブジェクトがオリジナルとは全く違うものに出来るということです。例えば、2つの異なるバーションの飛行機を作成します。1つのMesh Rendererと飛行機の物理動作を行うスクリプトを含むゲームオブジェクト。 モデルを1つのゲームオブジェクトとして持つことで、ゲームが速く動作します。モデルを少ない三角形と少ない部品で構成することで複雑なものよりも速く動 作させることが出来ます。飛行機が順調に楽しく飛んでいる間は、ばらばらになった部品を保持しておく必要はありません。

壊れた飛行機プレハブを作る通常の手順は:

  1. 好きなモデリングツールを用いて、飛行機を様々なパーツから作成します。
  2. 空のシーンを作成します。
  3. モデルをからのシーンにドラッグします
  4. 全てのパーツにリジッドボディを追加します。すべてを選択してComponent->Physics->Rigidbodyを クリックします。
  5. ボックス古来だを全てのパーツに追加します。すべてを選択してをクリックします。Component->Physics->Box Colliderをクリックします。
  6. 追加の特殊効果のために、煙のようなパーティクルシステムをゲームオブジェクトに子要素として追加します。それぞれのパーツに追加します。
  7. これで複数の爆発するパーツを持った飛行機が作成できました。それらは物理に従って分解され地上に落ちるでしょう。パーティクルシステムに よって煙の尾も再現されます。Playを押しモデルがどのように動作するかを確認しましょう。
  8. Assets->Create Prefabを選択します。
  9. 全ての飛行機パーツを含むゲームオブジェクトのルートをドラッグしプレハブにドロップします。
var wreck : GameObject;

// As an example, we turn the game object into a wreck after 3 seconds automatically
function Start () {
yield WaitForSeconds(3);
KillSelf();
}

// Calls the fire method when holding down ctrl or mouse
function KillSelf () {
// Instantiate the wreck game object at the same position we are at
var wreckClone = Instantiate(wreck, transform.position, transform.rotation);

// Sometimes we need to carry over some variables from this object
// to the wreck
wreckClone.GetComponent(MyScript).someVariable = GetComponent(MyScript).someVariable;

// Kill ourselves
Destroy(gameObject);
}

1人称視点シューティング(The First Person Shooter)チュートリアルはキャラクタをラグドールと置き換える方法を説明します。また、下半身を最後のアニメーション状態と一致させる方法につい ても説明します。チュートリアルは Tutorials ページで見つけることが出来ます。

オブジェクトを特定のパターンで配置(Placing a bunch of objects in a specific pattern)

格子や円形のパターンで多くのオブジェクトを配置したいとします。伝統的には次のように行われます:

  1. オブジェクトを完全にコードから作成する。これは大変です!スクリプトで値を入れることは遅く、非効率的です。
  2. リジッドなオブジェクトを作成し、シーン中でいくつか複製します。これも大変です。グリッド上に正しくオブジェクトを配置することは難しいで しょう。

Instantiate()とプレハブを変わりに使 いましょう! 何故プレハブがそれほど便利なのかが、このシナリオで解るでしょう。このシナリオに必要なコードは次のとおりです。:

// Instantiates a prefab in a circle

var prefab : GameObject;
var numberOfObjects = 20;
var radius = 5;

function Start () {
for (var i = 0; i < numberOfObjects; i++) {
var angle = i * Mathf.PI * 2 / numberOfObjects;
var pos = Vector3 (Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
Instantiate(prefab, pos, Quaternion.identity);
}
}
// Instantiates a prefab in a grid

var prefab : GameObject;
var gridX = 5;
var gridY = 5;
var spacing = 2.0;

function Start () {
for (var y = 0; y < gridY; y++) {
for (var x=0;x<gridX;x++) {
var pos = Vector3 (x, 0, y) * spacing;
Instantiate(prefab, pos, Quaternion.identity);
}
}
}