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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

2回答

11125閲覧

MonoBehaviourのAwake、Start、Updateという関数が呼ばれる仕組み

Waken

総合スコア37

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

4グッド

1クリップ

投稿2016/06/01 02:13

MonoBehaviourを継承してAwake、Start、Updateという関数を作るとUnity側で勝手に呼んでくれますが、これはどういう仕組みで動いているのでしょうか?

最初、MonoBehaviour側にvirtualな関数、もしくはabstractな関数で定義されているのかとも思ったのですが、overrideしなくても書けますし、定義を書かなくてもコンパイルエラーにならないので、そういうわけでもないんですよね?

どういう仕組なのか、非常に不思議に思っています。

ご教授お願い致します。

ちなみに、私、C++にはある程度精通していますがC#歴は浅いです。

ozwk, shironegi, suittizihou👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

いろいろ調べてみたところ、以下のようなことがわかりました。

スクリプティングランタイム(Mono・IL2CPP)によって Update()やStart()など特定のメソッドが定義されているかを調査され、MonoBehaviourが特定のメソッドを持っていたら所定のリストに組み込まれるようです。
ゲーム中はこのリストからメソッドが呼ばれている、というものだそうです。

この情報はUnity公式ブログに記載されていた情報なので信頼できるソースだと思います。
詳しくは以下のリンクを参考にしてみてください。
Update()を10000回呼ぶ

余談ですが、私自身この記事を見るまでSystem.Reflectionを使って何かしらしてるんじゃないかな、と思っていました。

投稿2016/06/01 11:03

urahimono

総合スコア714

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shironegi

2016/06/01 11:12

非常に的確なご回答ありがとうございます.とても勉強になりました.質問者ではありませんが感謝しています.
Waken

2016/06/01 23:56

スクリプティングランタイムが、集めて回してくれているんですね。 疑問に思っていたことがすっきり解決しました。 ありがとうございます。 ご紹介してくださった記事、面白いですね。 やはり大したことしてなくてもイテレーションは遅いんですね。 前職の時、頑張ってイテレーション数を減らそうと努力していたのを思い出しました。
guest

0

こんにちは.

私も同じ疑問を抱いていました.
調べても特に回答を得られなかったので,私の中で至った結論は
「Unityは独自のコンパイラを使用しているので,特定のイベント関数のみエンジンから呼べるようにしている」
ということです.
仮想関数はオーバーヘッドがかかりますからね.

C++ならまだしもC#ですし,エンジンの根幹部分で多大なオーバーヘッドによる負荷を生じさせてしまってはゲームどころではなくなってしまうため,コンパイラレベルで根本的に手を入れているのではないかと思っています.
さらに言うとpublicさえ付けさえない(付けなくて良い)のはイベント関数が不用意に他のクラスから呼ばれる事を防ぐためと,下記の点を実現するためではないかと.(長いので別段落にしました)

なお,継承した場合に基底クラスのイベント関数(例えばUpdate)にpublicを付けない場合は言語仕様通り継承されず,派生クラスでUpdateを定義しない場合は基底クラスのUpdateさえ呼ばれないので,クラスだけ継承してもオブジェクトの動作を決定するイベント関数は完全に別個になります.
それが Mono(単一の)Behaviour(動作)の名前の由来と考えると繋がります.
(BehaviourからではなくMonoBehaviourからイベント関数が定義されていますよね)
publicにすると言語仕様上必ず継承されてしまうので,子側で空の関数を定義しない限り親の動作を引き継いでしまい,このような動作は実現できません.
継承されようとも動作定義をクラス単位で別個にするには,publicを付けない状態で呼び出せる方法(=コンパイラ拡張)が必要になります.
前述のパフォーマンスのためか,MonoBehaviourの設計思想のためか,理由はどちらにせよ根本的に手を入れている線は間違いないのではないかと.

いまひとつ文章がまとまっていなくてすみません.
あくまで推測なので鵜呑みにしないで頂ければ幸いです.

※追記
誤った情報がありますが訂正しておりませんので,
後々ご覧になる方はコメント欄を見て補完して下さい.

投稿2016/06/01 04:00

編集2016/06/01 04:53
shironegi

総合スコア119

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Waken

2016/06/01 04:44

なるほど。丁寧な説明ありがとうございます。色々と参考になりました。 試しに、 基底クラスでpublicを付けずにStart関数を定義し、派生クラスではStartを定義しない。 っとしてみたところ、基底クラスのStart関数は呼ばれているようでした。 はて?
shironegi

2016/06/01 04:50

おや…これは失礼いたしました. 別の方のブログでpublicを付けない場合継承されないという情報を目にしていた為,聞きかじった情報を交えてお答えしてしまいました. http://wannabe-jellyfish.hatenablog.com/entry/2015/12/13/221128 申し訳ございません.もっと精進致します.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問