Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
いまさらだけど確認しておこう Coroutine
Search
RyotaMurohoshi
September 15, 2018
Technology
4
8k
いまさらだけど確認しておこう Coroutine
2019/09/15に開催された「Unity非同期完全に理解した」勉強会のLT資料です。
https://connpass.com/event/95696/
RyotaMurohoshi
September 15, 2018
Tweet
Share
More Decks by RyotaMurohoshi
See All by RyotaMurohoshi
Tilemapのアップデートについて
ryotamurohoshi
0
24
Unityの合同同人誌や合同商業誌を書いてる僕は感想やレビューや評価が欲しい
ryotamurohoshi
0
530
Unity 2021.1での Unityパッケージの名称変更について
ryotamurohoshi
0
710
Odin Validationはいいぞ!
ryotamurohoshi
2
960
Tilemapはいいぞ!2020 〜すごいぞ、プロジェクト専用拡張Brush〜
ryotamurohoshi
0
2.4k
Unityでも、新しいC#
ryotamurohoshi
0
1.3k
Riderはいいぞ!
ryotamurohoshi
1
3.5k
Riderのススメ〜俺はRiderここが好き〜
ryotamurohoshi
1
2.4k
Unity開発者に伝えたい.NETのこと
ryotamurohoshi
4
37k
Other Decks in Technology
See All in Technology
AI Ready API ─ AI時代に求められるAPI設計とは?/ AI-Ready API - Designing MCP and APIs in the AI Era
yokawasa
8
2.3k
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.2k
毎晩の 負荷試験自動実行による効果
recruitengineers
PRO
5
180
データ戦略部門 紹介資料
sansan33
PRO
1
3.3k
Maintainer Meetupで「生の声」を聞く ~講演だけじゃないKubeCon
logica0419
0
110
衛星運用をソフトウェアエンジニアに依頼したときにできあがるもの
sankichi92
1
1k
Autify Company Deck
autifyhq
2
44k
サービスを止めるな! DDoS攻撃へのスマートな備えと最前線の事例
coconala_engineer
1
180
ゼロから始めるSREの事業貢献 - 生成AI時代のSRE成長戦略と実践 / Starting SRE from Day One
shinyorke
PRO
0
120
推し書籍📚 / Books and a QA Engineer
ak1210
0
140
PHPからはじめるコンピュータアーキテクチャ / From Scripts to Silicon: A Journey Through the Layers of Computing
tomzoh
2
130
モニタリング統一への道のり - 分散モニタリングツール統合のためのオブザーバビリティプロジェクト
niftycorp
PRO
1
520
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.7k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Embracing the Ebb and Flow
colly
86
4.8k
Code Review Best Practice
trishagee
69
19k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
Into the Great Unknown - MozCon
thekraken
40
1.9k
Six Lessons from altMBA
skipperchong
28
3.9k
Build The Right Thing And Hit Your Dates
maggiecrowley
37
2.8k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.2k
Building a Scalable Design System with Sketch
lauravandoore
462
33k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Transcript
いまさらだけど確認しておこう Coroutine @RyotaMurohoshi 2018/09/15(土) Unity非同期完全に理解した勉強会
2015年3月21日
None
いやぁ~~っ! 未来、ついに来ましたね!
async/await、最高ですね! ガンガン使っていきましょう!
ところでちょっと 現実に、そして日常に戻りましょう
Unityのバージョン何ですか? 2018系?2017系?5系?もしかして4系?
『最新作を作っているバージョン』だけじゃないですよ! 『利益を生み出しているゲームのバージョン』は何ですか!?
世の中のすべてのUnityプロジェクトが (特になんの工夫もせず) async/awaitが使えるわけじゃない・・・ 使えるけれど、大人のあれで使わないってこともあるよね
ある程度利益を出していて大きく変更予定のないヤツ 大人の事情でUnityをアップデートできないヤツ こういうプロジェクト、まれによくある
世の中の全てのUnityプロジェクトで async/awaitが使えるわけじゃない・・・
というわけで・・・
いまさらだけど確認しておこう Coroutine @RyotaMurohoshi 2018/09/15(土) Unity非同期完全に理解した勉強会
※ 私の勤め先や個人ではUnity 2018やasync/await 使えますよ!
Coroutineがasync/awaitの代わりになるわけじゃない async/awaitが使える場所ではそっち使おう! Rxが適切な時もあるよ!
けれど、それでも・・・
古いプロジェクトをメンテ・改善していると Coroutineが助けてくれること、ある! Coroutineのデバックで嵌ることも、あるかも! 今更だけど、このタイミングで確認しておきましょう!
基本的なCoroutineの使い方は 知っている前提で いくつか(みんなが知っているかもしれないけど)Tipsを話します
public void StartLaunchLoop() { StartCoroutine(LaunchCoroutine()); } private IEnumerator LaunchCoroutine() {
// 1秒に一回 Launch が呼び出される while (true) { Launch(); yield return new WaitForSeconds(1.0F); } } private void Launch() { // 略 }
「当たり前」って大切 確認していきましょう
その1
void Start() { // 入れ子のコルーチンを呼び出す StartCoroutine(ParentRoutine()); } IEnumerator ParentRoutine() {
Debug.Log("start parent"); // 子コルーチンの呼び出し yield return ChildRoutine(); Debug.Log("end parent"); } IEnumerator ChildRoutine() { Debug.Log("start child"); yield return new WaitForSeconds(1.0F); Debug.Log("end child"); } 実行結果 start parent start child end child end parent ※ Unity 5.3 以降
その1 Coroutineの入れ子でStartCoroutineがいらないのはUnity 5.3から! Unity 5.2とそれより前ではStartCoroutineが必要! コンパイルエラーにならないからこそ、気を付けよう!
void Start() { // 入れ子のコルーチンを呼び出す StartCoroutine(ParentRoutine()); } IEnumerator ParentRoutine() {
Debug.Log("start parent"); // 子コルーチンの呼び出し yield return ChildRoutine(); Debug.Log("end parent"); } IEnumerator ChildRoutine() { Debug.Log("start child"); yield return new WaitForSeconds(1.0F); Debug.Log("end child"); } 実行結果 Unity 5.3 以降 start parent start child end child end parent 実行結果 Unity 5.2 以前 start parent end parent
void Start() { // 入れ子のコルーチンを呼び出す StartCoroutine(ParentRoutine()); } IEnumerator ParentRoutine() {
Debug.Log("start parent"); // Unity 5.2以前で子コルーチンの呼び出し // StartCoroutineが必要! yield return StartCoroutine(ChildRoutine()); Debug.Log("end parent"); } IEnumerator ChildRoutine() { Debug.Log("start child"); yield return new WaitForSeconds(1.0F); Debug.Log("end child"); } 実行結果 start parent start child end child end parent
コンパイルエラーにならないからこそたちが悪い! Unity 5.3以上になれている人が、古いプロジェクトを触って これに気が付かず、コンパイルは通るのに 「あれ、なんか思ってる挙動と違う!?」ってなるorz
その2
その2 WaitForSecondsはTime.timeScaleの影響を受ける 影響を受けたくないならば、WaitForSecondsRealtimeを使う! 注) WaitForSecondsRealtimeはUnity 5.3から利用可能
IEnumerator WaitRoutine() { Debug.Log("start"); // ↓Time.timescaleの影響を受ける yield return new WaitForSeconds(1.0F);
// ↓Time.timescaleの影響を受けない yield return new WaitForSecondsRealtime(1.0F); Debug.Log("end"); }
その3
その3 Unity 5.3からはWaitUntil、WaitWhile、 そしてCustomYieldInstructionを活用しよう!
IEnumerator BattleRoutine() { SetUiBeforeBattle(); yield return new WaitUntil(() => onReadyBattle);
// onReadyBattleがtrueになったらここに到達 StartBattle(); // 略 }
CustomYieldInstructionを使えば、 自分でWaitUntil・WaitWhileみたいなクラスを 柔軟に作れる
その4
その4 Unity 5.2とそれより古いバージョンでも WaitUntil、WaitWhile、CustomYieldInstructionは作れる・使える ただしStartCoroutineとの併用が必要!
WaitUntil、WaitWhile、CustomYieldInstructionは Unity 5.3から導入された型。けどUnity 5.2以前でも自分で作れる。
public abstract class CustomYieldInstruction : IEnumerator { public abstract bool
keepWaiting { get; } public object Current { get { return null; } } public bool MoveNext() { return keepWaiting; } public void Reset() { } } public sealed class WaitUntil : CustomYieldInstruction { Func<bool> m_Predicate; public override bool keepWaiting { get { return !m_Predicate(); } } public WaitUntil(Func<bool> predicate) { m_Predicate = predicate; } }
IEnumerator BattleRoutine() { SetUiBeforeBattle(); // StartCoroutineが必要なことに注意! yield return new StartCoroutine(WaitUntil(()
=> onReadyBattle)); // onReadyBattleがtrueになったらここに到達 StartBattle(); // 略 }
その5
その5 StopCoroutine(Coroutine routine)が使えるのは、 Unity 2017.1から!
その6
その6 StartCoroutineしたコンポーネントがdisableになっても Coroutineは動き続ける
その7
その7 StartCoroutineしたコンポーネントが破壊されると Coroutineは止まる
その8
その8 StartCoroutineしたコンポーネントを 持つGameObjectが破壊されるとCoroutineは止まる
その9
その9 StartCoroutineしたコンポーネントを 持つGameObjectがSetActivate(false) されると Coroutineは止まる。再開もしない。
「あれ何でCoroutine動かないの?」って思ったら、 コンポーネントが破壊されてないかも確認しましょう
その10
その10 StartCoroutine(IEnumerator)したCoroutineは、 StopCoroutine(string)じゃ止められない。
void Start() { StartCoroutine(SpawnRoutine()); } void StopSpawn() { // StartCoroutine(IEnumerator)で始めたCoroutineは、
// StopCoroutine(string)では止められない StopCoroutine("SpawnRoutine"); } IEnumerator SpawnRoutine() { // 略 }
その11
その11 あるコンポーネントにおいて StartCoroutine(string)したCoroutineが複数あって、 StopCoroutine(string) すると そのstring(メソッド名)のすべてのCoroutineが止まる
void Start() { // Coroutineは複数走っている StartCoroutine("SpawnRoutine"); StartCoroutine("SpawnRoutine"); } void StopSpawn()
{ // このコンポーネントのSpawnRoutine(文字列)がすべて止まる StopCoroutine("SpawnRoutine"); } IEnumerator SpawnRoutine() { // 略 }
※ 文字列でのStartCoroutine・StopCoroutineの利用 おすすめしません
その12
その12 StopAllCoroutinesはそのコンポーネントがStartした Coroutineをすべて止める StartCoroutine(string)・StartCoroutine(IEnumerator)で始めたやつどちらもすべて。
その13
その13 StartやOnCollisionEnterなどのイベント関数も Coroutineライクに書ける
void OnCollisionEnter(Collision collision) { Debug.Log(collision.gameObject.name); // すぐに殺す Destroy(collision.gameObject); }
// voidじゃなくて、IEnumerator IEnumerator OnCollisionEnter(Collision collision) { Debug.Log(collision.gameObject.name); // 1秒待ってから殺す yield
return new WaitForSeconds(1.0F); Destroy(collision.gameObject); }
その14
その14 Coroutineはコンポーネントのインスタンスに紐づく
その15
その15 Coroutineはメインスレッドで動く
まとめ
Coroutineがasync/awaitの代わりになるわけじゃない async/awaitが使える場所ではそっち使おう! Rxが適切な時もあるよ!
けれど、それでも・・・
古いプロジェクトをメンテ・改善していると Coroutineが助けてくれること、ある! Coroutineのデバックで嵌ることも、あるかも! 今更だけど、このタイミングで確認、大切ですね!
async / awaitはいいぞ! Rxもいいぞ! Coroutineもプロジェクトによっては、使う時があるよね!
いまさらだけど確認しておこう Coroutine @RyotaMurohoshi 2018/09/15(土) Unity非同期完全に理解した勉強会