UnityのC#でインスタンスを取得しよう

programing thumbnail

さて、ある程度基本的なプログラムが書けるようになってきたところで、もうちょっと実用的な事を覚えてみましょう。

この記事は本のように順を追って解説しています。この記事は途中のページになります。
この記事を見ていて、現在の状況がわからない場合や忘れてしまった事などが出てきたら↓のリンクから目次ページへ飛べますので立ち戻って見てください。

<インスタンスとは>

このサイトではオブジェクト指向を「設計図」と「実体」という風に例えています。

インスタンスというのはこの「実体」に当たるものです。

class(設計図)を元にしてインスタンス(実体)を作成し、様々な実体を扱う事によってゲームは構成されます。

実体になるという事はメモリに乗るという事です。

ところで、実体になっただけでは「そこにあるだけ」ですので、プログラムから制御したり、操作したい時には実体にアクセスしなければいけません。

インスタンスにアクセスするために、インスタンスを”捕まえる”必要があります。

このように実体をとらえて使用できるようにする事を「インスタンスを取得する」と言います。

今までの解説ではUnityが自動でインスタンスを取得してくれていましたが、今回は自分でclassのインスタンスを作ったり、取得したりしたいと思います。

<GetComponent>

コンポーネントのインスタンスについて

さて、以前の解説ではスクリプトをインスペクターウィンドウにドラッグ&ドロップでインスタンス化させていました。

attach script

↑のようにスクリプトをゲームオブジェクトに貼っつけるとこのスクリプトはコンポーネントとしてくっつき、実体化(インスタンス化)した状態になります

ところで以前の解説でCubeを右側に移動させていました。

move cube

この時、特に何もしていないにも関わらずtransformという変数が使え、変数の中に勝手に中身が入っていました。

これはUnityが全部自動でやってくれていた感じですが、このtransformには一体何のインスタンスが入っていたかと言うと↓コレですね。

transform scale

Uniyがtransformという変数を用意して、自動でTransformというコンポーネントのインスタンスを取得して変数の中に入れていてくれたわけです。

このようにコンポーネントのインスタンスを取得することによってそれにアクセスして使えるようになります。

transform.position += Vector3.right;

↑はコンポーネントにアクセスして操作していたわけですね。

今回はtransformのようにコンポーネントを自分で取得してみようと思います。

コンポーネントのインスタンスを取得しよう

まずは以前のようにCubeを作成してください。よくわからない方はこちらから

game-object-cube

さて、今現在、同じゲームオブジェクト内にくっついているコンポーネントでBox Colliderというものがあると思いますが、これを捕まえてみようと思います。

GetComponent

↑のように書いてみてください。そして、Cubeにこのスクリプトをくっつけてください。

BoxCollider box = null;

でBoxCollider型の変数boxを定義しています。

コンポーネントと同じ名前なのでわかりやすいですね。コンポーネントはclassでもあるので、型として定義する事ができます。

classを型にできるのはここで解説しています。

そして nullというものを代入しています。

これは何かというと「何もない」という意味です。

以前変数を箱と例えていましたから、この場合空(カラ)とも言えます。

そして、Debug.Logでboxの中身を表示させています。

box = GetComponent<BoxCollider>();

これはゲームオブジェクトについているコンポーネントを取得する命令です。

↑のように書いた場合、このスクリプトがくっついているゲームオブジェクトのコンポーネントを取得する事ができます。

この命令はMonoBehaviourを継承しているため使えます。< >の中に取得したいコンポーネントの型を指定します。

同じコンポーネントがいくつもついているどれを取ってくるのかわからないので同じコンポーネントを同じゲームオブジェクトにいくつもつけるのはやめておいたほうがいいかもしれません。どれを取ってくるかは端末次第になるので自分はうまく動いていていても違うPCとかだと動かなくなる危険性があります。

さて、これを実行してみると

get instance

最初Nullで何も入っていなかったのが、GetComponentで中身が入っていることがわかります。

これでboxの中にインスタンスを入れることができたのでboxからBoxColliderのコンポーネントにアクセスすることができます。

Point

・GetComponentはコンポーネントのインスタンスを取得できるよ!
・< > の中で指定した型のコンポーネントを捕まえられるよ!

スポンサーリンク

<GameObject.Find>

ゲームオブジェクトのインスタンスを取得しよう

さて、↑の例ではスクリプトを貼っつけたゲームオブジェクトのコンポーネントのインスタンスしか取ってこれませんでした。

ちなみにインスタンスのはすなわち実体であるので、何もコンポーネントだけがインスタンスを持つわけではありません。

ゲームオブジェクトにも実体(インスタンス)があります。

では他のゲームオブジェクトのインスタンスを取得してみましょう。

GameObject Find

↑のように書いてみてください。

削除していなければシーン上にDirectional Lightというゲームオブジェクトがいると思うのでそれを捕まえてみます。

GetComponentの時と同じように空の変数を用意します。GameObjectとなっていますね。

ゲームオブジェクトもclassから実体化されているので型として持つ事ができます

gと言う名前は適当です。

そして

g = GameObject.Find(ゲームオブジェクトの名前);

で指定した名前のゲームオブジェクトのインスタンスを取得する事ができます。

log Game Object Find

これで実行すると↑のようにちゃんと変数の中に入っているのがわかります。

別のゲームオブジェクトについているコンポーネントのインスタンスを取得しよう

さて、別のゲームオブジェクトをインスタンスを取得できたということは、そのゲームオブジェクトについているコンポーネントのインスタンスも取得する事ができます。

Game Object Find And GetComponent

Directional LightにはLightというコンポーネントがついていると思いますが、これのインスタンスを取得してみましょう。

すでにDirectional Lightを捕まえて変数gの中に突っ込んでいるので

g.GetComponent<Light>();

これでDirectional LightについているLightを捕まえることができます。

GetComponentは自身についているコンポーネントを捕まえる命令なのですが、「g.(ドット)」とすることによって、変数gにあるインスタンス(実体)にアクセスし、その中のGetComponentを呼んでいます。

gはGameObjectのインスタンスを格納しているので、「g.」はゲームオブジェクトのインスタンスにアクセスしている感じになります。

これにより「自身」にあたるのはCubeではなくDirectional Lightということになります。C#では「インスタンス.(ドット)」とすることでその実体の中身にアクセスすることができます。

例外とか色々ありますが、今は↑の認識でいいかなと思います。

指定した名前のゲームオブジェクトのインスタンスを取得し、アクセスすることによって、そのゲームオブジェクトについているコンポーネントのインスタンスにもアクセスできるようになるわけです。

さて、これによりシーン上に存在するどのゲームオブジェクトのコンポーネントでもアクセス可能になりました。

色々なことができるようになりそうです。

Point

・GameObject.Findでゲームオブジェクトのインスタンスを捕まえられるよ!
・インスタンス.(ドット)でその実体の中身にアクセスする事ができるよ!

<new>

さて、↑ではゲームオブジェクトとかコンポーネントとかUnityの機能で既に実体化しているインスタンスを捕まえていましたが、インスタンスは自分で作ることもできます。

new instance

さて↑のように書いてみてください。

Vector3と言うのはx,y,zの3つの数字を扱えるクラスになっています。

using UnityEngine;としているので最初からUnityが用意してくれているクラスを使用する事ができます。

Cubeを動かすときにも使用していましたね。

transform.position += Vector3.right;

↑はちょっと特別な使い方をしていますが、今回は普通のやり方をします。

Vector3にもnullを代入したいところなんですが、Vector3はnull非許容型といって、nullが入れることができないので、いきなりインスタンスをぶち込みます。

Vector3 v = new Vector3();

この部分ですね。

new 型名(); 

とすることでその型のインスタンスを作成することができます

Vector3というのはコンポーネントではないので、ゲームオブジェクトにくっつけてインスタンス化することができません。このようにコンポーネントではないclassはnewしてあげることによって実体を得るわけです。

(コンポーネントはclassだけど、classはコンポーネントとは限らない)

このようにclassのインスタンスを作成することによってその機能を使う事ができるようになります。

まぁ、今は様々な便利な機能を実体化して使う事ができるんだと覚えておいてください。

自分で作成したclassのインスタンスも作成する事もできます。

ちなみに、インスタンスを持っていない状態でアクセスしようとするとエラーになります。当たり前ですけど。

<値型と参照型>

さて、ここで疑問に思った方もいるかもしれません。GetComponentとかGameObject.Findとか、シーン上で既にインスタンス化(実体化)しているにも関わらず、それが入る変数(箱)を用意しています。

箱を用意するということはその分だけのメモリを確保するということになります。

シーン上でもメモリを使い、スクリプト上でもメモリを使い、食いすぎじゃないのか?ということですね。

安心してください。

変数の型によって値型と参照型というのに分かれます。

値型というのは呼んで字のごとく値をもつ型の事です。intとかfloatとかですね。絶対に箱の中に実体そのものが入っています。まぁ、今までのイメージ通りのものだと思ってもらって大丈夫です。

参照型というのはちょっと特殊なのですが、インスタンスの場所を示したものが入っています。要は箱の中に入っているのはインスタンスではなくインスタンスがある場所のメモと言えるかもしれません。先程から「インスタンスを取得する」と言っていましたが、これは「インスタンスを見つけてその場所をメモする」ということになります。

ちなみにclassは参照型になります。

コンポーネントは全てclassであり、GameObjectもclassなので、GetComponentもGameObject.Findも実体そのものを捕らえてきたわけではなく、メモリの場所を特定してその場所を伝えてきたという感じになります。

そのため、実体が複数存在するわけではなく、メモリも食いまくっていたわけではないことがわかります。

この値型と参照型というのは覚えておかないと、わりと厄介です。何故なら本当の実体を取り扱っているのか、実体の場所が記してあるメモを取り扱っているかで違うからです。また注意しなければならないときに解説しようと思いますが、頭の片隅に入れておいてください。

<まとめ>

さて、今回はインスタンスを取得したり、作ったりする方法について解説しました。色々なものを操作する上でインスタンスを理解しておくのは重要なので覚えておいてください。

Point

・nullは何もないという意味だよ!
・インスタンスは実体化しているものだよ!
・newでインスタンスを作る事ができるよ!
・型には値型と参照型があるよ!
・値型は実体そのものが入っているよ!
・参照型は「実体がある場所」を記したメモが入っているよ!

覚えておきたい

・GetComponent<型名>();
・GameObject.Find(“ゲームオブジェクト名”);



タイトルとURLをコピーしました