+1 支持
657 閲覧

こんにちは。

GetComponentは処理が重いのであまり使わない方が良いと聞いたのですが、当たり判定時のPhysicsクラスなどを使った時やOnCollisionEnter等の内部で、どんなオブジェクトに当たったのかを調べる時にはGetComponentを使わざるを得ないように思うのですが、皆さんはどうしているのでしょうか?

閉鎖
初心者 (280 ポイント) | 657 閲覧

回答 4

+1 支持
ベストアンサー

使わない方が良いというのは「絶対に使わないようにしよう」ではなく「使わないで済ませられる所では使わないようにしよう」なので、必要な所で使うことは全く問題ないです!

使わないで済ませられる所については、以下の記事が参考になると思います。

http://unity-michi.com/post-508/

見習い回答者 (500 ポイント)
選択
0
こんにちは、回答ありがとうございます。
それでは、このままGetComponentを使わせていただきます。
+2 支持

私はOnCollisionEnterで、どんなオブジェクトに当たったのかを調べる時はタグで判断しています!
タグについて→https://docs.unity3d.com/ja/current/Manual/Tags.html

実装は↓のような感じです!(タグ名が多いならリテラル(直接コードに書いた文字や数字のこと)として書かずに定義した方が良いかも)

private void OnCollisionEnter(Collision col) {
if (col.gameObject.CompareTag("Player")) {
return;
}
Destroy(gameObject);
}


GetComponentについては仰る通りで処理が重いのであまり使わない方が良いですね。
(いわゆるfind系を頻繁に使うのは好ましくないです)
しかしながら、プログラミングに慣れないうちは処理の重さより作りきることが何より大事です。
最初のうちは、速度をあまり気にせず、一度作りきってから遅ければ直してみるというスタンスで良いんじゃないかなと私は考えます。

見習い回答者 (560 ポイント)
0
こんにちは、回答ありがとうございます。
なるほど、タグを使えばGetComponentを使わずに済むのですか。
ですが、取り敢えず動くものを作る事を考えます。
+1 支持
これは私も悩んでいて、直接的な解答はない気がしています。
自分も質問のケースでは使っています。(もしあったら自分が無知!!

落としどころとしては、
・GetComponentは巷で言われるほど遅くはない
なのかなあと。
o8queさんが紹介された記事にあるように、
毎フレーム、1000回近く呼び出す……、とかだとさすがに問題になってきますが、
接触時にチェックする用途なら基本的に不定期に1回だけの使用になるはずですし。

となると、処理速度を意識する場合、どちらかといえば考えるべきは、
「不必要に接触のトリガー関数が呼ばれるケース」を
いかにして減らすか、ということになるのかなあと……。

※一応SendMessageで相手のコンポーネントに関わらず強引に叩きに行くことはできますが、
 おそらくあらゆる面でGetComponentよりタチが悪いことになりそうです
達人回答者 (6.2k ポイント)
0
こんにちは、回答ありがとうございます。
僕と同じ事で悩んでいる人がいて嬉しいです。
そうですね、接触した時の処理は毎フレーム頻繁に起こる事ではないので、GetComponentでいきます。
+2 支持
こんにちは。

細かい所を気にしていると、ちょっとした気づきもあり楽しいですよね。

本題ですが、多分パフォーマンスに対する懸念が根底にあるのかな?と推測します。

GetComponent自体はオブジェクトについてるコンポーネントを上から舐めるだけなので気にするレベルでは無いと思います。

そのうえで敢えてやれる事は無いか?と言うと

質問のOnCollisionEnterの場合はまず、Collisionクラスからrigidbody、Transform、gameobjectが取れます。

これだけでも、相当幅が広がる筈です。GameObjectなんて、名前やTagも持ってますので。

他にもContactsからそのフレームで侵入した相手のN数分の場所、入射のNormal、collider等が取れます。これらを使えば物理挙動は結構カバー出来ると思います。

又、GetComponentを成るべく減らす手としてはStart時にキャッシュしてしまう手法があります。

○○クラスをアタッチして、○○クラスのStartやAwakeで同Objectにあるコンポーネント類を全て取得しておいてしまう方法です。

接触時にGetComponentをする際にこのアタッチした○○を一回とれば他のコンポーネントは皆取れる形になります。

ただこれはキャッシュをPublicにしないと、相手に通知する為の過程を生む為、パフォーマンス的には本末転倒になり、GetComponentの方がいいやと成ります。

Publicにしたらしたで、どのオブジェクトがどのオブジェクトに影響を及ぼしたか把握し辛く成り、今度は設計的に把握し辛くなってきます。

Publicにする場合は、明確に、当てる方が取得するんだ!いや当たる方が取得するんだ!と、開発関係者で意思統一することをお勧めします。

世間的にはパターンやベストプラクティスは転がっていますが、自分で出来る事はやっておくんだ!と言う気持ちは大事にしたいところですね!頑張って下さい!

関連する質問

0 支持
0 回答
0 支持
1 回答
0 支持
2 回答
0 支持
0 回答
0 支持
1 回答
hotchan 初心者 (120 ポイント) 4/28 質問 | 72 閲覧
2021-02-08 質問・回答をMarkdownで入力できるようにしました。
2020-09-03 新たなスパム対策を導入しました。

175 質問

157 回答

163 コメント

214 ユーザー