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

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

新規登録して質問してみよう
ただいま回答率
85.31%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Unity

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

Q&A

解決済

2回答

2886閲覧

Unityにおける非同期処理の用例について

cushionA

総合スコア90

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Unity

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

0グッド

0クリップ

投稿2021/08/16 15:11

編集2021/08/16 15:14

前提・実現したいこと

Unityで非同期処理を扱おうと思ったのですが、メインスレッド制約(メインスレッドでしかMonobehaviorの機能を使用できない)があるせいでさしたる用途を見つけられずにいます。
そこで皆さんがどのようなことにUnitaskやその他の非同期処理を使用しているかをうかがわせていただきたく思い質問させていただきました。
また、僕の非同期処理に対する考えに誤りがあれば指摘していただけると嬉しいです。

考えたこと

僕の考えとしてゲームにおける非同期処理は音の再生や揺れものの制御などゲームの状況に直接影響を及ばさない、いわゆる独立した投げっぱなしの処理にのみ使うべきであるのかなというものがあります。
極端な例ですが敵とプレイヤーの移動処理を別々のスレッドで行う、ということをすればプレイヤーと敵の間での座標の参照がうまくいかないようなトラブルが起きるのではないかと思うからです。
この考えに基づいて僕は非同期処理を運用しようとしたのですが、そうなるとリソースの管理や音の再生、イベントや時間の待ち受けくらいしか思いつきませんでした。
リソースのロードやインスタンス化はAddressablesのAPIで非同期処理が提供されているのでいいとしても、音の再生は先述の制約により非同期処理では行えません。
またイベントや時間の待ち受けもわざわざ非同期で行うほどのものかと思ってしまいます。
HPバーの更新などならともかくUIメニューを開いた時の動作などはそもそもほかの処理が止まっているのでそこまで負荷を気にする必要があるとは思えません。
ほかにもチャージ時間や無敵フレームの計測などもありますが、これらの大半はごく短い時間のみ計測されるものなので同じように気に掛ける必要があるとは思えません。
ボタンの入力などはメインスレッドの処理とタイミングがずれたりしないかが少し怖いです。

独立した投げっぱなしの処理にのみ使うべきである、という前提を含めてこれらの考えに間違いがあれば教えてくれると嬉しいです。
さらに非同期処理の用法について僕の考えが及んでいない点がありましたらそれも教えてくだされば幸いです。
どうぞよろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

Unity 2020 3.6f1
VisualStudio 2019

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/08/16 22:42 編集

unity async advantages などをキーワードにググるといろいろ参考になりそうな記事がヒットすると思いますが・・・
cushionA

2021/08/16 22:49 編集

SurferOnWww様、ありがとうございます。 英語で検索する……ということは今までやってこなかったので目からうろこでございます。 今回に限らずこれからのリサーチの手法に取り入れたいと思います。 今軽く調べただけでもものすごく情報があったのですが、少し朝から用事があるので戻ってからまたじっくり見て自己解決を書き質問を閉じたいと思います。 ですがSurferOnWww様がなにか(サイトの規約的に問題なければ「あ」とか本当に適当でいいですが)解答の書き込みをしてくださるのに差し支えなければベストアンサーになっていただきたいと思います。 改めてありがとうございました。
退会済みユーザー

退会済みユーザー

2021/08/16 23:40

もう少し回答を待たれてはいかがですか? もし、2, 3 日待っても期待する回答が出てこなければ、その間にご自分が調べて得た情報の内もっとも役に立ったものを解答欄に書いて、それにマークを付けてクローズするようにしていただければと思います。
cushionA

2021/08/17 03:43

SurferOnWww様、親切にありがとうございます。 とりあえず一応自己解決方法は書いて、それに対してのご意見を待つ形でもう少し時間を持たせていただこうと思います。 ご助言大変ためになりました。
guest

回答2

0

ベストアンサー

await UniTask.SwitchToMainThread()でいつでもメインスレッドに復帰可能ですからメインスレッド制約は実は簡単に対処出来るんじゃないでしょうか。

UniTaskの真価は細かな待ち表現のためにasync/awaitで利用してもパフォーマンス上のデメリットをほとんど受けないか、むしろeventやコルーチン等で手書きするよりも効率的に動作する点にあります。なにより非同期処理を少ない行数で表現出来ることは偉大なメリットです。

ですから、並列負荷分散を期待した非同期(実際それは並列処理)としてだけではなく、単に時間方向への操作を平易に記述できる方法としてUniTaskをどう運用するかを考えていったほうがいいのかなと思います。

参考として、UniTask以前にasync/awaitが必要とされるようになった成り立ちを抑える意味でも、イベント駆動プログラミング(C# のevent、JavaScriptのPromise)、あるいは非同期プログラミングの隣接概念であるリアクティブプログラミング(Reactive Extensions または Observable)といったプログラミングのパラダイムを勉強していくとよいのかなと思います。

投稿2021/08/17 04:13

tor4kichi

総合スコア771

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

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

cushionA

2021/08/17 05:05 編集

tor4kichi様、回答ありがとうございます。 少し調べものと検証をしてから改めて返信いたします。 回答の方とても参考になりました。 まずはお礼のみ先に述べさせていただきます。
cushionA

2021/08/17 05:53 編集

tor4kichi様、改めて回答ありがとうございます。 確かにおっしゃるとおりメインスレッド制約はSwitchToメソッドで回避できました。 それからUniTaskのReadMeを読みに行ったところ基本的にUniTaskはメインスレッドで実行されるというふうに書いてあり、実際の動きもそのようになっておりました。 明示的にプールスレッドに切り替えなければスイッチする必要すらないようです。 だというのにメインスレッド制約が厳しく感じられていたのはひとえに僕の理解が浅く、また教本にあるお手本(マルチスレッドのもの)のモノマネのようなコードをなにも考えずに書いていたことが原因だと思われます。 ところでお話を聞いて少し考えてみた結果、要するにこのAPIはawait、つまりは待つという動作をローコストで利用できる点が優れているのではないかという認識に落ち着きました。(マルチスレッド≠async/await) それは連続した処理の隙間に待ち時間を挟みながら実行するという意味でもあり、イベントを待つという意味でもそうでしょうか。 つまり単にプールスレッドに処理を割り振るためのAPIではなく、各処理の制御を簡単にするためのツールという意味合いも持ち合わせているのかもしれないと思いました。(よく考えたら理解も何もお言葉そのままですね) また参考として挙げてくださったイベント駆動型やリアクティブプログラミングについてはUniRxを少しだけかじったのですがその意義を理解できず早々にやめてしまいました。 当時の僕としては「オーバーヘッドが軽くなるわけでもないなら、入力やイベントを待つより普通に入力を取得したりイベントに付属のOn〜メソッドとかアニメーションイベントメソッドを利用するだけでよくないかな」という考えだったのですが、今なら利点を少しだけ理解できるような気がします。 それは例えば横入力キーなどをアクションの場面やUI操作などの複数のコードで取得したりしているのを一つのイベントにまとめることができるという点です。 横入力キーを一つのイベントとして管理すればキーの処理の変更があっても大元のイベントを一つ変えれば済むので管理が簡単です。 また複数コードに影響を及ぼすフラグ(たとえばダメージを受けたフラグとか。ヒット後の無敵処理や怯みによる移動禁止処理など様々な影響を及ぼす)などもイベントに一括で管理することで扱いが容易になるでしょう。 UniTaskはRxほど強力ではないかもしれませんがイベントを扱えるということで、こういった発想の延長で使えると理解できて大変参考になりました。 もし理解がおかしな方向に行っていたら訂正いただけるとたいへん嬉しいです。 丁寧なご指導に心より感謝申し上げます。
tor4kichi

2021/08/17 09:27

前段のasync/awaitや非同期の理解はその通りだと思います。私の理解とも一致していて違和感はないです。並列処理と非同期は別の話というのは大事ですね。 後段について、まず入力のキーマッピング管理はUnityの組み込み機能としてInput Systemとしてまとめられているので、もしご存知なければまずそちらを確認してみてください。 UniRx(Observable)の基本的な理解として、UniRx(Observable)は「複数回」の非同期イベントを数珠つなぎに処理するコードをサポートし、UniTask(async/await)は「単発」の非同期イベントを待機して処理するコードをサポートする、と整理できます。この点は neuecc氏 の投稿や、とりすーぷ氏 のUniTask/UniRx関連のスライド資料や書籍でもしばしば説明されているかと思います。 待ちたいイベントが複数回か単発かの性質を抑えてUniTask/UniRxの使い分けを検討できるといいですね。 また、UniRxで入力を管理することは想定されていますが、特に時間軸的な連続入力を扱う際に効果が大きいです。 例)2秒間XボタンをホールドしたらOnNextを発行する UniRxは非同期に連続するイベントを「束ねて解釈する」ようObservableシーケンスを変形させることで、複雑な入力を簡単な出力として扱えるように出来る点にメリットがあるのかなと思います。 どちらを使うにしても「複雑なことを単純に分解してコードとしてまとめる」ことが求められるのかなと思います。 「UniRx/UniTask完全理解」という本には私が説明した以上にまとまった形でパラダイムの説明からUniTask/UniRxの使い分け仔細に知識を得ることができますから、所属組織の書籍貸し出しか自費かでなんとか読んで貰えるといいんじゃないでしょうか。
cushionA

2021/08/18 03:16 編集

tor4kichi様、重ねてご指導していただきありがとうございます。 また返信が遅れて申し訳ありません。 具体的な資料のあてを教えてくださった上でわかりやすくRxとTaskの説明をいただけて助かりました。 つまりuniTask、ひいてはawaitが待てるのはイベントの発行それのみですが、Rxはイベントが「どのように」発行されたかを見ることで連続入力や長押しへと対応するということでしょうか。 HPがマックスの時に発行されるHP_Maxイベントがあったとして、もし使い分けるならHPがマックスになった、などの単発ならTaskでよし。 HPが30秒間マックスのまま、というイベントなら30秒間マックスイベントを受け取り続けることでRxが性能を発揮する、という形でしょうか。 これも30秒間HPがマックスのままであるというイベントを作ればタスクでも利用できますが、Rxのすごさは既存のイベントの解釈を変えることで多様な表現を可能にする点であると理解しました。 書籍の方も今読んでる本を読み終えたらぜひとも手に入れたく思います。 返信が遅れてしまった非礼をわびますと共に、改めてご指導いただけたことに感謝申し上げます。 追記・入力の新しいシステムについては名前だけは聞き及んでいたのですが、Rewiredというアセットを入力に使用しているので詳しく知りませんでした。 初めて見たときはよく分からなくて投げてしまったのですが、いずれ主流の実装になると聞いているのでまた機会を設けて勉強したいと思います。 ありがとうございます。
guest

0

ネットワークアクセスの戻りを待ってたら画面が止まっちゃうので、必ず非同期でやります。

投稿2021/08/16 16:45

bboydaisuke

総合スコア5339

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

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

cushionA

2021/08/16 16:58

回答ありがとうございます。 オフラインゲームですのでそのまま参考にはできないかもしれませんが、先に進まず待機する必要がある処理に非同期が利用できるのかな、というふうな理解が得られました。 興味深いご意見に感謝いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問