feat: add bootstrap architecture and common utilities for Unity project
- Add GameLifetimeScope for dependency injection with Zenject - Implement boot flow service with entry point and interfaces - Create boot state machine (Splash, Menu, Load states) - Add UI views for boot screens - Add common services base class and interface - Implement generic state machine controller - Add base UI view components and ViewModel interface - Update SampleScene.unity - Add BootSettings asset Добавлена архитектура bootstrap и общие утилиты для Unity проекта: - Добавлен GameLifetimeScope для внедрения зависимостей (Zenject) - Реализован сервис потока загрузки с точкой входа и интерфейсами - Создана машина состояний загрузки (Splash, Menu, Load состояния) - Добавлены UI представления для экранов загрузки - Добавлены базовые классы сервисов и интерфейс IService - Реализован контроллер машины состояний - Добавлены базовые компоненты UI вида и интерфейс ViewModel - Обновлена сцена SampleScene.unity - Добавлен ассет BootSettings
This commit is contained in:
@@ -206,3 +206,179 @@ Transform:
|
|||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_RootOrder: 0
|
m_RootOrder: 0
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!1 &1000000001
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1000000002}
|
||||||
|
- component: {fileID: 1000000003}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: GameLifetimeScope
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &1000000002
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1000000001}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 1
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1000000003
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1000000001}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: a1111111111111111111111111111111, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
<BootSettings>k__BackingField: {fileID: 11400000, guid: c1111111111111111111111111111111, type: 2}
|
||||||
|
<SplashView>k__BackingField: {fileID: 1000000103}
|
||||||
|
<LoadingView>k__BackingField: {fileID: 1000000203}
|
||||||
|
<MenuView>k__BackingField: {fileID: 1000000303}
|
||||||
|
--- !u!1 &1000000101
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1000000102}
|
||||||
|
- component: {fileID: 1000000103}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: SplashView
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 0
|
||||||
|
--- !u!4 &1000000102
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1000000101}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 2
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1000000103
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1000000101}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b1111111111111111111111111111111, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
--- !u!1 &1000000201
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1000000202}
|
||||||
|
- component: {fileID: 1000000203}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: LoadingView
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 0
|
||||||
|
--- !u!4 &1000000202
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1000000201}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 3
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1000000203
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1000000201}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b2222222222222222222222222222222, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
--- !u!1 &1000000301
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 1000000302}
|
||||||
|
- component: {fileID: 1000000303}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: MenuView
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 0
|
||||||
|
--- !u!4 &1000000302
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1000000301}
|
||||||
|
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||||
|
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||||
|
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||||
|
m_Children: []
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 4
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &1000000303
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 1000000301}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b3333333333333333333333333333333, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d1111111111111111111111111111111
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d2222222222222222222222222222222
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d3333333333333333333333333333333
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using QuizPleaseTest.Boot.Flow;
|
||||||
|
using QuizPleaseTest.Boot.Settings;
|
||||||
|
using QuizPleaseTest.Boot.States;
|
||||||
|
using QuizPleaseTest.Boot.UI;
|
||||||
|
using QuizPleaseTest.Common.Services;
|
||||||
|
using QuizPleaseTest.Common.StateMachine;
|
||||||
|
using UnityEngine;
|
||||||
|
using VContainer;
|
||||||
|
using VContainer.Unity;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.Composition
|
||||||
|
{
|
||||||
|
public class GameLifetimeScope : LifetimeScope
|
||||||
|
{
|
||||||
|
[field: SerializeField] public BootSettings BootSettings { get; private set; }
|
||||||
|
[field: SerializeField] public SplashUIView SplashView { get; private set; }
|
||||||
|
[field: SerializeField] public LoadingUIView LoadingView { get; private set; }
|
||||||
|
[field: SerializeField] public MenuUIView MenuView { get; private set; }
|
||||||
|
|
||||||
|
protected override void Configure(IContainerBuilder builder)
|
||||||
|
{
|
||||||
|
builder.RegisterInstance(BootSettings);
|
||||||
|
|
||||||
|
builder.RegisterComponent(SplashView);
|
||||||
|
builder.RegisterComponent(LoadingView);
|
||||||
|
builder.RegisterComponent(MenuView);
|
||||||
|
|
||||||
|
builder.Register<BootFlowService>(Lifetime.Singleton)
|
||||||
|
.As<IBootFlowService>()
|
||||||
|
.As<IService>();
|
||||||
|
|
||||||
|
builder.Register<BootStatesController>(Lifetime.Singleton)
|
||||||
|
.As<IStatesController<BootStateCode>>()
|
||||||
|
.AsSelf();
|
||||||
|
|
||||||
|
builder.Register<SplashState>(Lifetime.Singleton);
|
||||||
|
builder.Register<LoadState>(Lifetime.Singleton);
|
||||||
|
builder.Register<MenuState>(Lifetime.Singleton);
|
||||||
|
|
||||||
|
builder.RegisterEntryPoint<BootstrapEntryPoint>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a1111111111111111111111111111111
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d4444444444444444444444444444444
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using QuizPleaseTest.Common.Services;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.Flow
|
||||||
|
{
|
||||||
|
public class BootFlowService : Service, IBootFlowService
|
||||||
|
{
|
||||||
|
public override UniTask InitializeAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override UniTask ReleaseAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f3333333333333333333333333333333
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
using VContainer.Unity;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.Flow
|
||||||
|
{
|
||||||
|
public class BootstrapEntryPoint : IStartable, IDisposable
|
||||||
|
{
|
||||||
|
private readonly IBootFlowService _bootFlowService;
|
||||||
|
private CancellationTokenSource _lifetimeCts;
|
||||||
|
|
||||||
|
public BootstrapEntryPoint(IBootFlowService bootFlowService)
|
||||||
|
{
|
||||||
|
_bootFlowService = bootFlowService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
_lifetimeCts = new CancellationTokenSource();
|
||||||
|
RunAsync(_lifetimeCts.Token).Forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_lifetimeCts == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lifetimeCts.Cancel();
|
||||||
|
_bootFlowService.ReleaseAsync(CancellationToken.None).Forget();
|
||||||
|
_lifetimeCts.Dispose();
|
||||||
|
_lifetimeCts = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async UniTask RunAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _bootFlowService.InitializeAsync(ct);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (ct.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
Debug.LogException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f4444444444444444444444444444444
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using QuizPleaseTest.Common.Services;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.Flow
|
||||||
|
{
|
||||||
|
public interface IBootFlowService : IService
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f2222222222222222222222222222222
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d5555555555555555555555555555555
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.Settings
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(fileName = "BootSettings", menuName = "QuizPleaseTest/Boot Settings")]
|
||||||
|
public class BootSettings : ScriptableObject
|
||||||
|
{
|
||||||
|
[field: SerializeField] public float SplashDurationSeconds { get; private set; } = 1f;
|
||||||
|
[field: SerializeField] public int LoadSteps { get; private set; } = 5;
|
||||||
|
[field: SerializeField] public int LoadStepDurationMs { get; private set; } = 200;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b4444444444444444444444444444444
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d6666666666666666666666666666666
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace QuizPleaseTest.Boot.States
|
||||||
|
{
|
||||||
|
public enum BootStateCode
|
||||||
|
{
|
||||||
|
Splash,
|
||||||
|
Load,
|
||||||
|
Menu
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f5555555555555555555555555555555
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using QuizPleaseTest.Common.StateMachine;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.States
|
||||||
|
{
|
||||||
|
public class BootStatesController : StatesController<BootStateCode>
|
||||||
|
{
|
||||||
|
public BootStatesController(
|
||||||
|
SplashState splashState,
|
||||||
|
LoadState loadState,
|
||||||
|
MenuState menuState)
|
||||||
|
: base(CreateStates(splashState, loadState, menuState))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IReadOnlyDictionary<BootStateCode, IState> CreateStates(
|
||||||
|
SplashState splashState,
|
||||||
|
LoadState loadState,
|
||||||
|
MenuState menuState)
|
||||||
|
{
|
||||||
|
return new Dictionary<BootStateCode, IState>
|
||||||
|
{
|
||||||
|
{ BootStateCode.Splash, splashState },
|
||||||
|
{ BootStateCode.Load, loadState },
|
||||||
|
{ BootStateCode.Menu, menuState }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f6666666666666666666666666666666
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using QuizPleaseTest.Boot.UI;
|
||||||
|
using QuizPleaseTest.Common.StateMachine;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.States
|
||||||
|
{
|
||||||
|
public class LoadState : IState
|
||||||
|
{
|
||||||
|
private readonly LoadingUIView _view;
|
||||||
|
|
||||||
|
public LoadState(LoadingUIView view)
|
||||||
|
{
|
||||||
|
_view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask EnterAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
_view.Initialize();
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask ExitAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
_view.Release();
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f8888888888888888888888888888888
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using QuizPleaseTest.Boot.UI;
|
||||||
|
using QuizPleaseTest.Common.StateMachine;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.States
|
||||||
|
{
|
||||||
|
public class MenuState : IState
|
||||||
|
{
|
||||||
|
private readonly MenuUIView _view;
|
||||||
|
|
||||||
|
public MenuState(MenuUIView view)
|
||||||
|
{
|
||||||
|
_view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask EnterAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
_view.Initialize();
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask ExitAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
_view.Release();
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f9999999999999999999999999999999
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using QuizPleaseTest.Boot.UI;
|
||||||
|
using QuizPleaseTest.Common.StateMachine;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.States
|
||||||
|
{
|
||||||
|
public class SplashState : IState
|
||||||
|
{
|
||||||
|
private readonly SplashUIView _view;
|
||||||
|
|
||||||
|
public SplashState(SplashUIView view)
|
||||||
|
{
|
||||||
|
_view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask EnterAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
_view.Initialize();
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTask ExitAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
_view.Release();
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f7777777777777777777777777777777
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d7777777777777777777777777777777
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using QuizPleaseTest.Common.UI;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.UI
|
||||||
|
{
|
||||||
|
public class LoadingUIView : UIView
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b2222222222222222222222222222222
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using QuizPleaseTest.Common.UI;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.UI
|
||||||
|
{
|
||||||
|
public class MenuUIView : UIView
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b3333333333333333333333333333333
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using QuizPleaseTest.Common.UI;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Boot.UI
|
||||||
|
{
|
||||||
|
public class SplashUIView : UIView
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b1111111111111111111111111111111
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d8888888888888888888888888888888
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d9999999999999999999999999999999
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Common.Services
|
||||||
|
{
|
||||||
|
public interface IService
|
||||||
|
{
|
||||||
|
UniTask InitializeAsync(CancellationToken ct);
|
||||||
|
UniTask ReleaseAsync(CancellationToken ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e3333333333333333333333333333333
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Common.Services
|
||||||
|
{
|
||||||
|
public class Service : IService
|
||||||
|
{
|
||||||
|
public virtual UniTask InitializeAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual UniTask ReleaseAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
return UniTask.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e4444444444444444444444444444444
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e1111111111111111111111111111111
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Common.StateMachine
|
||||||
|
{
|
||||||
|
public interface IState
|
||||||
|
{
|
||||||
|
UniTask EnterAsync(CancellationToken ct);
|
||||||
|
UniTask ExitAsync(CancellationToken ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e5555555555555555555555555555555
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Common.StateMachine
|
||||||
|
{
|
||||||
|
public interface IStatesController<TEnum>
|
||||||
|
{
|
||||||
|
UniTask EnterStateAsync(TEnum code, CancellationToken ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e6666666666666666666666666666666
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Common.StateMachine
|
||||||
|
{
|
||||||
|
public class StatesController<TEnum> : IStatesController<TEnum>
|
||||||
|
{
|
||||||
|
private readonly IReadOnlyDictionary<TEnum, IState> _states;
|
||||||
|
private IState _currentState;
|
||||||
|
|
||||||
|
public StatesController(IReadOnlyDictionary<TEnum, IState> states)
|
||||||
|
{
|
||||||
|
_states = states;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async UniTask EnterStateAsync(TEnum code, CancellationToken ct)
|
||||||
|
{
|
||||||
|
if (!_states.TryGetValue(code, out IState newState))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"State is not registered: {code}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentState != null)
|
||||||
|
{
|
||||||
|
await _currentState.ExitAsync(ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentState = newState;
|
||||||
|
await _currentState.EnterAsync(ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e7777777777777777777777777777777
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e2222222222222222222222222222222
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace QuizPleaseTest.Common.UI
|
||||||
|
{
|
||||||
|
public interface IUIViewModel
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e8888888888888888888888888888888
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
namespace QuizPleaseTest.Common.UI
|
||||||
|
{
|
||||||
|
public class UIView<TVm> : UIView where TVm : IUIViewModel
|
||||||
|
{
|
||||||
|
public TVm ViewModel { get; private set; }
|
||||||
|
|
||||||
|
public virtual void Bind(TVm viewModel)
|
||||||
|
{
|
||||||
|
ViewModel = viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Release()
|
||||||
|
{
|
||||||
|
base.Release();
|
||||||
|
ViewModel = default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f1111111111111111111111111111111
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace QuizPleaseTest.Common.UI
|
||||||
|
{
|
||||||
|
public class UIView : MonoBehaviour
|
||||||
|
{
|
||||||
|
public virtual void Initialize()
|
||||||
|
{
|
||||||
|
gameObject.SetActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Release()
|
||||||
|
{
|
||||||
|
gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e9999999999999999999999999999999
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c2222222222222222222222222222222
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: b4444444444444444444444444444444, type: 3}
|
||||||
|
m_Name: BootSettings
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
<SplashDurationSeconds>k__BackingField: 1
|
||||||
|
<LoadSteps>k__BackingField: 5
|
||||||
|
<LoadStepDurationMs>k__BackingField: 200
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c1111111111111111111111111111111
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user