この時点までに プレハブ の概念について基本的なレベルで理解できているはずです。プレハブはゲームを通じて再利用できる、事前定義済みの ゲームオブジェクト と コンポーネント の集合です。もしプレハブが何か分からない場合は、プレハブ のより基本的な説明を参照してください。
プレハブは複雑なゲームオブジェクトをランタイムにインスタンス化したい場合に便利です。プレハブのインスタンス化の代替手段は 0 からコードを使用してゲームオブジェクトを作成することです。プレハブのインスタンス化はこの代替手段に比べて、以下を含む多くの長所があります。
プレハブの効果を説明するために、便利に使える基本的な場面を考えてみます。
このサンプルでは、コードからオブジェクトを作成する場合と比較して、プレハブ使用の利点を示しています。
最初に、コードからレンガの壁を作成します。
public class Instantiation : MonoBehaviour
{
void Start()
{
for (int y = 0; y < 5; y++)
{
for (int x = 0; x < 5; x++)
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.AddComponent<Rigidbody>();
cube.transform.position = new Vector3(x, y, 0);
}
}
}
}
もしコードを実行すると、再生モードのときにレンガの壁全体が見られます。個別のレンガの機能に関連する箇所が 2 行あります。 CreatePrimitive
の行と AddComponent
の行です。ここまではそう悪くはないですが、個々のレンガにはテクスチャがありません。ブロックに行いたいすべての追加のアクションは 1 行づつ必要となります。例えば、テクスチャ、摩擦、Rigidbody の mass (重量) の変更には追加の行が必要です。
もしプレハブを作成して、設定をあらかじめ行っておくと、1 行のコードを使えば各レンガの作成と設定ができます。これにより、もし変更を行いたい場合に大量のコードの保守と変更が不要となります。プレハブがあれば、変更を行って実行するのみです。コードの変更は必要ありません。
もし各レンガにプレハブを使用している場合、次のコードで壁が作成できます。
//ゲームオブジェクトをインスタンス化するため、インスタンス化はすべてのコンポーネントタイプを受け付けます。
public Transform brick;
void Start()
{
for (int y = 0; y < 5; y++)
{
for (int x = 0; x < 5; x++)
{
Instantiate(brick, new Vector3(x, y, 0), Quaternion.identity);
}
}
}
これはクリーンであるだけでなく再利用性も高いものです。キューブをインスタンス化する、とか Rigidbody を含む必要があるなどと、どこにも書いていません。このすべてはプレハブに定義されていてエディターで速やかに作成することができます。
さて、プレハブを作成してみましょう。エディターで以下のように行います。
Brick プレハブを作成したので、これをスクリプトの brick 変数にアタッチする必要があります。スクリプトを含む空のゲームオブジェクトを選択すると、インスペクター上で Brick 変数が表示されます。
次に Project ビューの Brick プレハブを Inspector 上の brick 変数にドラッグアンドドロップします。再生ボタンをクリックすると、プレハブを使って作成した壁が表示されます。
このワークフローは Unity で繰り返し使用できるものです。はじめは、なぜこの方法がそこまでよいのか分からないかもしれません。スクリプトから作成してもたった 2 行長いだけですから。
しかし、今はプレハブを使用しているので、プレハブの調整を数秒でできます。これらすべてのインスタンスの mass を変更したい場合はプレハブの Rigidbody を 1 回調整するだけです。すべてのインスタンスで Material を別のものに変更したい場合は使用するマテリアルをプレハブの上に 1 回ドラッグするだけです。摩擦を変更したい場合は、プレハブの Collider の Physic Material を変更するだけです。すべてのボックスに Particle System を追加したい場合は、プレハブに子を 1 回追加するだけです。
プレハブをこのシナリオで使用する方法は次のとおりです。
ロケットのゲームオブジェクトを完全にコードから作成する (手動でコンポーネントを追加しプロパティを設定する) こともできますが、プレハブをインスタンス化したほうがはるかに簡単です。ロケットのプレハブの複雑さに関わらず、1 行のコードでロケットのインスタンス化を行うことができます。プレハブをインスタンス化した後、さらに、インスタンス化したオブジェクトのプロパティを変更することができます (例えば、ロケットの Rigidbody の速度を設定するなど)。
あつかうのが容易である事とは別にして、プレハブは後から変更することができます。そのためロケットの作成時に、急いでトレイルパーティクルを加える必要はありません。後から追加すれば良いのです。トレイルを子ゲームオブジェクトとしてプレハブに追加すると、すべてのインスタンス化されたロケットに、トレイルのパーティクルが加えられます。そして最後に、インスペクター上で速やかにロケットプレハブのプロパティを微調整できるため、ゲームの調整が遥かに容易になります。
次のスクリプトでロケットを Instantiate() 関数を使用して発射する方法を示します。
//ロケットにリジッドボディを設定する必要があります。
//この方法では、ユーザーがリジッドボディなしでプレハブを割り当てることはできません。
public Rigidbody rocket;
public float speed = 10f;
void FireRocket ()
{
Rigidbody rocketClone = (Rigidbody) Instantiate(rocket, transform.position, transform.rotation);
rocketClone.velocity = transform.forward * speed;
// 他のコンポーネント/スクリプトの複製にもアクセスできます
rocketClone.GetComponent<MyRocketScript>().DoSomething();
}
// Ctrl かマウスを押し続けると、発射のメソッドを呼び出します
void Update ()
{
if (Input.GetButtonDown("Fire1"))
{
FireRocket();
}
}
完全にリギングされた敵キャラクターが死亡したとします。その場合、単にキャラクター上で死亡するアニメーションを再生して、通常、敵ロジックを処理していたすべてのスクリプトを無効にすることもできます。恐らく、スクリプトの一部を取り除き、死亡した敵に対して誰もこれ以上攻撃しないカスタム製のロジックを加え、他のクリーンアップタスクを処理する必要があります。
もっと良い方法は、無傷のキャラクターを直ちに削除して、インスタンス化された破壊されたプレハブで置き換えることです。これにより様々なことが簡単にできます。死亡したキャラクターに対して異なるマテリアルを適用したり、まったく異なるスクリプトをアタッチしたり、多数に分解されたオブジェクトを含むプレハブを生成して、バラバラになった敵を再現したり、または単純に変形したキャラクターを含むプレハブをインスタンス化することもできます。
いずれの方法であっても、1 回 Instantiate() を呼び出すだけでよく、正しいプレハブに結び付けて、それで完了です。
重要なことは、Instantiate() する破壊された物を元とは全く異なるオブジェクトで作成できることです。例えば、飛行機があったとすると、2 つのバージョンを作ります。ひとつは、Mesh Renderer および飛行機の物理挙動を実行するスクリプトを持つ飛行機です。モデルを 1 つのオブジェクトだけにすることで、ゲームはより高速に実行されます。なぜなら、モデルをより少ない三角形で作成でき、より少ないオブジェクトで構成されるため、小さいパーツを多く使用するよりも速くレンダリングができるからです。さらに飛行機が飛び回っている間はわざわざいくつかの部分に分ける必要性がありません。
破壊された飛行機のプレハブを作成するときに典型的なステップは以下のとおりです。
次の例は、これらのステップがどのようにコード内で形成されているかを示しています。
public GameObject wreck;
//例として、自動的に 3 秒後にゲームオブジェクトを爆破します。
IEnumerator Start()
{
yield return new WaitForSeconds(3);
KillSelf();
}
//Ctrl またはマウスを押したままにするときに、fire メソッドを呼び出します。
void KillSelf ()
{
// 同じ位置で、壊れたゲームオブジェクトをインスタンス化します
GameObject wreckClone = (GameObject) Instantiate(wreck, transform.position, transform.rotation);
// ときどき、このオブジェクトから壊れたものへ、いくつかの変数を
// 引き継ぐ必要があります。
wreckClone.GetComponent<MyScript>().someVariable = GetComponent<MyScript>().someVariable;
//自動的に削除します
Destroy(gameObject);
}
例えばたくさんのオブジェクトをグリッド状または円状に配置したいとします。既存の方法では、次のいずれかの方法をとります。
代わりにプレハブで Instantiate() を使用してください。このシナリオで、なぜゲームオブジェクトが役に立つのかはお判りでしょう。このシナリオのため必要なコードは次のとおりです。
//プレハブを円状にインスタンス化する
public GameObject prefab;
public int numberOfObjects = 20;
public float radius = 5f;
void Start()
{
for (int i = 0; i < numberOfObjects; i++)
{
float angle = i * Mathf.PI * 2 / numberOfObjects;
Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
Instantiate(prefab, pos, Quaternion.identity);
}
}
//プレハブをグリッド状にインスタンス化する
public GameObject prefab;
public float gridX = 5f;
public float gridY = 5f;
public float spacing = 2f;
void Start()
{
for (int y = 0; y < gridY; y++)
{
for (int x = 0; x < gridX; x++)
{
Vector3 pos = new Vector3(x, 0, y) * spacing;
Instantiate(prefab, pos, Quaternion.identity);
}
}
}
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.