合并 P0 主菜单示例
This commit is contained in:
8
My project/Assets/FlowScope/Samples.meta
Normal file
8
My project/Assets/FlowScope/Samples.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c21892f24eee4c20b29f51afc7228321
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 76085fdd1da44ab08b69395b17064b59
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"Gold": 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bd391f0c499b42a3a264d0a9de2483f8
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c88fe653c15d473cac0029539a2ff355
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &100000
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component: []
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: MainMenuPanel
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_IsActive: 1
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9841d62cd2d24cb48e23ac11adaaf5a9
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 946526d21b06440688088de21f383782
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!29 &1
|
||||||
|
OcclusionCullingSettings:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
--- !u!104 &2
|
||||||
|
RenderSettings:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
--- !u!157 &3
|
||||||
|
LightmapSettings:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
--- !u!196 &4
|
||||||
|
NavMeshSettings:
|
||||||
|
serializedVersion: 2
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
--- !u!1 &100000
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component: []
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: MainMenuP0
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_IsActive: 1
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 03630d34cf304668afe00ab221f3557e
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 93879cc02e2644039382a2006c5434b1
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FlowScope.Audio;
|
||||||
|
using FlowScope.Config;
|
||||||
|
using FlowScope.Flow;
|
||||||
|
using FlowScope.Resources;
|
||||||
|
using FlowScope.Save;
|
||||||
|
using FlowScope.UI;
|
||||||
|
using UnityEngine;
|
||||||
|
using ContainerType = FlowScope.Container.Container;
|
||||||
|
|
||||||
|
namespace FlowScope.Samples.MainMenuP0
|
||||||
|
{
|
||||||
|
public sealed class GameBootstrap : MonoBehaviour
|
||||||
|
{
|
||||||
|
private const string SaveKey = "main-menu-player";
|
||||||
|
|
||||||
|
[SerializeField] private Canvas hudCanvas;
|
||||||
|
[SerializeField] private MainMenuPanel mainMenuPanelPrefab;
|
||||||
|
[SerializeField] private int defaultGold;
|
||||||
|
|
||||||
|
private ContainerType _root;
|
||||||
|
private GameFlow _gameFlow;
|
||||||
|
private ISaveService _saveService;
|
||||||
|
private PlayerData _playerData;
|
||||||
|
private CancellationTokenSource _lifetime;
|
||||||
|
|
||||||
|
private async void Awake()
|
||||||
|
{
|
||||||
|
_lifetime = new CancellationTokenSource();
|
||||||
|
await StartupAsync(_lifetime.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StartupAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_root = new ContainerType();
|
||||||
|
_gameFlow = new GameFlow();
|
||||||
|
|
||||||
|
var resources = new SampleResourceService();
|
||||||
|
if (mainMenuPanelPrefab != null)
|
||||||
|
{
|
||||||
|
resources.Register("FlowScope/Samples/MainMenuP0/MainMenuPanel", mainMenuPanelPrefab.gameObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
_saveService = new SaveService(
|
||||||
|
new FileSaveStorage(),
|
||||||
|
new JsonSaveSerializer());
|
||||||
|
_playerData = await _saveService.LoadAsync(
|
||||||
|
SaveKey,
|
||||||
|
new PlayerData { Gold = new R3.ReactiveProperty<int>(defaultGold) },
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
var uiManager = new UIManager(resources);
|
||||||
|
uiManager.RegisterLayer("hud", ResolveHudCanvas(), 0, PanelStrategy.Cache);
|
||||||
|
|
||||||
|
var audioService = gameObject.AddComponent<AudioService>().Initialize(resources);
|
||||||
|
_root.RegisterInstance(_root);
|
||||||
|
_root.RegisterInstance<IConfigProvider>(
|
||||||
|
new JsonConfigProvider(Array.Empty<JsonConfigProvider.ConfigMapping>()));
|
||||||
|
_root.RegisterInstance<IResourceService>(resources);
|
||||||
|
_root.RegisterInstance<ISaveService>(_saveService);
|
||||||
|
_root.RegisterInstance<IAudioService>(audioService);
|
||||||
|
_root.RegisterInstance(uiManager);
|
||||||
|
_root.RegisterInstance(_playerData);
|
||||||
|
_root.RegisterFactory(_ => new MainMenuFeature(uiManager, _playerData));
|
||||||
|
|
||||||
|
await _gameFlow.StartupAsync<MainMenuFeature>(_root, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ShutdownAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (_saveService != null && _playerData != null)
|
||||||
|
{
|
||||||
|
await _saveService.SaveAsync(SaveKey, _playerData, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_gameFlow != null && _gameFlow.State != GameFlowState.Disposed)
|
||||||
|
{
|
||||||
|
await _gameFlow.ShutdownAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnApplicationQuit()
|
||||||
|
{
|
||||||
|
_lifetime?.Cancel();
|
||||||
|
await ShutdownAsync(CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
_lifetime?.Cancel();
|
||||||
|
_lifetime?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Canvas ResolveHudCanvas()
|
||||||
|
{
|
||||||
|
if (hudCanvas != null)
|
||||||
|
{
|
||||||
|
return hudCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
var canvasObject = new GameObject("FlowScope HUD Canvas");
|
||||||
|
canvasObject.transform.SetParent(transform, false);
|
||||||
|
hudCanvas = canvasObject.AddComponent<Canvas>();
|
||||||
|
hudCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
|
return hudCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class SampleResourceService : IResourceService
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, GameObject> _prefabs = new();
|
||||||
|
|
||||||
|
public void Register(string key, GameObject prefab)
|
||||||
|
{
|
||||||
|
_prefabs[key] = prefab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<IResourceHandle<T>> LoadAsync<T>(
|
||||||
|
string key,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
where T : class
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
if (typeof(T) == typeof(GameObject) &&
|
||||||
|
_prefabs.TryGetValue(key, out var prefab))
|
||||||
|
{
|
||||||
|
return Task.FromResult<IResourceHandle<T>>(
|
||||||
|
new SampleResourceHandle<T>(key, prefab as T));
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException($"Sample resource is not registered: {key}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IResourceGroup CreateGroup()
|
||||||
|
{
|
||||||
|
return new ResourceGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class SampleResourceHandle<T> : IResourceHandle<T> where T : class
|
||||||
|
{
|
||||||
|
public SampleResourceHandle(string key, T asset)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
Asset = asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Key { get; }
|
||||||
|
public T Asset { get; private set; }
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
IsDisposed = true;
|
||||||
|
Asset = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cd97432f2838454cbbf2d19dbe14d7f3
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using FlowScope.Flow;
|
||||||
|
using FlowScope.UI;
|
||||||
|
|
||||||
|
namespace FlowScope.Samples.MainMenuP0
|
||||||
|
{
|
||||||
|
public sealed class MainMenuFeature : FeatureBase
|
||||||
|
{
|
||||||
|
private readonly UIManager _uiManager;
|
||||||
|
private readonly PlayerData _playerData;
|
||||||
|
private MainMenuViewModel _viewModel;
|
||||||
|
|
||||||
|
public MainMenuFeature(UIManager uiManager, PlayerData playerData)
|
||||||
|
{
|
||||||
|
_uiManager = uiManager;
|
||||||
|
_playerData = playerData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task LoadAsync(FeatureContext context)
|
||||||
|
{
|
||||||
|
base.LoadAsync(context);
|
||||||
|
_viewModel = new MainMenuViewModel(_playerData);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task EnterAsync(FeatureContext context)
|
||||||
|
{
|
||||||
|
await _uiManager.OpenAsync<MainMenuPanel, MainMenuViewModel>(
|
||||||
|
_viewModel,
|
||||||
|
context.CancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task ExitAsync(FeatureContext context)
|
||||||
|
{
|
||||||
|
_uiManager.Close<MainMenuPanel>();
|
||||||
|
return base.ExitAsync(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
_viewModel = null;
|
||||||
|
base.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b015663928874766b56036f39f0aca6d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using FlowScope.UI;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace FlowScope.Samples.MainMenuP0
|
||||||
|
{
|
||||||
|
[UIPanel("hud", "FlowScope/Samples/MainMenuP0/MainMenuPanel", PanelStrategy.Cache)]
|
||||||
|
public sealed class MainMenuPanel : UIPanelBase<MainMenuViewModel>
|
||||||
|
{
|
||||||
|
[SerializeField] private Text goldText;
|
||||||
|
[SerializeField] private Button incrementButton;
|
||||||
|
|
||||||
|
public void Configure(Text goldLabel, Button incrementGoldButton)
|
||||||
|
{
|
||||||
|
goldText = goldLabel;
|
||||||
|
incrementButton = incrementGoldButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnBind(MainMenuViewModel viewModel)
|
||||||
|
{
|
||||||
|
if (goldText == null)
|
||||||
|
{
|
||||||
|
goldText = GetComponentInChildren<Text>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incrementButton == null)
|
||||||
|
{
|
||||||
|
incrementButton = GetComponentInChildren<Button>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateGold(viewModel.Gold.Value);
|
||||||
|
viewModel.GoldChanged += UpdateGold;
|
||||||
|
if (incrementButton != null)
|
||||||
|
{
|
||||||
|
incrementButton.onClick.AddListener(viewModel.IncrementGold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Unbind()
|
||||||
|
{
|
||||||
|
if (ViewModel != null)
|
||||||
|
{
|
||||||
|
ViewModel.GoldChanged -= UpdateGold;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incrementButton != null)
|
||||||
|
{
|
||||||
|
incrementButton.onClick.RemoveAllListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateGold(int value)
|
||||||
|
{
|
||||||
|
if (goldText != null)
|
||||||
|
{
|
||||||
|
goldText.text = value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3a641bd6447847f2af2cd5af40305a5a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using R3;
|
||||||
|
|
||||||
|
namespace FlowScope.Samples.MainMenuP0
|
||||||
|
{
|
||||||
|
public sealed class MainMenuViewModel
|
||||||
|
{
|
||||||
|
private readonly PlayerData _data;
|
||||||
|
|
||||||
|
public MainMenuViewModel(PlayerData data)
|
||||||
|
{
|
||||||
|
_data = data ?? throw new ArgumentNullException(nameof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactiveProperty<int> Gold => _data.Gold;
|
||||||
|
public event Action<int> GoldChanged;
|
||||||
|
|
||||||
|
public void IncrementGold()
|
||||||
|
{
|
||||||
|
Gold.Value++;
|
||||||
|
GoldChanged?.Invoke(Gold.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 68e2343c920540a280ac2718ceae12ed
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using R3;
|
||||||
|
|
||||||
|
namespace FlowScope.Samples.MainMenuP0
|
||||||
|
{
|
||||||
|
public sealed class PlayerData
|
||||||
|
{
|
||||||
|
public ReactiveProperty<int> Gold { get; set; } = new(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8d62814450dc46fba84df1fba2a372f4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
My project/Assets/FlowScope/Tests/PlayMode/Samples.meta
Normal file
8
My project/Assets/FlowScope/Tests/PlayMode/Samples.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 43a878f0cf3a402fb63a7ad3cb26d5aa
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FlowScope.Samples.MainMenuP0;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace FlowScope.Tests.PlayMode.Samples
|
||||||
|
{
|
||||||
|
public sealed class MainMenuP0Tests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void ViewModel_IncrementGold_UpdatesPlayerDataImmediately()
|
||||||
|
{
|
||||||
|
var data = new PlayerData();
|
||||||
|
var viewModel = new MainMenuViewModel(data);
|
||||||
|
|
||||||
|
viewModel.IncrementGold();
|
||||||
|
|
||||||
|
Assert.AreEqual(1, data.Gold.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Bootstrap_CanConstructAndShutdownWithoutSceneAsset()
|
||||||
|
{
|
||||||
|
var root = new GameObject("bootstrap-test");
|
||||||
|
var panelObject = new GameObject("panel-prefab");
|
||||||
|
panelObject.AddComponent<CanvasRenderer>();
|
||||||
|
var panel = panelObject.AddComponent<MainMenuPanel>();
|
||||||
|
var labelObject = new GameObject("gold");
|
||||||
|
labelObject.transform.SetParent(panelObject.transform, false);
|
||||||
|
var label = labelObject.AddComponent<Text>();
|
||||||
|
var buttonObject = new GameObject("button");
|
||||||
|
buttonObject.transform.SetParent(panelObject.transform, false);
|
||||||
|
var button = buttonObject.AddComponent<Button>();
|
||||||
|
panel.Configure(label, button);
|
||||||
|
|
||||||
|
var bootstrap = root.AddComponent<GameBootstrap>();
|
||||||
|
await bootstrap.ShutdownAsync(CancellationToken.None);
|
||||||
|
|
||||||
|
Object.DestroyImmediate(panelObject);
|
||||||
|
Object.DestroyImmediate(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 49ffcc8b051a462c95d2ee7e6ce2857b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user