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
いも
March 24, 2021
Programming
8.9k
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
660
Unityテスト活動のふりかえり
adarapata
1
710
Gather.townはいいぞ その後
adarapata
1
1.7k
Unityでの開発事例
adarapata
3
23k
Gather.townはいいぞ
adarapata
2
2.5k
宴はいいぞ
adarapata
0
2.3k
わかった気になるモブプログラミング
adarapata
1
180
モブワークっぽいのをやっている話/Trying mobwork
adarapata
2
1.3k
Zenjectを導入する前に
adarapata
0
4.1k
Other Decks in Programming
See All in Programming
dotNET_vulnclicker_intro.pdf
deka_morita
0
130
[2026-09-26]空論ジェネリックプロセス~テスト資産とAIで紡ぐ、再現可能なパフォーマンスチューニングの話~
tosite
0
260
Simple Storage Service(S3) is not simple
iwatsukayura
0
230
contenteditable と日本語入力に向き合う
colorful12
0
180
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
5k
外から家のPCの電源入れたい!をPHPで解決する
kawashimo0
1
120
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
340
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
150
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
140
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.5k
Workers Cache を知る
syumai
0
350
難しいけど、読めた。- OSSの入口に立った話。
sts11142
0
140
Featured
See All Featured
Designing for humans not robots
tammielis
254
26k
Paper Plane
katiecoart
PRO
4
54k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
7k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
The Language of Interfaces
destraynor
162
27k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.6k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
Done Done
chrislema
187
17k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
340
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
420
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
320
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