diff --git a/game/Assets/Prefabs.meta b/game/Assets/Prefabs.meta new file mode 100644 index 0000000..d2fefc0 --- /dev/null +++ b/game/Assets/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f40cf77e2ef30fe4f8a89d5e5d5ee51e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/game/Assets/Prefabs/Player.prefab b/game/Assets/Prefabs/Player.prefab new file mode 100644 index 0000000..390c17d --- /dev/null +++ b/game/Assets/Prefabs/Player.prefab @@ -0,0 +1,487 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1865034783 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1865034784} + - component: {fileID: 1865034787} + - component: {fileID: 1865034786} + - component: {fileID: 1865034785} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1865034784 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1865034783} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0.5, z: 0.6} + m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} + m_Children: [] + m_Father: {fileID: 7846295001490405682} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &1865034787 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1865034783} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1865034786 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1865034783} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 1b0f58118cf7a5a4e85fda00fe3de44b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &1865034785 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1865034783} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!1 &7846295001045979005 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7846295001045979004} + - component: {fileID: 7846295001045979006} + - component: {fileID: 7846295001045978993} + - component: {fileID: 7846295001045978992} + - component: {fileID: 7846295000056357947} + m_Layer: 0 + m_Name: Player + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7846295001045979004 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001045979005} + 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: + - {fileID: 7846295001490405682} + - {fileID: 7846295001499866554} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &7846295001045979006 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001045979005} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a734b8e2d64ba604795fd5cef5d741f4, type: 3} + m_Name: + m_EditorClassIdentifier: + _movementSettings: {fileID: 11400000, guid: 0c168708f93291545b51df2eec8f4ac3, type: 2} + _inputHandler: {fileID: 7846295001045978992} + _controller: {fileID: 7846295000056357947} + _graphics: {fileID: 7846295001490405682} +--- !u!114 &7846295001045978993 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001045979005} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 62899f850307741f2a39c98a8b639597, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Actions: {fileID: -944628639613478452, guid: d4d9eb5db7beac84ca3cb36cfc09cd0a, type: 3} + m_NotificationBehavior: 2 + m_UIInputModule: {fileID: 0} + m_DeviceLostEvent: + m_PersistentCalls: + m_Calls: [] + m_DeviceRegainedEvent: + m_PersistentCalls: + m_Calls: [] + m_ControlsChangedEvent: + m_PersistentCalls: + m_Calls: [] + m_ActionEvents: + - m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 7846295001045978992} + m_TargetAssemblyTypeName: PlayerInputHandler, Assembly-CSharp + m_MethodName: Move + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_ActionId: 5c440996-60ec-4084-9223-75d39638108a + m_ActionName: CoreMap/Move[/Keyboard/w,/Keyboard/s,/Keyboard/a,/Keyboard/d,/XInputControllerWindows/leftStick] + - m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 7846295001045978992} + m_TargetAssemblyTypeName: PlayerInputHandler, Assembly-CSharp + m_MethodName: Look + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_ActionId: d271942b-8516-4550-88ae-552350feb4b1 + m_ActionName: CoreMap/Look[/Mouse/delta,/XInputControllerWindows/rightStick] + - m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 7846295001045978992} + m_TargetAssemblyTypeName: PlayerInputHandler, Assembly-CSharp + m_MethodName: Jump + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_ActionId: da936947-fcfa-4872-a4e3-15763afe56b6 + m_ActionName: CoreMap/Jump[/Keyboard/space,/XInputControllerWindows/buttonSouth] + - m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 7846295001045978992} + m_TargetAssemblyTypeName: PlayerInputHandler, Assembly-CSharp + m_MethodName: Use + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_ActionId: 2bbc2e93-6016-4544-8399-0c4ee222850c + m_ActionName: CoreMap/Use[/Keyboard/e,/XInputControllerWindows/buttonWest] + m_NeverAutoSwitchControlSchemes: 1 + m_DefaultControlScheme: Gamepad + m_DefaultActionMap: CoreMap + m_SplitScreenIndex: -1 + m_Camera: {fileID: 7846295001499866555} +--- !u!114 &7846295001045978992 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001045979005} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e12816fc78a8ca3429be019aa4e51fdd, type: 3} + m_Name: + m_EditorClassIdentifier: + _inputSettings: {fileID: 11400000, guid: 09b165d6ce14f86459be7213da9688a7, type: 2} +--- !u!143 &7846295000056357947 +CharacterController: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001045979005} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Height: 2 + m_Radius: 0.5 + m_SlopeLimit: 45 + m_StepOffset: 0.3 + m_SkinWidth: 0.01 + m_MinMoveDistance: 0.001 + m_Center: {x: 0, y: 1, z: 0} +--- !u!1 &7846295001490405694 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7846295001490405682} + - component: {fileID: 7846295001490405683} + - component: {fileID: 7846295001490405680} + m_Layer: 0 + m_Name: Graphics + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7846295001490405682 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001490405694} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1865034784} + m_Father: {fileID: 7846295001045979004} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &7846295001490405683 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001490405694} + m_Mesh: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &7846295001490405680 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001490405694} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 1b0f58118cf7a5a4e85fda00fe3de44b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &7846295001499866553 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7846295001499866554} + - component: {fileID: 7846295001499866555} + - component: {fileID: 7846295001499866552} + - component: {fileID: 7846295001499866557} + - component: {fileID: 7846295001499866556} + m_Layer: 0 + m_Name: PlayerCamera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7846295001499866554 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001499866553} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 7846295001045979004} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!20 &7846295001499866555 +Camera: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001499866553} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_projectionMatrixMode: 1 + m_GateFitMode: 2 + m_FOVAxisMode: 0 + m_SensorSize: {x: 36, y: 24} + m_LensShift: {x: 0, y: 0} + m_FocalLength: 50 + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 65 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_AllowDynamicResolution: 0 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 +--- !u!81 &7846295001499866552 +AudioListener: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001499866553} + m_Enabled: 1 +--- !u!114 &7846295001499866557 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001499866553} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} + m_Name: + m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: 0 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_RenderPostProcessing: 1 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 +--- !u!114 &7846295001499866556 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7846295001499866553} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 805caadbe4df94a40bf7ddb70bea02f6, type: 3} + m_Name: + m_EditorClassIdentifier: + _settings: {fileID: 11400000, guid: 995f378ab762cd344b7a6d108f049191, type: 2} + _inputHandler: {fileID: 7846295001045978992} diff --git a/game/Assets/Prefabs/Player.prefab.meta b/game/Assets/Prefabs/Player.prefab.meta new file mode 100644 index 0000000..edbe640 --- /dev/null +++ b/game/Assets/Prefabs/Player.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ed6e7ba262c00374d9ed95757ea54c05 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/game/Assets/Scripts/Flow/Bootstrap.cs b/game/Assets/Scripts/Flow/Bootstrap.cs index 9db92f5..8097ac8 100644 --- a/game/Assets/Scripts/Flow/Bootstrap.cs +++ b/game/Assets/Scripts/Flow/Bootstrap.cs @@ -1,321 +1,318 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using System.Runtime.InteropServices; -using System.Text; -using NaughtyAttributes; -using UnityEditor.Experimental.Rendering; -using UnityEngine; -using UnityEngine.SceneManagement; -using UnityEngine.UI; -using TMPro; - -enum LoadState -{ - Idle, - FadeOut, - UnityUnload, - Cleanup, - UnityLoad, - SceneSetup, - Sync, - FadeIn, - - COUNT -} - -public class Bootstrap : MonoBehaviour -{ - [Header( "Debug" )] - [SerializeField] - private bool _debugMode; - - [Header( "Config" )] - [SerializeField] [Expandable] - private BootstrapConfig _config; - - private static Bootstrap _instance; - - private LoadState _loadState; - private Coroutine _currentSceneLoad; - private SceneType _activeSceneType; - - private SceneLoader _activeScene; - private string _activeSceneName; - - [Header( "References" )] - [SerializeField] - private Image _fader; - - [SerializeField] - private TMP_Text _debugDisplay; - - //private LevelDescriptor _activeLevelDescriptor; - - private List _loadedLevels = new List(); - - private Queue _toLoadLevels = new Queue(); - private AsyncOperation _levelLoadAsync = null; - - private Queue _toUnloadLevels = new Queue(); - private AsyncOperation _levelUnloadAsync = null; - - public bool IsLoading => _loadState != LoadState.Idle; - - private void QueryLoadState() - { - if ( _activeScene != null && _activeScene.ToLoad != SceneType.None ) - { - LoadScene( _activeScene.ToLoad ); - } - } - - private void Awake() - { - _instance = this; - - if ( _debugMode ) - { - StartCoroutine( DebugCR() ); - } - } - - void Start() - { - LoadScene( SceneType.BootSequence ); - } - - public static void LoadScene( SceneType scene ) - { - if ( _instance.IsLoading ) - { - Debug.LogError( "[Bootstrap]: couldn't load scene: another load operation already active." ); - return; - } - - _instance._currentSceneLoad = _instance.StartCoroutine( _instance.LoadSceneCR( scene ) ); - } - - public static void LoadLevel( LevelDescriptor descriptor ) - { - _instance._toLoadLevels.Enqueue( descriptor ); - } - - private IEnumerator DebugCR() - { - LoadState loadState = LoadState.COUNT; - StringBuilder sb = new StringBuilder(); - - while ( true ) - { - if ( _loadState != loadState ) - { - loadState = _loadState; - sb.Clear(); - - sb.Append( "LoadState::" ); - sb.AppendLine( _loadState.ToString() ); - - if ( _activeSceneName != null ) - { - sb.AppendFormat( "S: {0} ({1})", _activeSceneType, _activeSceneName ); - } - else - { - sb.AppendFormat( "S: [none]" ); - } - - sb.Append( "\n" ); - - if ( (_loadedLevels?.Count ?? 0) > 0 ) - { - sb.Append( "L: " ); - for ( int i = 0; i < _loadedLevels.Count; ++i ) - { - sb.Append( _loadedLevels[ i ].LevelScene ); - if ( i != _loadedLevels.Count - 1 ) - { - sb.Append( ", " ); - } - } - } - else - { - sb.AppendFormat( "L: [none]" ); - } - - sb.Append( "\n" ); - sb.AppendFormat( "Load: {0} ({1} queued)\n", _levelLoadAsync?.isDone ?? true ? "idle" : "busy" , _toLoadLevels.Count ); - sb.AppendFormat( "Unload: {0} ({1} queued)\n", _levelUnloadAsync?.isDone ?? true ? "idle" : "busy" , _toUnloadLevels.Count ); - - _debugDisplay.SetText( sb.ToString() ); - } - - yield return null; - } - } - - private bool ProcessLevelUnloads() - { - if (_levelUnloadAsync?.isDone ?? true) - { - while (true) - { - if ( _toUnloadLevels.Count == 0 ) - { - break; - } - - var target = _toUnloadLevels.Dequeue(); - if ( _loadedLevels.Contains( target ) == false ) - { - continue; - } - - _levelUnloadAsync = SceneManager.UnloadSceneAsync( target.LevelScene ); - _loadedLevels.Remove( target ); - return false; - } - } - - return (_levelUnloadAsync?.isDone ?? true) && _toUnloadLevels.Count == 0; - } - - private bool ProcessLevelLoads() - { - if (_levelLoadAsync?.isDone ?? true) - { - while (true) - { - if ( _toLoadLevels.Count == 0 ) - { - break; - } - - var target = _toLoadLevels.Dequeue(); - if ( _loadedLevels.Contains( target ) ) - { - continue; - } - - _levelLoadAsync = SceneManager.LoadSceneAsync( target.LevelScene, LoadSceneMode.Additive ); - _loadedLevels.Add( target ); - return false; - } - } - - return (_levelLoadAsync?.isDone ?? true) && _toLoadLevels.Count == 0; - } - - private IEnumerator LoadSceneCR( SceneType scene ) - { - AsyncOperation asyncOp; - - // fade out - _loadState = LoadState.FadeOut; - _fader.CrossFadeAlpha( 1f, _config.TransitionDuration, true ); - yield return new WaitForSecondsRealtime( _config.TransitionDuration ); - - // unload unity's scenes - _loadState = LoadState.UnityUnload; - - if ( _activeSceneName != null ) - { - // unload main scene - asyncOp = SceneManager.UnloadSceneAsync( _activeSceneName ); - - while ( asyncOp.isDone == false ) - yield return null; - - _activeScene = null; - _activeSceneName = null; - } - - // cleanup - _loadState = LoadState.Cleanup; - - if ( scene == SceneType.Gameplay ) - { - _toUnloadLevels.Clear(); - _toLoadLevels.Clear(); - _loadedLevels.Clear(); - _toLoadLevels.Enqueue( _config.StartLevel ); - } - else - { - _toLoadLevels.Clear(); - - for ( int i = 0; i < _loadedLevels.Count; ++i ) - { - if ( _toUnloadLevels.Contains( _loadedLevels[ i ] ) == false ) - { - _toUnloadLevels.Enqueue( _loadedLevels[ i ] ); - } - } - } - - // 6 collections, as that is the deepest unity hierarchies go. - for ( int i = 0; i < 6; ++i ) - { - GC.Collect(); - yield return null; - } - - // unity loading - _loadState = LoadState.UnityLoad; - _activeSceneType = scene; - _activeSceneName = _config.GetScene( scene ); - - asyncOp = SceneManager.LoadSceneAsync( _activeSceneName, LoadSceneMode.Additive ); - - while ( asyncOp.isDone == false ) - yield return null; - - // setup - _loadState = LoadState.SceneSetup; - - _activeScene = FindObjectOfType(); - - while ( _activeScene.LoadComplete == false ) - yield return null; - - // sync - _loadState = LoadState.Sync; - while ( ProcessLevelUnloads() == false ) - { - yield return null; - } - - while ( ProcessLevelLoads() == false ) - { - yield return null; - } - - // fade in - _loadState = LoadState.FadeIn; - _fader.CrossFadeAlpha( 0f, _config.TransitionDuration, true ); - yield return new WaitForSecondsRealtime( _config.TransitionDuration ); - - yield return null; - _loadState = LoadState.Idle; - _currentSceneLoad = null; - } - - - private void Update() - { - if ( !IsLoading ) - { - QueryLoadState(); - - if ( _activeSceneType == SceneType.Gameplay ) - { - if ( ProcessLevelUnloads() ) - { - ProcessLevelLoads(); - } - } - } - } +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using NaughtyAttributes; +using UnityEngine; +using UnityEngine.SceneManagement; +using UnityEngine.UI; +using TMPro; + +enum LoadState +{ + Idle, + FadeOut, + UnityUnload, + Cleanup, + UnityLoad, + SceneSetup, + Sync, + FadeIn, + + COUNT +} + +public class Bootstrap : MonoBehaviour +{ + [Header( "Debug" )] + [SerializeField] + private bool _debugMode; + + [Header( "Config" )] + [SerializeField] [Expandable] + private BootstrapConfig _config; + + private static Bootstrap _instance; + + private LoadState _loadState; + private Coroutine _currentSceneLoad; + private SceneType _activeSceneType; + + private SceneLoader _activeScene; + private string _activeSceneName; + + [Header( "References" )] + [SerializeField] + private Image _fader; + + [SerializeField] + private TMP_Text _debugDisplay; + + //private LevelDescriptor _activeLevelDescriptor; + + private List _loadedLevels = new List(); + + private Queue _toLoadLevels = new Queue(); + private AsyncOperation _levelLoadAsync = null; + + private Queue _toUnloadLevels = new Queue(); + private AsyncOperation _levelUnloadAsync = null; + + public bool IsLoading => _loadState != LoadState.Idle; + + private void QueryLoadState() + { + if ( _activeScene != null && _activeScene.ToLoad != SceneType.None ) + { + LoadScene( _activeScene.ToLoad ); + } + } + + private void Awake() + { + _instance = this; + + if ( _debugMode ) + { + StartCoroutine( DebugCR() ); + } + } + + void Start() + { + LoadScene( SceneType.BootSequence ); + } + + public static void LoadScene( SceneType scene ) + { + if ( _instance.IsLoading ) + { + Debug.LogError( "[Bootstrap]: couldn't load scene: another load operation already active." ); + return; + } + + _instance._currentSceneLoad = _instance.StartCoroutine( _instance.LoadSceneCR( scene ) ); + } + + public static void LoadLevel( LevelDescriptor descriptor ) + { + _instance._toLoadLevels.Enqueue( descriptor ); + } + + private IEnumerator DebugCR() + { + LoadState loadState = LoadState.COUNT; + StringBuilder sb = new StringBuilder(); + + while ( true ) + { + if ( _loadState != loadState ) + { + loadState = _loadState; + sb.Clear(); + + sb.Append( "LoadState::" ); + sb.AppendLine( _loadState.ToString() ); + + if ( _activeSceneName != null ) + { + sb.AppendFormat( "S: {0} ({1})", _activeSceneType, _activeSceneName ); + } + else + { + sb.AppendFormat( "S: [none]" ); + } + + sb.Append( "\n" ); + + if ( (_loadedLevels?.Count ?? 0) > 0 ) + { + sb.Append( "L: " ); + for ( int i = 0; i < _loadedLevels.Count; ++i ) + { + sb.Append( _loadedLevels[ i ].LevelScene ); + if ( i != _loadedLevels.Count - 1 ) + { + sb.Append( ", " ); + } + } + } + else + { + sb.AppendFormat( "L: [none]" ); + } + + sb.Append( "\n" ); + sb.AppendFormat( "Load: {0} ({1} queued)\n", _levelLoadAsync?.isDone ?? true ? "idle" : "busy" , _toLoadLevels.Count ); + sb.AppendFormat( "Unload: {0} ({1} queued)\n", _levelUnloadAsync?.isDone ?? true ? "idle" : "busy" , _toUnloadLevels.Count ); + + _debugDisplay.SetText( sb.ToString() ); + } + + yield return null; + } + } + + private bool ProcessLevelUnloads() + { + if (_levelUnloadAsync?.isDone ?? true) + { + while (true) + { + if ( _toUnloadLevels.Count == 0 ) + { + break; + } + + var target = _toUnloadLevels.Dequeue(); + if ( _loadedLevels.Contains( target ) == false ) + { + continue; + } + + _levelUnloadAsync = SceneManager.UnloadSceneAsync( target.LevelScene ); + _loadedLevels.Remove( target ); + return false; + } + } + + return (_levelUnloadAsync?.isDone ?? true) && _toUnloadLevels.Count == 0; + } + + private bool ProcessLevelLoads() + { + if (_levelLoadAsync?.isDone ?? true) + { + while (true) + { + if ( _toLoadLevels.Count == 0 ) + { + break; + } + + var target = _toLoadLevels.Dequeue(); + if ( _loadedLevels.Contains( target ) ) + { + continue; + } + + _levelLoadAsync = SceneManager.LoadSceneAsync( target.LevelScene, LoadSceneMode.Additive ); + _loadedLevels.Add( target ); + return false; + } + } + + return (_levelLoadAsync?.isDone ?? true) && _toLoadLevels.Count == 0; + } + + private IEnumerator LoadSceneCR( SceneType scene ) + { + AsyncOperation asyncOp; + + // fade out + _loadState = LoadState.FadeOut; + _fader.CrossFadeAlpha( 1f, _config.TransitionDuration, true ); + yield return new WaitForSecondsRealtime( _config.TransitionDuration ); + + // unload unity's scenes + _loadState = LoadState.UnityUnload; + + if ( _activeSceneName != null ) + { + // unload main scene + asyncOp = SceneManager.UnloadSceneAsync( _activeSceneName ); + + while ( asyncOp.isDone == false ) + yield return null; + + _activeScene = null; + _activeSceneName = null; + } + + // cleanup + _loadState = LoadState.Cleanup; + + if ( scene == SceneType.Gameplay ) + { + _toUnloadLevels.Clear(); + _toLoadLevels.Clear(); + _loadedLevels.Clear(); + _toLoadLevels.Enqueue( _config.StartLevel ); + } + else + { + _toLoadLevels.Clear(); + + for ( int i = 0; i < _loadedLevels.Count; ++i ) + { + if ( _toUnloadLevels.Contains( _loadedLevels[ i ] ) == false ) + { + _toUnloadLevels.Enqueue( _loadedLevels[ i ] ); + } + } + } + + // 6 collections, as that is the deepest unity hierarchies go. + for ( int i = 0; i < 6; ++i ) + { + GC.Collect(); + yield return null; + } + + // unity loading + _loadState = LoadState.UnityLoad; + _activeSceneType = scene; + _activeSceneName = _config.GetScene( scene ); + + asyncOp = SceneManager.LoadSceneAsync( _activeSceneName, LoadSceneMode.Additive ); + + while ( asyncOp.isDone == false ) + yield return null; + + // setup + _loadState = LoadState.SceneSetup; + + _activeScene = FindObjectOfType(); + + while ( _activeScene.LoadComplete == false ) + yield return null; + + // sync + _loadState = LoadState.Sync; + while ( ProcessLevelUnloads() == false ) + { + yield return null; + } + + while ( ProcessLevelLoads() == false ) + { + yield return null; + } + + // fade in + _loadState = LoadState.FadeIn; + _fader.CrossFadeAlpha( 0f, _config.TransitionDuration, true ); + yield return new WaitForSecondsRealtime( _config.TransitionDuration ); + + yield return null; + _loadState = LoadState.Idle; + _currentSceneLoad = null; + } + + + private void Update() + { + if ( !IsLoading ) + { + QueryLoadState(); + + if ( _activeSceneType == SceneType.Gameplay ) + { + if ( ProcessLevelUnloads() ) + { + ProcessLevelLoads(); + } + } + } + } } \ No newline at end of file