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

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

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

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

Q&A

解決済

3回答

15183閲覧

Unityで わざわざasync/awaitを使う必要性について

ads3hcgff

総合スコア16

Unity

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

0グッド

2クリップ

投稿2018/09/30 13:13

編集2018/09/30 13:26

unityで非同期処理を行う際C#固有の機能であるasync/awaitの使いどころについて。

unityでは非同期をシングルスレッドで行うようなコルーチンという機能がありますが、
カスタムコルーチンが導入されたことにより、非同期はすべてコルーチンで行えばいいのではないかと思います。

そもそも、コンポーネント指向のunityにおいて同じオブジェクトにupdate関数を持ったスクリプトを2個張り付ければ非同期であるのではないでしょうか。
これで賄いきれないものをカスタムコルーチンで実装すればいいと思います。

例えばwwwクラス

IEnumerator Start() { // WWWクラスのコンストラクタに画像のURLを指定してダウンロードを開始する string url = "http://www.mybdesign.com/unityui/images/cat.jpg"; WWW www = new WWW(url); // 画像のダウンロードが完了するのを待つ yield return www; // ウェブサーバーから取得した画像をローイメージで表示する RawImage rawImage = GetComponent<RawImage>(); rawImage.texture = www.textureNonReadable; // ローイメージのサイズをピクセル等倍にする rawImage.SetNativeSize(); }

カスタムコルーチンにより、 CustomYieldInstructionを継承したクラスでkeepWaitingをオーバーライドすればwwwで
スクレイピングを行っている最中はメインスレッドに処理を戻しておます。この動きはasync/await同じ動きですよね?
また、ここで処理をもどしているといってもwebと通信は行っているので実質マルチスレッドなのでやはり非同期。

コルーチンになったStartが実行。

webと通信 ここでコルーチンは中断

メインスレッドに処理を戻す。 ここで平行してwebで通信をしているので実質マルチスレッドなのでは?????

↓ 通信が完了 ↓ 中断していたコルーチンを再開 ↓ コルーチンが完了したので、メインスレッドに処理を戻す。 async/awaitをわざわざ使う意義とは?

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

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

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

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

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

guest

回答3

0

ベストアンサー

基本的にDeadEndShoot666さんの回答に同意しますがコメント欄に書くのは長いのでこちらで。

「コルーチンはシングルスレッド」は確かですが、「1ソースの中で同時に複数メソッドが動く(厳密には1フレーム刻みかもしれないけど)」という意味では(広義の?)並列処理ではあるかなと思います。
Unityでマルチスレッド使うならスレッドを明示的に呼び出すか・JobSystemを使うか・その他になるかと。
Unityのマルチスレッド界隈のはなし - おれんじりりぃぶろぐ

で、どれがいいかと言うと、やっぱり用途による。(※個人的感想が含まれます)

何かの処理を待つだけならコルーチンまたはUpdateまたはEvent。
(どれがいいかは状況による。コルーチンも書き方によっては負荷が上がるし、複数Updateが一律ダメかというとそうでもない。プロファイルしてナンボ。なおクリック待ちなんかはよくUpdateに書かれるけどIPointerEnterHandler等のイベントインターフェースを使う手もある)

本当に重い処理と並行で動かしたいならasync/await。
(以前「WebCamTextureで取得した画像をリアルタイムに加工して表示」をした時はこっちじゃないとまともに動きませんでした)

JobSystemは何かすごそうなんだけど、自分で使ってないので「ははーんなるほどね(わかってない)」状態なのでご自分で調査&お試しを。
【Unity】C# Job Systemを自分なりに解説してみる - テラシュールブログ

……などと書いてたらUniRxの人が全部まとめてくださってた。
neue cc - UniTask - Unity + async/awaitの完全でハイパフォーマンスな統合
「もういっそ全部これでいいのでは?」と思いそうになりますが私は未検証なのでご参考までに。

投稿2018/10/01 11:25

sakura_hana

総合スコア11425

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

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

0

Unity2019.2.10f1 の場合ですが、

UnityのメインスレッドのStartやUpdateなどから
StartCoroutine(メソッド名)した場合と、
明示的に別スレッドを使うTask.Run()を用いずに単にasyncを付加したメソッドを呼んだ場合、

呼ばれた側で可能な非同期処理(UnityWebRequestなど)と
待ち処理(yeild returnやawait)は同じで、

Unityではawait以降でもスレッドIDが変わらないので、
内部的にはほぼ同じような実装で動いているようです。

明示的にTask.Runしないのであればどちらでも構わないと思います。

投稿2019/12/12 06:21

ippei

総合スコア89

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

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

0

※深く理解していないので頓珍漢な可能性ありツッコミ大歓迎

非同期的な処理に限ればコルーチンで問題ないというか積極的に使うべきです。エンドユーザー向けに用意されているクラスや関数はシングルスレッドで動くことを前提に作られていて、下手にasync/awaitを使うとエラーを吐いて停止します

C#6対応でついてきたおまけのような物なので嫌なら無理して使うこともないでしょう。頻繁に使うtransform.positionでエラー吐く時点で運営側がそれ程熱心にasync/awaitを推しているとも思えません

ただ最適化や並列処理となれば、コルーチンはシングルスレッドで動いているので比較的時間のかかる処理に使うとフレームレートの低下を招く上にそもそも並列で処理されません

例だと画像一枚拾ってくるだけなので十分だと思いますが、例えば100枚拾って全部をネガティブ化するとかだとUnity内の関数とコルーチンで処理するよりも、async/awaitと自家製または外部ライブラリで処理した方が軽いかもしれません

他にも外部ライブラリのクラスを継承したクラスを使いたい場合とかだと、MonoBehaviourを継承していないのでasync/awaitを使うしかありません

空のUpdate()を放置するだけでも最適化上問題があると言われているので非同期的に処理するために複数配置するというのもあまり良い方法だとは思えません

実際問題エンドユーザーがC#で書くコードの大部分はゲームよってはLuaとか独自言語で書かれている本来高速化がそこまで重要ではない部分ではあるので「本当にasync/awaitが必要かコルーチンで非同期的に動けば良いのではないか」と言えばそういう気もします

個人的な見方だと自分の書いた部分を動かしてるコアだけ100%に貼り付いているような不細工なゲームになるのを防ぐための最後のお供です

ところでどうしても腑に落ちないのですが、「メインスレッドに戻す」という処理は本当に行われていますか? 実際スクレイピング自体はマルチスレッドで動いているとは思いますが、コルーチンでのスレッド切り替えは仕様上有り得ないと思うのですが。もしできるのなら上はただの駄文です、すいません

投稿2018/10/01 06:38

DeadEndShoot666

総合スコア203

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問