Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
どこのご家庭にもあるシーンマネージャーの話
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
いも
March 24, 2021
Programming
8.8k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
どこのご家庭にもあるシーンマネージャーの話
いも
March 24, 2021
More Decks by いも
See All by いも
UnityプログラミングバイブルR6号宣伝&Unity Logging小話
adarapata
0
650
Unityテスト活動のふりかえり
adarapata
1
700
Gather.townはいいぞ その後
adarapata
1
1.7k
Unityでの開発事例
adarapata
3
23k
Gather.townはいいぞ
adarapata
2
2.5k
宴はいいぞ
adarapata
0
2.2k
わかった気になるモブプログラミング
adarapata
1
180
モブワークっぽいのをやっている話/Trying mobwork
adarapata
2
1.3k
Zenjectを導入する前に
adarapata
0
4.1k
Other Decks in Programming
See All in Programming
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
140
Foundry Localでエージェント開発
seosoft
0
160
Building an Out-of-Order CPU
latte72
1
740
AI駆動開発にグラフDBを重ねてみた
satoshi256kbyte
2
770
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
130
XHTMLが残したもの
yosuke_furukawa
PRO
2
640
DynamoDBの基礎を振り返りながらベクトル検索機能を理解する
musan
3
280
GKE アップグレード前に知っておきたい Blue/Green と PDB の関係
stkk
0
160
Can LLMs Replicate 4 Years of Compose Migration? Exploring the boundaries of automation with 279 XML files from a real product
makun
0
130
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
150
巨大モノリシックアプリ モダン化大作戦
ktcryomm
0
420
Family mrubyの進捗
kishima
1
110
Featured
See All Featured
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
710
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
Deep Space Network (abreviated)
tonyrice
0
300
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
680
Balancing Empowerment & Direction
lara
6
1.3k
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
880
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
560
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
690
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
840
How to Ace a Technical Interview
jacobian
281
24k
Transcript
━━━ どのご家庭にもある シーンマネージャーの話 いも ━━━ 2021/03/24 Gotanda.unity #17 1
いもです twitter @adarapata Unity触ったりしています Godot Engineも好きです 2021/03/24 Gotanda.unity #17 2
モチベーション 画⾯遷移の管理の仕組みを毎回作っている気がする みんな各⾃で似たようなもの作ってる気がする しかしあまり公開されてる気がしない 話すからみんなも教えて下さい 2021/03/24 Gotanda.unity #17 3
シーンマネージャー is Unityでの「画⾯をいい感じに管理してくれる」君 画⾯の単位を定義して管理する 1Sceneとか1Prefabとか 画⾯をスタックできる 前の画⾯に戻ったりとか 画⾯遷移にデータを渡せる 前の画⾯で選択した設定でクエストに挑むとか 2021/03/24
Gotanda.unity #17 4
Unityデフォルトでの画⾯管理 Sceneファイルの切り替え・追加は可能 Prefabはデフォルトではない 画⾯の名称の管理が必要 遷移先の⽂字列 or Indexをどう持つか。増えたらどうするか パラメータを渡す⼿段がデフォルトではない スタックする機能はない ⼀個前の画⾯の状態を保持させるなど
この辺を解決するために画⾯管理クラスを作ったりする 2021/03/24 Gotanda.unity #17 5
解決したいこと 画⾯をスタックできること パラメータを渡せること 名称の管理が楽なこと 2021/03/24 Gotanda.unity #17 6
⾃作の⼀例 : PageManager 画⾯のことを「Page」と呼ぶ SceneはUnityの呼称とかぶるのでPageにした 1Page = 1Prefab Page Prefabを動的にロードして追加する
Pageをスタックしており、前のPageに戻れる 遷移先Pageを型で呼ぶ パラメータを型で渡せる 依存関係の解決にVContainerを使⽤ 2021/03/24 Gotanda.unity #17 7
呼び⽅ var parameter = new FooPage.CreateParameter { Bar = "bar"
}; _pageManager.Push(new FooPage.Transition { Parameter = parameter }); // 追加 _pageManager.Pop(); // ⼀つ前に戻る _pageManager.Replace(new FooPage.Transition { Parameter = parameter }); // 現在のページを破棄して追加する // スタックしたページをすべて破棄して追加する _pageManager.ReplaceAll(new FooPage.Transition { Parameter = parameter }); await _pageManager.PushAsync(new FooPage.Transition { Parameter = parameter }); // ⾮同期で追加 2021/03/24 Gotanda.unity #17 8
Page定義側 [PageAsset("BarPage.prefab")] public class BarPage : BasePage { public class
Transition : BasePageTransition<BarPage>{} } 2021/03/24 Gotanda.unity #17 9
登場⼈物 PageManager : ページのスタック・ライフサイクル管理者 IPageTransition : ページ遷移者 BasePage : ページ本体
2021/03/24 Gotanda.unity #17 10
クラス図 2021/03/24 Gotanda.unity #17 11
PageManager Pageのスタックを管理する リストで保持してる 読み込まれたPageに対して初期化・停⽌というライフサイクルイベ ントを呼んであげるのが役割 具体的にどうやってPageが読み込まれるのかは知らない public async UniTask PushAsync(IPageTransition
transition) { var page = await transition.LoadPage(); await page.Initialize(); _pages.Add(page); // ページリストの管理 } 2021/03/24 Gotanda.unity #17 12
処理の流れ 2021/03/24 Gotanda.unity #17 13
ライフサイクル Unityのライフサイクルに合わせるとハンドリングしにくい StartはPageManager側から⾒て初期化済みか保証できない Destroyで破棄はできるが⼀時停⽌とか再開がない なのでざっくりと4つのライフサイクルイベントを⽤意 Initialize Suspend Resume Discard 2021/03/24
Gotanda.unity #17 14
Pushすると、現在のPageのSupend、新しいPageのInitializeが呼ばれ る Popすると、現在のPageのSuspend->Discard、⼀つ前のPageの Resumeが呼ばれる 2021/03/24 Gotanda.unity #17 15
BasePage 画⾯⾃体を司るクラス ライフサイクルを実装しており、初期化とか停⽌とかできる PageManagerとか外の世界とのやり取りを⾏う際の受け⼝ なので内部はMVCとかMVPとか好きに分割してる 2021/03/24 Gotanda.unity #17 16
public abstract class BasePage { public virtual UniTask Initialize(); public
virtual UniTask Suspend(); public virtual UniTask Resume(); public virtual UniTask Discard(); } public abstract class BasePage<TParam> : BasePage { protected TParam Parameter { get; } } 2021/03/24 Gotanda.unity #17 17
IPageTransition Pageの呼び出し⽅を知っているやつ PageManagerが直接Pageの呼び出しを⾏うのではなく IPageTransitionに具体的な呼び出しをお任せする public class PageTransitionBase<TPage> : IPageTransition where
TPage : BasePage { public virtual async UniTask<PageBase> LoadPage() { var pageInstance = await DoPrefabLoad(pageAssetName); var pageLifetimeScope = pageInstance.GetComponent<LifetimeScope>(); InitializePageParameter(pageLifetimeScope); pageLifetimeScope.Build(); // Page側の依存関係解決 var page = pageLifetimeScope.Container.Resolve<TPage>(); return page; } } 2021/03/24 Gotanda.unity #17 18
リソースとクラスのマッピング どのアセットを引っ張ってくるのかパスを渡したい 毎回⼿打ちで渡したくはない クラス定義とPageアセットは原則1:1と考えて良い // pageAssetNameをどう渡すか var pageInstance = await
DoPrefabLoad(pageAssetName); カスタムアトリビュートで直接紐付けてしまう 2021/03/24 Gotanda.unity #17 19
[AttributeUsage(AttributeTargets.Class, Inherited = false)] public class PageAssetAttribute : Attribute {
public string PrefabName { get; } public PageAssetAttribute(string prefabName) { this.PrefabName = prefabName; } } [PageAsset("BarPage.prefab")] public class BarPage : BasePage { public class Transition : BasePageTransition<BarPage>{} } // PageAssetAttributeを取り出す var pageNameAttr = Attribute.GetCustomAttribute(typeof(TPage), typeof(PageAssetAttribute)) as PageAssetAttribute; var pageInstance = await DoPrefabLoad(pageNameAttr.PrefabName); 2021/03/24 Gotanda.unity #17 20
パラメータ渡し [PageAsset("FooPage.prefab")] public class FooPage : BasePage<FooPage.CreateParameter> { public class
CreateParameter { public string Bar; } public class Transition : BasePageTransition<FooPage, CreateParameter> { } } ジェネリクスで定義できるようにする 2021/03/24 Gotanda.unity #17 21
そもそも外部パラメータをどう扱っているのか public class LifetimeScopeWithParameter<TParam> : LifetimeScope { public TParam Param;
protected override void Configure(IContainerBuilder builder) { builder.RegisterInstance(Param); } } 外からパラメータを設定できるようなLifetimeScopeを⽤意 2021/03/24 Gotanda.unity #17 22
パラメータを設定した上でBuildする public class BasePageTransition<TPage> : IPageTransition where TPage : BasePage
{ public virtual async UniTask<PageBase> LoadPage() { var pageInstance = await DoPrefabLoad(pageAssetName); var pageLifetimeScope = pageInstance.GetComponent<LifetimeScope>(); InitializePageParameter(pageLifetimeScope); pageLifetimeScope.Build(); // Page側の依存関係解決 var page = pageLifetimeScope.Container.Resolve<TPage>(); return page; } protected virtual void InitializePageParameter(LifetimeScope container) { } } public class BasePageTransition<TPage, TParam> : PageTransitionBase<TPage> where TPage : BasePage<TParam> { public TParam Parameter { get; set; } protected override void InitializePageParameter(LifetimeScope scope) { if (scope is LifetimeScopeWithParameter<TParam> s) { s.Parameter = Parameter; } } } 2021/03/24 Gotanda.unity #17 23
PageのアセットにLifetimeScopeをアタッチする public class FooLifetimeScope : LifetimeScopeWithParameter<FooPage.CreateParameter> { [SerializeField] private FooView
_fooView; protected override void Configure(IContainerBuilder builder) { base.Configure(builder); builder.Register<FooPage>(Lifetime.Scoped); builder.Register<FooPresenter>(Lifetime.Scoped); builder.Register<FooModel>(Lifetime.Scoped); builder.RegisterComponent(_fooView); } } これでPageのオブジェクトに外部データをInjectionできる 2021/03/24 Gotanda.unity #17 24
好きなところ 型ベースで画⾯遷移を⾏える 定数を管理しなくていい 渡すべきパラメータも型で管理できるので楽 コード⾒ればリソースがわかる 1:1の関係なら密接でもいいんじゃない派 2021/03/24 Gotanda.unity #17 25
PageManagerまとめ 遷移先をクラス名で指定できる パラメータも型で定義して渡せる Managerから詳細な遷移処理を切り出している Pageは独⾃にライフサイクルを持たせている クラスとアセットをカスタムアトリビュートで紐付けしている 2021/03/24 Gotanda.unity #17 26
みなさんの 画⾯遷移マネージャーの話を お待ちしています 2021/03/24 Gotanda.unity #17 27