Unity初心者の俺が調べたことをメモするスレ (99レス)
上下前次1-新
49: 2023/09/15(金)21:07 ID:Fj2wueol(1/2) AAS
>>48
Dictionaryは個別の値へのアクセスは早いけど高性能な分メモリ使用量は多いよ
配列やリストはメモリ使用量は少なめでIndexでのアクセスは早いけど、個別の値の検索や削除が要素数に比例して遅くなるから多数のアイテムを管理するシステムには不向きな印象がある
明日は久しぶりにコレクションについてまとめてみるか
今日は抽象クラスの整理はひとまず終わったので次に作るUIの設計を考えた
クラス間の結合を弱めるにはインターフェースやZenject(外部ライブラリ)が有効だそうだが、導入には一手間かかりそうだなという印象
インターフェースはUnityの標準機能じゃインスペクターから設定できない(オーディンインスペクターという有料アセットや外部ライブラリを利用すれば一応可能)のが残念
それとインスペクターで参照を設定するのだと結局ゲームオブジェクト(MonoBehaviour)同士の結合は緩められてない気がする
「クラスAに機能を追加・修正・削除したから、クラスBの該当部分も直して~」っていう作業から抜けたいなあ
50: 2023/09/15(金)21:24 ID:hZKK5Ca7(1) AAS
因みに今のパソコンでそのディクショナリのはやさとかメモリとかどれだけ影響あるのでしょうか?
最後の文章見ると個人開発じゃなくてグループ?
このメモは一体、、、
51: 2023/09/15(金)21:52 ID:Fj2wueol(2/2) AAS
個人開発だよ
「直して〜」の「〜」は呼びかけじゃなくて以下ループとかそういうニュアンスのつもりだった
大量のデータを扱うコレクション(配列とかリストとかディクショナリ)の場合はどのコレクションを選択するかで処理速度は顕著な差が出るね
前に実験したことあるけど、1万個の所持アイテム用インスタンスを格納した?List<自作クラス>と?Dictionary<int,自作クラス>で一番最初に入手したアイテム(ListではIndex0、Dictionaryではint型キーを連番になるように制御して格納しているのでこれもキー0になる)を削除する処理を行った場合
?Listだと500msぐらいかかる一方で、?Dictionaryだと0.1msで終わる
これはListでは内部的には配列に特殊な処理を加えて自由に挿入・削除のできるコレクションに仕立てているから、削除関数であるRemoveAt()を実行すると削除した要素Indexの後ろに並んでいる要素たちを全部1つずつコピーして前に詰める作業が内部的に行われると全体の要素数が増えるにしたがってクッソ重くなる
一方でDictionaryは内部ではハッシュテーブルを利用していて、与えられたキーをハッシュに変換する作業がある代わりに基本的に要求された要素だけを参照しに行くから、全体の要素数が増えても処理速度に対して影響は出ない
メモリ使用量についてはモバイル端末想定じゃなきゃまあ誤差だとは思うけど可能な限りは軽くしたいね
52: 2023/09/16(土)21:40 ID:OFNct1/O(1) AAS
コレクションについてまとめようと思ったけど別のことして忘れてた
とりあえず今日はメニュー画面の作成を進めた
今日から作成を始めたメインメニューはクラス間のシリアライズによる参照は使わずに、イベントとリスナー登録で情報のやり取りをしようと考えている
一般的にイベントでやり取りをする方法は、クラス間でお互いの内部実装に無関心で済むため(イベントの発火がされなければ待機しているだけで、引数を受け取ってどう使うかも自由)、疎結合に分類されるらしい
まあシリアライズの代わりにデリゲートへの関数のキャッシュとリスナーの登録をコードで行う必要があって、更に複数のリスナーが存在する場合は実行順序の制御も別所で必要になるので、インスペクターからシリアライズで参照設定をしてグチャっと処理コードを書いた方が短期的には楽に見えるのはナイショ
53: 2023/09/16(土)22:33 ID:GeGtMKJg(1) AAS
やべぇー
なんか、高度すぎて
分からん
54: 2023/09/17(日)22:58 ID:SjciO0EV(1/2) AAS
基本的に実装したい処理が思い浮かんだ時に必要そうな処理を基礎からその都度調べているだけよ
地道にUnityやっていけば必ず到達できるレベルでしかないからガンバレ
本日の作業もメニュー作り
静的イベントを利用してクラス間のやり取りをするうちに気になったのが、イベントとゲームオブジェクトのライフサイクルとの関係性
メインメニュー → 「装備」ボタンを押すと静的イベントを発火 → リッスンした装備メニューのマネージャークラスが装備メニューをSetActive といった流れを実装したかったが、テストプレイすると「装備」ボタンを押しても装備メニューが起動しない
原因は、装備メニューのマネージャークラスがアタッチされたゲームオブジェクトが無効化されていたためっぽい
無効化されたゲームオブジェクトの関数を外部からコールすることは可能だが、無効化中にはイベントのリスナーとしてコールバックを行うことはできないようだ
確かにゲームオブジェクトにアタッチされたクラスはUpdateなどのマジックメソッドが呼び出されないが、厳密にはこれらもランタイムから呼び出されている訳で、外部からコールされている状態に近いように思える
イベントのリスナーとしてのコールバックもEventHandler?が呼び出しているらしいので、「ゲームオブジェクト」のライフサイクルにはこれらの仕様を変更する(というか、制限された仕様のインスタンスをUnityが提供している?)ようだ
まあ面倒な理屈はともかく、イベントでやり取りするクラスは発火前にゲームオブジェクトを有効化しておくか、MonoBehaviourを利用しないクラスとして設計しましょう、というのが今日得た結論となる
55: 2023/09/17(日)23:04 ID:aXQbPdAS(1) AAS
それセットアクティブじゃなくて
Enableでは?
56: 2023/09/17(日)23:08 ID:SjciO0EV(2/2) AAS
いやイベントのリスナーになっているクラス(コンポーネント)がアタッチされているゲームオブジェクトが無効化されているとコールバックが行われないっぽのよね
コンポーネントじゃなくてゲームオブジェクトだからSetActiveの話
57(1): 2023/09/18(月)12:08 ID:RKiVL9Tq(1) AAS
l_i_t_e(邪魔という方は左記をNGお願いします)
更にご家族に教えて加えて¥4000×人数をGETできます!
画像リンク[jpg]:i.imgur.com
58: 2023/09/18(月)13:39 ID:YQ8UtnvT(1) AAS
>>57
もう現金に換えてアンインストした
59: 2023/09/18(月)16:11 ID:ylIv/p+P(1) AAS
普通なら削除依頼出しとけよって定型文貼られるようなスレだけど
技術者多い板の性質と真面目な内容が組み合わさって技術メモブログのように存在を許されている
60: 2023/09/18(月)16:34 ID:GrWZQeuh(1) AAS
絵描き板とかである個スレみたいなもんでしょ
過疎板にはよくある
61: 2023/09/18(月)22:31 ID:+Uz7sHbq(1) AAS
アウトプットも兼ねて覚えたこと書き殴りたくなる機会がたまにあるんだけど、Unityの制作面中心の雑談スレが見当たらなかったからノリで立てちゃったのよねすまん
代わりに毎日何かしらは作業する・調べるように努力してます
今日気になったこと
・ジェネリックの扱い方
ジェネリックと抽象クラスを利用してUI関係の整理を続けていたが、独自セレクタブルたちが引数の型の異なるRefresh関数(描画情報を更新するために管理クラス側からコールされるpublicな関数)をそれぞれ持っており、これをどうやって統一するか悩む
統一すること自体は抽象クラスにRefresh関数自体をジェネリック<T>で抽象メソッドとして宣言すれば簡単にできるのだが、そうすると同時セレクタブルたちの型が抽象クラスとしても異なってしまうため、管理クラス側から独自セレクタブルたちの配列を扱う時にその型(内部実装)を知る必要性が出てきてしまうように思える
インターフェースでよくないか?とも思ったのだが、インターフェースはUnityの標準機能ではシリアライズ化できないし、キャストしたりGetComponentで具体的な型を指定しないと多分Transform等にもアクセスができないしどうしたものか
抽象クラスの基底に更に抽象クラスを宣言すれば何とかなるのかな…明日以降検証してみる
ちなみにコレクションの復習はまだ出来ていない
というかUIのクラスとレイアウト周りの整理が中心で、検索システムとか内部面は一段落したので暫くコード書くときにコレクションに触れてない
省1
62: 2023/09/19(火)22:19 ID:CqPMq7Md(1) AAS
今日の作業
・独自の派生セレクタブルの処理を抽象化するためにRefresh関数の引数をint型に統一することに決定する。int型以外を引数とするクラスはコード全体を見直す必要が出てきたので数か月前の設計のガバさのツケが回ってきた形。
・MonoBehaviourを継承しないクラスに[Serializable]を付けて、このクラスをフィールドとして保有するMonoBehaviour継承クラスのインスペクターから値を弄れるようにしてみた
基本的な使い方だけどスクリプタブルオブジェクト以外で[Serializable]を利用してこなかったのでちょっと感動
・ノーコード系ゲーム制作アセットの戦闘システムに自作の拡張機能を追加した。攻撃時に攻撃者と被害者をそれぞれ独自戦闘システムインターフェース型でGetComponentしてダメージ計算など色々な処理をスクリプトから行う
有料アセットのテンプレートは便利だけど、個人的にはノーコード系のノードやリスト形式の命令処理は何となく苦手
VisualStudioで素直にC#書いた方が楽だし処理も追いやすい気がしてならない
・「今日の疑問」について調べている時にDictionaryのTryGetValueを使えばキーの存在確認と値のチェックを両方できることを知った
というか前に調べて覚えたつもりだったけど忘れていた
嫌な予感がして自分のコード見てみたらContansKeyとDictionary[]を両方使って二重にDictionaryを走査している箇所が案の定見つかった
省5
63(1): 2023/09/19(火)22:23 ID:iPzaBk+A(1) AAS
ゲットコンポーネントは重くないでしょ
それは公式でも書いてると思うけど
Updateでやっちやあかんって
64(1): 2023/09/20(水)03:37 ID:ncaLFBeu(1) AAS
「Unityでよくある失敗」はコードを書く習慣がある層ならUnity初学者でも回避するよう内容が多いな
GetComponentとFindを周期処理のなかに書くなんぞ最たるもんだな
65: 2023/09/20(水)22:16 ID:6f4RNUvQ(1/3) AAS
>>63-64
必要ならキャッシュしておいた方がいい、との記述はあるものの
外部リンク:learn.microsoft.com
色々な人の検証結果を見る限りはGetComponentを1フレーム内で数万回繰り返しても、処理時間はそれ自体ではぶっちゃけ殆ど差が出ないみたいだね
そう考えると実はUpdate内で毎度呼び出しても現実的なボトルネックにはならないんだろうね
ある意味「GetComponentは重いぞ神話」が独り歩きしている状況かもしれない
自分は基本的にその場限りで利用する場合以外はキャッシュするけども
66: 2023/09/20(水)22:21 ID:6f4RNUvQ(2/3) AAS
代わってGameObject.Find系は本当に看過できないほど重いようだ
ゲームオブジェクト全体を走査する系の処理は重いのは感覚的にもよく分かる
同じくゲームオブジェクト全体にメッセージを送信するSendMassageも滅茶苦茶重いらしくてMicrosoftのDocには
「SendMessage() と BroadcastMessage() は、どんな犠牲を払っても排除されるべきです。これらの関数は、直接関数呼び出しよりも約1000倍遅くなる可能性があります。」(google翻訳)
って書いてあって草
素直にUnityEventsかC#Eventを使うのが安心だな
67(1): 2023/09/20(水)22:22 ID:9mke4B6g(1) AAS
おそらくはまだCPUがショボい頃の事が今でも尾を引いてらのかもね
68: 2023/09/20(水)22:30 ID:6f4RNUvQ(3/3) AAS
>>67
あと可能性があるとしたら、TransformへのアクセスはUnityのバージョンアップで最適化がされたことがあるそうで、GetComponentもそうなのかもしれん(調べてない)
・今日の作業
今日の作業は昨日と変わらず、重い処理関係以外で特に何も調べたりはしなかった
引き続き設計思想の話としては、インスペクターから値・参照を設定・確認できるのは便利である一方で、Unityに慣れるにつれてインスペクターから設定しなくてはならないのはコードとインスペクターの双方を行き来する必要があって面倒だとも感じてきた
UnityにはEventTriggerなど便利なコンポーネントが存在しているが、一部は自分でスクリプトを組めば代替できるものもある
GameObject.Find系が推奨されないもう一つの理由として「制作途中の仕様変更に弱い」という指摘があるが、これにはコードとインスペクターだけではなくヒエラルキーも動作確認の際にチェック対象になってしまう煩雑さを回避したいという願いが暗に含まれていそうだ
上下前次1-新書関写板覧索設栞歴
あと 31 レスあります
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル
ぬこの手 ぬこTOP 0.025s