added some doc + some global configs

This commit is contained in:
Felix Boucher 2023-09-17 20:30:02 -04:00
parent 9e07c48fd4
commit ef6b345a03
14 changed files with 306 additions and 1032 deletions

View File

@ -12,7 +12,6 @@ GameObject:
- component: {fileID: 3028288566889208750}
- component: {fileID: 3028288566889208749}
- component: {fileID: -245230096461627285}
- component: {fileID: 5626804684391367242}
m_Layer: 0
m_Name: LevelManager
m_TagString: Untagged
@ -47,6 +46,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c8f415d45fd9659408ac8c5ce2e96aba, type: 3}
m_Name:
m_EditorClassIdentifier:
loadOnStart: 0
firstLevel: {fileID: 11400000, guid: a6e34739c9325da4cac4fbaea30d052c, type: 2}
--- !u!114 &3028288566889208749
MonoBehaviour:
@ -120,16 +120,3 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 37c0aa967043d974783120d6ea9b136c, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &5626804684391367242
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3028288566889208744}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c8f878516c4a3324aa1a9672f8b336c9, type: 3}
m_Name:
m_EditorClassIdentifier:
_current: {fileID: 11400000, guid: 132e291fc51a8f445b1183b11a5d6b39, type: 2}

File diff suppressed because it is too large Load Diff

View File

@ -2582,6 +2582,64 @@ GameObject:
m_CorrespondingSourceObject: {fileID: 1893888152770301340, guid: eb25bde5e3c72d34fbc9095e2c83cdb4, type: 3}
m_PrefabInstance: {fileID: 1878632746}
m_PrefabAsset: {fileID: 0}
--- !u!1 &2015431890
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2015431891}
- component: {fileID: 2015431892}
- component: {fileID: 2015431893}
m_Layer: 0
m_Name: GlobalConfig
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2015431891
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2015431890}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -2.6812747, y: -2.3953135, z: 0.25616607}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2015431892
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2015431890}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: c8f878516c4a3324aa1a9672f8b336c9, type: 3}
m_Name:
m_EditorClassIdentifier:
_current: {fileID: 11400000, guid: 132e291fc51a8f445b1183b11a5d6b39, type: 2}
--- !u!114 &2015431893
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2015431890}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fa9f587ee4cf938499416afd7af15106, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &1893888154391728751
PrefabInstance:
m_ObjectHideFlags: 0

View File

@ -0,0 +1,9 @@
using UnityEngine;
public class DontDestroy : MonoBehaviour
{
void Awake()
{
DontDestroyOnLoad(gameObject);
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 389cc3c423055324fb8d7de50f62f709
guid: fa9f587ee4cf938499416afd7af15106
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -9,9 +9,9 @@ using System.Threading.Tasks;
public static class Extensions
{
public static async Task WaitWhile(Func<bool> untilTrue)
public static async Task WaitWhile(Func<bool> toKeepTrue)
{
while (untilTrue?.Invoke() == false)
while (toKeepTrue?.Invoke() == true)
{
await Task.Yield();
}

View File

@ -2,6 +2,7 @@ using UnityEngine;
public class GlobalConfig : SingletonBehaviour<GlobalConfig>
{
[SerializeField]
private GlobalConfigFile _current;
public GlobalConfigFile Current

View File

@ -30,4 +30,9 @@ public class GlobalConfigFile : ScriptableObject
public bool useRandomHarvestDuration = false;
public int randomHarvestDurationMinimum = 0;
public int randomHarvestDurationMaximum = 0;
[Header("loading screen")]
public float loadingAddedTime = 3;
public float baseTileSpawnSpeed = 12;
public float tileSpawnAcceleration = 1;
}

View File

@ -15,6 +15,6 @@ public class SingletonBehaviour<T> : MonoBehaviour where T : SingletonBehaviour<
protected virtual void Awake()
{
if (!Instance) Instance = this as T;
else Destroy(gameObject);
else Destroy(this);
}
}

View File

@ -34,10 +34,21 @@ namespace GatherAndDefend.LevelEditor
public string Key => _key;
public async Task LoadToTilemap(Tilemap reference, PlacementAnimationHandler placementAnimation = null, Reference<bool> allTilesSpawned = default, Func<float> tileSpawnAcceleration = default)
/// <summary>
///
/// </summary>
/// <param name="reference">the current tilemap</param>
/// <param name="placementAnimation">the tiles falling on the tilemap</param>
/// <param name="allTilesSpawned">a reference value that is used in caller method to detect when all tiles have been spawned</param>
/// <param name="tileSpawnAcceleration">a delegate which speeds up the spawning of the tiles over time</param>
/// <returns></returns>
public async Task LoadToTilemap(Tilemap reference, PlacementAnimationHandler placementAnimation = null, Action allTilesSpawned = default, Func<float> tileSpawnAcceleration = default)
{
// if the function we receive is null, we just make it constant 1
if (tileSpawnAcceleration == default) tileSpawnAcceleration = () => 1;
const int tilesPerSecond = 15;
reference.transform.localPosition = _position;
reference.transform.localScale = _scale;
@ -51,13 +62,14 @@ namespace GatherAndDefend.LevelEditor
collision.isTrigger = _isTrigger;
}
//all tiles are loaded after their animation is over. use a task to asyncroneously load them and keep control over the flow
var tasks = new List<Task>();
foreach (TileData data in _tiles)
{
tasks.Add(placementAnimation(data.Position, data.Tile, () => reference.SetTile(data.Position, data.Tile)));
await Task.Delay((int)(1000f / (tilesPerSecond * tileSpawnAcceleration())));
}
if (allTilesSpawned != null) allTilesSpawned.Value = true;
allTilesSpawned?.Invoke();
await Task.WhenAll(tasks);
}
/// <summary>

View File

@ -143,14 +143,16 @@ public class LevelManager : Singleton<LevelManager>
}
/// <summary>
/// permet de loader un scriptable object de niveau
/// loads a Level scriptable object
/// </summary>
/// <param name="level">le niveau à loader</param>
/// <param name="shouldClear">est ce qu'on veut effacer ce qui est déjà là?</param>
/// <param name="level">the level to load</param>
/// <param name="shouldClear">do we want to clear what's already there before loading?</param>
/// <param name="placementAnimation">the tiles falling from the top of the screen</param>
public async Task LoadLevel(Level level, bool shouldClear = false, PlacementAnimationHandler placementAnimation = null)
{
float tileSpawnAcceleration = 1;
float tileSpawnAccelerationFunc() => (tileSpawnAcceleration += Time.deltaTime);
float accelerationOfAcceleration = GlobalConfig.Instance.Current.tileSpawnAcceleration;
float tileCurrentAcceleration = 1;
float tileSpawnAccelerationFunc() => (tileCurrentAcceleration += accelerationOfAcceleration * Time.deltaTime);
if (shouldClear)
{
@ -181,14 +183,15 @@ public class LevelManager : Singleton<LevelManager>
//generate all tilemaps
foreach (TilemapData tilemapData in _currentLevel)
{
bool allTilesSpawned = false;
System.Action OnAllTilesSpawned = () => allTilesSpawned = true;
var tilemap = new GameObject(tilemapData.Key).AddComponent<Tilemap>();
tilemap.tileAnchor = Vector3.zero;
tilemap.gameObject.AddComponent<TilemapRenderer>();
tilemap.transform.SetParent(grid.transform);
Reference<bool> allTileSpawned = false;
tasks.Add(tilemapData.LoadToTilemap(tilemap, placementAnimation, allTileSpawned, tileSpawnAccelerationFunc));
await Extensions.WaitWhile(() => allTileSpawned);
tasks.Add(tilemapData.LoadToTilemap(tilemap, placementAnimation, OnAllTilesSpawned, tileSpawnAccelerationFunc));
await Extensions.WaitWhile(() => !allTilesSpawned);
}
await Task.WhenAll(tasks);
@ -197,10 +200,11 @@ public class LevelManager : Singleton<LevelManager>
}
/// <summary>
/// permet de loader un scriptable object de niveau
/// load a Level scriptable object using its name
/// </summary>
/// <param name="levelName">le nom du niveau à loader</param>
/// <param name="shouldClear">est ce qu'on veut effacer ce qui est déjà là?</param>
/// <param name="levelName">the name of the loaded Level</param>
/// <param name="shouldClear">should we clear what's already there?</param>
/// <param name="placementAnimation">the tiles falling animation</param>
public async Task LoadLevel(string levelName, bool shouldClear = false, PlacementAnimationHandler placementAnimation = null)
{
if (shouldClear)

View File

@ -5,6 +5,10 @@ using UnityEngine.Tilemaps;
using System.Threading.Tasks;
using System;
/// <param name="position">The position the tile should be placed on</param>
/// <param name="tile">the tile we should place</param>
/// <param name="tilePlacement">the action of placing the tile on the tilemap</param>
/// <returns></returns>
public delegate Task PlacementAnimationHandler(Vector3 position, TileBase tile, Action tilePlacement);
public class LevelManagerScript : SingletonBehaviour<LevelManagerScript>
{
@ -13,6 +17,7 @@ public class LevelManagerScript : SingletonBehaviour<LevelManagerScript>
public Level firstLevel;
async void Start()
{
//only when the level is loaded do we start updating
LevelManager.Instance.LevelLoaded += Instance_LevelLoaded;
if (loadOnStart && firstLevel)
{
@ -32,17 +37,28 @@ public class LevelManagerScript : SingletonBehaviour<LevelManagerScript>
private void Instance_LevelLoaded(Level level)
{
//only when the level is loaded do we start updating
updateAction = LevelManager.Instance.UpdateLevel;
}
/// <summary>
/// the tile falls from the top of the screen, up to it's position on the tilemap
/// </summary>
/// <param name="position">where it should land</param>
/// <param name="tile">what the tile represents</param>
/// <param name="putTileOnTilemap">the action of actually placing the tile</param>
/// <returns></returns>
public static async Task PlacementAnimation(Vector3 position, TileBase tile, System.Action putTileOnTilemap)
{
const string layer = "Unit";
float speed = 0;
float acceleration = -9.81f;
//create the falling GameObject that will placehold for the tile
var tilePlaceholder = new GameObject("tile");
var rend = tilePlaceholder.AddComponent<SpriteRenderer>();
rend.sortingOrder = 10;
rend.sortingLayerName = "Unit";
rend.sortingLayerName = layer;
if (tile is LevelTile)
{
@ -53,6 +69,7 @@ public class LevelManagerScript : SingletonBehaviour<LevelManagerScript>
rend.sprite = (tile as Tile).sprite;
}
//position the tile over the board (past the camera's FOV)
tilePlaceholder.transform.position = position + Vector3.up * Camera.main.orthographicSize * 2;
var delta = tilePlaceholder.transform.position - position;
@ -61,10 +78,12 @@ public class LevelManagerScript : SingletonBehaviour<LevelManagerScript>
while (true)
{
//if the placeholder was destroyed, stop
if (!tilePlaceholder) break;
//make the placeholder fall and check if we went past the target position
speed += acceleration * Time.deltaTime;
tilePlaceholder.transform.position += direction * Time.deltaTime * speed;
tilePlaceholder.transform.position += speed * Time.deltaTime * direction;
var newDelta = tilePlaceholder.transform.position - position;
var newSign = newDelta.y / Mathf.Abs(newDelta.y);
@ -73,6 +92,7 @@ public class LevelManagerScript : SingletonBehaviour<LevelManagerScript>
await Task.Yield();
}
//place the tile and destroy the placeholder
putTileOnTilemap.Invoke();
Destroy(tilePlaceholder);
}

View File

@ -14,22 +14,25 @@ public class LoadingManager : MonoBehaviour
private LoadingScreen loadingScreen;
public float testAddedTime = 5;
void Start()
{
loadingScreen = GetComponent<LoadingScreen>();
loadingScreen.ScreenActivated += StartLoadingGameScene;
loadingScreen.ScreenActivated += LoadTargetSceneAndCloseOthers;
loadingScreen.ShowLoadingScreen();
}
private void StartLoadingGameScene()
/// <summary>
/// loads the target scene after given time
/// </summary>
private void LoadTargetSceneAndCloseOthers()
{
StartCoroutine(LoadSceneAfterTime());
IEnumerator LoadSceneAfterTime()
{
yield return new WaitForSeconds(testAddedTime);
yield return new WaitForSeconds(GlobalConfig.Instance.Current.loadingAddedTime);
loadingScreen.ScreenActivated -= StartLoadingGameScene;
loadingScreen.ScreenActivated -= LoadTargetSceneAndCloseOthers;
SceneManager.sceneLoaded += StartHidingLoadingScreen;
var sceneToLoad = PlayerPrefs.GetString(SceneToLoad);
@ -45,12 +48,22 @@ public class LoadingManager : MonoBehaviour
SceneManager.LoadScene(sceneToLoad, LoadSceneMode.Additive);
}
}
/// <summary>
/// hide loading screen after target scene has finished loading
/// </summary>
/// <param name="arg0">unused</param>
/// <param name="arg1">unused</param>
private void StartHidingLoadingScreen(Scene arg0, LoadSceneMode arg1)
{
SceneManager.sceneLoaded -= StartHidingLoadingScreen;
loadingScreen.ScreenDeactivated += StartLoadingLevel;
loadingScreen.HideLoadingScreen();
}
/// <summary>
/// when loading screen is hidden, we load the level if we have a level to load (might not, if we have loaded another scene than the Game scene)
/// </summary>
private async void StartLoadingLevel()
{
loadingScreen.ScreenDeactivated -= StartLoadingLevel;
@ -68,6 +81,11 @@ public class LoadingManager : MonoBehaviour
}
}
/// <summary>
/// close the loading screen scene and start playing! w00t w00t
/// </summary>
/// <param name="level"></param>
private void UnloadLoadingScreenScene(GatherAndDefend.LevelEditor.Level level)
{
LevelManager.Instance.LevelLoaded -= UnloadLoadingScreenScene;

View File

@ -1,55 +0,0 @@
using UnityEditor;
using UnityEngine;
public class SceneAttribute : PropertyAttribute { }
[CustomPropertyDrawer(typeof(SceneAttribute))]
public class SceneDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
if (property.propertyType == SerializedPropertyType.String)
{
var sceneObject = GetSceneObject(property.stringValue);
var scene = EditorGUI.ObjectField(position, label, sceneObject, typeof(SceneAsset), true);
if (scene == null)
{
property.stringValue = "";
}
else if (scene.name != property.stringValue)
{
var sceneObj = GetSceneObject(scene.name);
if (sceneObj == null)
{
Debug.LogWarning("The scene " + scene.name + " cannot be used. To use this scene add it to the build settings for the project");
}
else
{
property.stringValue = scene.name;
}
}
}
else
EditorGUI.LabelField(position, label.text, "Use [Scene] with strings.");
}
protected SceneAsset GetSceneObject(string sceneObjectName)
{
if (string.IsNullOrEmpty(sceneObjectName))
{
return null;
}
foreach (var editorScene in EditorBuildSettings.scenes)
{
if (editorScene.path.IndexOf(sceneObjectName) != -1)
{
return AssetDatabase.LoadAssetAtPath(editorScene.path, typeof(SceneAsset)) as SceneAsset;
}
}
Debug.LogWarning("Scene [" + sceneObjectName + "] cannot be used. Add this scene to the 'Scenes in the Build' in build settings.");
return null;
}
}