質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.84%

  • Unity

    3229questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

FindObjectOfTypeについて教えてください。

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 160

tkmnusr

score 132

 前提・実現したいこと

FindObjectOfTypeはどういう関数かわからないので、教えていただけませんか?
Object.FindObjectOfTypeとありますが、
このObjectには、どういうものを指定すればよいのでしょうか?
できれば簡単なサンプルソースで説明していただけるとありがたいです。

 試したこと

なんとなくわかっていること。
・ヒエラルキー上のオブジェクトを全部走査するので重たい。

わかってないこと。
・Object.FindObjectOfTypeのObjectは何なのか。
・FindObjectOfType (Type type) 引数のtypeに何を指定するものなのか?
・何かしら見つけたものが戻り値として返ってくる。

すみません、書いてて気づきましたが、かなり理解できてません。
こちらのサイトを見ましたが、

スクリプトを参照して、スクリプトにアクセスするのがFindObjectOfTypeです。
スクリプト名.FindObjectOfType<スクリプト名>();

上記、左側のスクリプト名と、右側のスクリプト名、それぞれどういう風に指定すればよいかとかもわかりません。
「スクリプトを参照して、スクリプトにアクセスする」という意味もわかりません。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

Objectとは「Unity が参照できるすべてのオブジェクトの基本クラス」です。
Object - Unity スクリプトリファレンス

例えば人間も猫も雑草もコップも全て「物」であるように、
GameObjectもテクスチャも自作クラスも全部「Object」です。

(これは「そういう仕様になっているから」です。C#の「継承」を調べるとより深く分かるかと思います)


Object.FindObjectOfType<Object>の1つ目のObjectと2つ目のObjectは意味が違います。
1つ目(.の前)は「Objectクラスに実装されているよ」ということを意味します。

transformGetComponentが頭に何も付けなくても使えるように、
FindObjectOfTypeも前に何も付けなくても動作します。

但し前に何も付けない場合は返り値がObject型になります。 FindObjectOfType<GameObject>→GameObjectを探してObject型で返す。(見つけたオブジェクトをGameObject型として取り扱いたい場合は型変換が必要) GameObject.FindObjectOfType<GameObject>→GameObjectを探してGameObject型で返す。
→前に何も付けなくても<>内の型として返って来ます。

 
2つ目のObjectは探してくるクラスを指定します。

FindObjectOfType<GameObject>ならGameObjectを探す、
FindObjectOfType<SampleScript>ならSampleScriptを探す、
FindObjectOfType<Object>ならObjectを探します。
(シーン上にある該当する物の中からUnityが適当に選んだ1つが返ります。1つも存在していなかったらnullが返ります)


ゲームオブジェクトを参照して、スクリプトにアクセスするのがGetCompornetで、
スクリプトを参照して、スクリプトにアクセスするのがFindObjectOfTypeです。

参照=探し出す、そのオブジェクトを対象とする、というイメージです。

「田中さんを参照して、田中さんの個人情報にアクセスする」のがGetCompornet。
「その場に居る誰かの個人情報を参照して(誰の物かは指定出来ない)、その個人情報にアクセスする」のがFindObjectOfTypeです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/17 11:12

    回答書いてる間にfiveHundredさんが回答されてますが
    言ってることは同じです。被り申し訳無い。

    キャンセル

  • 2018/05/18 00:06

    ご回答ありがとうございます。
    まず、Object.FindObjectOfType<Object>の1つ目のObjectに関して理解できました。
    そして、なんとなく使い方がわかったのでいろいろコードを書いて試してみました。
    確認させていただきたいのですが、
    Object.FindObjectOfType<Object>の2つ目のObjectは、クラスを指定するとのことですが、これは言い換えると、コンポーネントを指定するということでしょうか?
    FindObjectOfType<T>()のTは、GetComponent<T>()のTと同じようにクラス(コンポーネント)を指定するということでしょうか?
    GetComponent<T>()が、その1つのゲームオブジェクトを対象にアタッチしているTのクラス(コンポーネント)を取得しようとするのに対し、FindObjectOfType<T>()は、シーン上の全てのゲームオブジェクトを対象に、最初に見つかったアタッチしているTのクラス(コンポーネント)を取得しようとするということでしょうか?

    キャンセル

  • 2018/05/18 11:43

    >コンポーネントを指定するということでしょうか?
    その通りです。

    >最初に見つかったアタッチしているTのクラス(コンポーネント)を取得しようとする
    未検証ですが、確か"最初"とは言い切れなかったように記憶しています(バージョンにより異なるかも。うろ覚えです)。
    少なくとも「ヒエラルキー上で一番上」のような意味での最初ではないですし、毎回違うコンポーネントを取って来るかもしれません。確実に特定のコンポーネントを取得したいならGameObject.Findを使用した方がいいです。

    キャンセル

  • 2018/05/19 00:34

    ご回答ありがとうございます。
    自分の解釈が間違ってないか確認させていただきたいのですが、
    「確実に特定のコンポーネントを取得したいならGameObject.Findを使用した方がいい」→「GameObject.Findで確実に目的のゲームオブジェクトを取得して、それをGetComponentした方がいい」という意味で合っていますか?

    キャンセル

  • 2018/05/21 11:31

    その通りです。
    但しGameObject.Findも「同名のオブジェクトが複数ある」場合はどれを取得するかはUnity次第です。
    必ず単一な名前を付けるとか、そもそもFind系メソッドを使わないとかの対応を行ってください。
    (ご存知の通りFind系メソッドは重い処理なので(GameObject.Findも)、別の方法で参照が取れるならその方がいいです。動作させたい内容や「細ぇこたぁいいんだよ」かどうかによるので一概には言えませんが……)

    キャンセル

  • 2018/05/21 16:13

    ご回答ありがとうございます。
    理解できました。
    ありがとうございます。
    「その場に居る誰かの個人情報を参照して(誰の物かは指定出来ない)、その個人情報にアクセスする」という表現がとてもわかりやすかったので、ベストアンサーにさせていただきました。

    キャンセル

+1

・Object.FindObjectOfTypeのObjectは何なのか。

Objectという名前のクラスです。
FindObjectOfType()はstaticな関数なので、Object.FindObjectOfType(typeof(T));Object.FindObjectOfType<T>();という形で呼び出せます。
ただし、MonoBehaviourはObjectの拡張版(子クラス)なので、Object.の部分は省略することが出来ます。

・FindObjectOfType (Type type) 引数のtypeに何を指定するものなのか?

検索したいインスタンスのクラスをtypeof(〜)で指定します。

・何かしら見つけたものが戻り値として返ってくる。

FindObjectOfType(typeof(T))FindObjectOfType<T>()ではT型で返ってきます。
FindObjectOfType(typeof(T))では、Object型で返ってきます。
このObjectはTで指定した型のものなので、FindObjectOfType(typeof(T)) as Tのようにキャストすると、FindObjectOfType<T>()と同じになります。

スクリプトを参照して、スクリプトにアクセスするのがFindObjectOfTypeです。
スクリプト名.FindObjectOfType<スクリプト名>();

これについては、おそらくそのサイトの内容が正しくないと思われます。
FindObjectOfType()はObjectのクラスにあるstaticな関数なので、Object.FindObjectOfType<T>();(あるいは、前述の通り省略できるので、FindObjectOfType<T>();)で呼び出せます。
そのサイトではGameEventControllerScript.〜としてますが、これはGameEventControllerScriptはObjectの拡張版(子クラス)だから呼び出せているだけで、わざわざそのように書く必要はないでしょう。

「スクリプトを参照して、スクリプトにアクセスする」という意味もわかりません。

前述の通り、Object型ではなく、指定した型で返ってくることを指しているのだろうと思います。

ソースについては、ググればいくつか出てくると思うので省略します。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/18 00:06

    ご回答ありがとうございます。
    まず、Object.FindObjectOfType<Object>の1つ目のObjectに関して理解できました。
    そして、なんとなく使い方がわかったのでいろいろコードを書いて試してみました。
    確認させていただきたいのですが、
    Object.FindObjectOfType<Object>の2つ目のObjectは、クラスを指定するとのことですが、これは言い換えると、コンポーネントを指定するということでしょうか?
    FindObjectOfType<T>()のTは、GetComponent<T>()のTと同じようにクラス(コンポーネント)を指定するということでしょうか?
    GetComponent<T>()が、その1つのゲームオブジェクトを対象にアタッチしているTのクラス(コンポーネント)を取得しようとするのに対し、FindObjectOfType<T>()は、シーン上の全てのゲームオブジェクトを対象に、最初に見つかったアタッチしているTのクラス(コンポーネント)を取得しようとするということでしょうか?

    キャンセル

  • 2018/05/18 09:34

    その解釈で特に問題ありません。
    一応、TにコンポーネントではないGameObjectを指定することも出来ますが、その場合でも同じ挙動になります。

    キャンセル

  • 2018/05/19 00:21

    ご回答ありがとうございます。
    最後に1点、質問させていただきたいのですが、
    コンポーネントだけでなく、GameObjectも指定できるとのことなのですが、例えば、ヒエラルキーにあるCubeのゲームオブジェクトなども指定できるのでしょうか?
    var obj = FindObjectOfType<Cube>();
    とすると、
    Assets/Scenes/Sample.cs(9,37): error CS0246: The type or namespace name `Cube' could not be found. Are you missing an assembly reference?
    とエラーが出てしまいます。

    キャンセル

  • 2018/05/19 10:06

    Cubeは、GameObjectにBoxColliderやMeshRendererなどがアタッチされたものなので、型(クラス)ではありません。
    従って、「FindObjectOfType<Cube>();」では取得出来ません。

    私が言いたかったのは「FindObjectOfType<GameObject>();」ということが出来るというだけです。
    (あまり実用性は無いような気もしますが…)

    キャンセル

  • 2018/05/21 16:12

    ご回答ありがとうございます。
    勉強になりました。
    ありがとうございました。
    ベストアンサー非常に迷いましたが、sakura様にさせていただきました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Unity

    3229questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。