using UnityEngine; using GatherAndDefend.LevelEditor; using System.Collections; using UnityEngine.Tilemaps; using System.Threading.Tasks; using System; /// The position the tile should be placed on /// the tile we should place /// the action of placing the tile on the tilemap /// public delegate Task PlacementAnimationHandler(Vector3 position, TileBase tile, Action tilePlacement); public class LevelManagerScript : SingletonBehaviour { private Action updateAction = null; public bool loadOnStart = false; public Level firstLevel; async void Start() { //only when the level is loaded do we start updating LevelManager.Instance.LevelLoaded += Instance_LevelLoaded; if (loadOnStart && firstLevel) { await LevelManager.Instance.LoadLevel(firstLevel, placementAnimation: PlacementAnimation); } } void OnDestroy() { updateAction = null; } void Update() { updateAction?.Invoke(); } private void Instance_LevelLoaded(Level level) { //only when the level is loaded do we start updating updateAction = LevelManager.Instance.UpdateLevel; } /// /// the tile falls from the top of the screen, up to it's position on the tilemap /// /// where it should land /// what the tile represents /// the action of actually placing the tile /// 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(); rend.sortingOrder = 10; rend.sortingLayerName = layer; if (tile is LevelTile) { rend.sprite = (tile as LevelTile).Sprite; } else { 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; var direction = delta.normalized; var signY = delta.y / Mathf.Abs(delta.y); 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 += speed * Time.deltaTime * direction; var newDelta = tilePlaceholder.transform.position - position; var newSign = newDelta.y / Mathf.Abs(newDelta.y); if (newSign != signY) break; await Task.Yield(); } //place the tile and destroy the placeholder putTileOnTilemap.Invoke(); Destroy(tilePlaceholder); } }