|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.AI;
|
|
|
|
using UnityEngine.Rendering;
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
using Random = UnityEngine.Random;
|
|
|
|
|
|
|
|
namespace ET
|
|
|
|
{
|
|
|
|
[Timer(TimerType.UpdateBuildingDataTimer)]
|
|
|
|
public class UpdateBuildingDataTimer : ATimer<MapComponent>
|
|
|
|
{
|
|
|
|
public override void Run(MapComponent self)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (self.IsDisposed || self.Parent == null) return;
|
|
|
|
if (self.DomainScene() == null) return;
|
|
|
|
self.UpdateBuildingData().Coroutine();
|
|
|
|
}
|
|
|
|
catch(Exception ex)
|
|
|
|
{
|
|
|
|
Log.Error(ex.ToString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class MapComponentAwakeSystem : AwakeSystem<MapComponent>
|
|
|
|
{
|
|
|
|
public override void Awake(MapComponent self)
|
|
|
|
{
|
|
|
|
self.Awake();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 以最底部为Map的数组的0,0点
|
|
|
|
[FriendClass(typeof(MapComponent))]
|
|
|
|
public static class MapComponentSystem
|
|
|
|
{
|
|
|
|
public static void Awake(this MapComponent self)
|
|
|
|
{
|
|
|
|
var gameSceneMgr = self.ZoneScene().CurrentScene().GetComponent<GameSceneManagerComponent>();
|
|
|
|
Transform mainSceneRoot = gameSceneMgr.GetRoot(GameSceneType.Main).transform;
|
|
|
|
var sceneTrans = mainSceneRoot.Find("Scene");
|
|
|
|
self.NavMesh2d = sceneTrans.GetComponent<NavMeshSurface2d>();
|
|
|
|
|
|
|
|
var mapSizeTran = mainSceneRoot.Find("MapSize");
|
|
|
|
BoxCollider2D collider2D = mapSizeTran.GetComponent<BoxCollider2D>();
|
|
|
|
var bounds = collider2D.bounds;
|
|
|
|
self.MapMinPos = bounds.min;
|
|
|
|
self.MapMaxPos = bounds.max;
|
|
|
|
self.MapSize = collider2D.size;
|
|
|
|
|
|
|
|
Transform availablePlaceObj = mapSizeTran.Find("AvailablePlaceSize");
|
|
|
|
collider2D = availablePlaceObj.GetComponent<BoxCollider2D>();
|
|
|
|
bounds = collider2D.bounds;
|
|
|
|
self.AvalablePlaceMinPos = bounds.min;
|
|
|
|
var size = collider2D.size;
|
|
|
|
|
|
|
|
float width = size.x;
|
|
|
|
float height = width / 2;
|
|
|
|
if (height > size.y)
|
|
|
|
{
|
|
|
|
height = size.y;
|
|
|
|
width = height * 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.TileMapWidth = width;
|
|
|
|
self.TileMapHeight = height;
|
|
|
|
self.HalfTileMapWidth = self.TileMapWidth / 2;
|
|
|
|
self.HalfTileMapHeight = self.TileMapHeight / 2;
|
|
|
|
self.MaxTileX = Mathf.FloorToInt(self.TileMapWidth / self.TileWidth);
|
|
|
|
self.MaxTileY = self.MaxTileX;
|
|
|
|
self.OccupyPlaceMap = new bool[self.MaxTileX, self.MaxTileY];
|
|
|
|
|
|
|
|
self.HalfTileHeight = self.TileHeight / 2;
|
|
|
|
self.HalfTileWidth = self.TileWidth / 2;
|
|
|
|
|
|
|
|
self.BuildingRoot = GameObject.Find("SceneRoot/MainSceneRoot/Scene/Layout/BuildingRoot").transform;
|
|
|
|
self.ResourceRoot = GameObject.Find("SceneRoot/MainSceneRoot/Scene/Layout/ResourceRoot").transform;
|
|
|
|
self.PeopleRoot = GameObject.Find("SceneRoot/MainSceneRoot/PeopleRoot").transform;
|
|
|
|
|
|
|
|
// add grid
|
|
|
|
self.CreateGrid();
|
|
|
|
self.HideGrid();
|
|
|
|
|
|
|
|
// add indicator
|
|
|
|
self.CreateIndicator();
|
|
|
|
self.HideIndicator();
|
|
|
|
|
|
|
|
self.UpdateBuildingDataTimer = TimerComponent.Instance.NewRepeatedTimer(30000, TimerType.UpdateBuildingDataTimer, self);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void CreateGrid(this MapComponent self)
|
|
|
|
{
|
|
|
|
Transform mainSceneRoot = GameObject.Find("MainSceneRoot").transform;
|
|
|
|
var gridMeshObj = mainSceneRoot.Find("GridMesh").gameObject;
|
|
|
|
MeshRenderer meshRenderer = gridMeshObj.AddComponent<MeshRenderer>();
|
|
|
|
meshRenderer.material = new Material(Shader.Find("Sprites/Default"));
|
|
|
|
meshRenderer.material.color = new Color(0.9f, 0.9f, 0.9f, 0.5f);
|
|
|
|
self.GridMeshFilter = gridMeshObj.AddComponent<MeshFilter>();
|
|
|
|
self.GridMesh = new Mesh();
|
|
|
|
|
|
|
|
var verticies = new List<Vector3>();
|
|
|
|
var indicies = new List<int>();
|
|
|
|
|
|
|
|
// 以最底部为Map的数组的0,0点
|
|
|
|
|
|
|
|
var halfTileWidth = self.HalfTileWidth;
|
|
|
|
var halfTileHeight = self.HalfTileHeight;
|
|
|
|
// for coloum
|
|
|
|
for (int i = 0; i <= self.MaxTileY; i++)
|
|
|
|
{
|
|
|
|
float beginX = i * halfTileWidth;
|
|
|
|
float beginY = -self.HalfTileMapHeight + i * halfTileHeight;
|
|
|
|
|
|
|
|
float endX = -self.HalfTileMapWidth + i * halfTileWidth;
|
|
|
|
float endY = i * halfTileHeight;
|
|
|
|
|
|
|
|
Vector3 start = new Vector3(beginX, beginY, 0);
|
|
|
|
Vector3 end = new Vector3(endX, endY, 0);
|
|
|
|
verticies.Add(start);
|
|
|
|
verticies.Add(end);
|
|
|
|
indicies.Add(i * 2);
|
|
|
|
indicies.Add(i*2 + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int offset = verticies.Count;
|
|
|
|
// for row
|
|
|
|
for (int i = 0; i <= self.MaxTileX; i++)
|
|
|
|
{
|
|
|
|
float beginX = -i * halfTileWidth;
|
|
|
|
float beginY = -self.HalfTileMapHeight + i * halfTileHeight;
|
|
|
|
|
|
|
|
float endX = self.HalfTileMapWidth - i * halfTileWidth;
|
|
|
|
float endY = i * halfTileHeight;
|
|
|
|
|
|
|
|
Vector3 start = new Vector3(beginX, beginY, 0);
|
|
|
|
Vector3 end = new Vector3(endX, endY, 0);
|
|
|
|
verticies.Add(start);
|
|
|
|
verticies.Add(end);
|
|
|
|
indicies.Add(offset + i * 2);
|
|
|
|
indicies.Add(offset + i * 2 + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.GridMesh.vertices = verticies.ToArray();
|
|
|
|
self.GridMesh.SetIndices(indicies.ToArray(), MeshTopology.Lines, 0);
|
|
|
|
self.GridMeshFilter.mesh = self.GridMesh;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void ShowGrid(this MapComponent self)
|
|
|
|
{
|
|
|
|
self.GridMeshFilter.gameObject.SetActive(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void HideGrid(this MapComponent self)
|
|
|
|
{
|
|
|
|
self.GridMeshFilter.gameObject.SetActive(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Vector2 MapToWorldPos(this MapComponent self, int row, int col)
|
|
|
|
{
|
|
|
|
Vector2 worldPos = new Vector2();
|
|
|
|
worldPos.x = (col - row) * self.HalfTileWidth;
|
|
|
|
worldPos.y = -self.HalfTileMapHeight + (row + col) * self.HalfTileHeight;
|
|
|
|
return worldPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Vector2Int WorldToMapPos(this MapComponent self, Vector2 worldPos)
|
|
|
|
{
|
|
|
|
Vector2Int mapPos = new Vector2Int();
|
|
|
|
var offsetY = worldPos.y + self.HalfTileMapHeight;
|
|
|
|
mapPos.x = Mathf.RoundToInt(offsetY / self.TileHeight - worldPos.x / self.TileWidth);
|
|
|
|
mapPos.y = Mathf.RoundToInt(worldPos.x / self.TileWidth + offsetY / self.TileHeight);
|
|
|
|
|
|
|
|
mapPos.x = Mathf.Clamp(mapPos.x, 0, self.MaxTileX);
|
|
|
|
mapPos.y = Mathf.Clamp(mapPos.y, 0, self.MaxTileY);
|
|
|
|
return mapPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void CreateIndicator(this MapComponent self)
|
|
|
|
{
|
|
|
|
self.OccupyPlaceInidcator = BuildingViewHelper.CreateOcupyPlaceInicator("OccupyPlaceIndicator", self.ValidColor);
|
|
|
|
self.OccupyPlaceIndicatorMR = self.OccupyPlaceInidcator.GetComponent<MeshRenderer>();;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static RectIndices GetUnitRectIndices(this MapComponent self, Vector3 worldPos, Vector2Int size)
|
|
|
|
{
|
|
|
|
RectIndices rectIndices = new();
|
|
|
|
// 坐标原点在底部中心
|
|
|
|
Vector2Int bottomPos = self.WorldToMapPos(worldPos);
|
|
|
|
rectIndices.startRow = bottomPos.x;
|
|
|
|
rectIndices.endRow = Mathf.Min(bottomPos.x + size.x, self.MaxTileX);
|
|
|
|
rectIndices.startCol = bottomPos.y;
|
|
|
|
rectIndices.endCol = Mathf.Min(bottomPos.y + size.y, self.MaxTileY);
|
|
|
|
|
|
|
|
return rectIndices;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 以传入的点为中心的一个矩形范围
|
|
|
|
public static RectIndices GetUnitRectIndicesOfCenter(this MapComponent self, Vector3 worldPos, Vector2Int size)
|
|
|
|
{
|
|
|
|
RectIndices rectIndices = new();
|
|
|
|
// 坐标原点在底部中心
|
|
|
|
Vector2Int bottomPos = self.WorldToMapPos(worldPos);
|
|
|
|
|
|
|
|
int halfSizeX = size.x / 2;
|
|
|
|
int halfSizeY = size.y / 2;
|
|
|
|
rectIndices.startRow = Mathf.Max(bottomPos.x - halfSizeX, 0);
|
|
|
|
rectIndices.endRow = Mathf.Min(bottomPos.x + halfSizeX, self.MaxTileX);
|
|
|
|
rectIndices.startCol = Mathf.Max(bottomPos.y - halfSizeY, 0);
|
|
|
|
rectIndices.endCol = Mathf.Min(bottomPos.y + halfSizeY, self.MaxTileY);
|
|
|
|
|
|
|
|
return rectIndices;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool IsPosInRect(this MapComponent self, Vector2Int pos, RectIndices rectIndices)
|
|
|
|
{
|
|
|
|
if (pos.x >= rectIndices.startRow &&
|
|
|
|
pos.x < rectIndices.endRow &&
|
|
|
|
pos.y >= rectIndices.startCol &&
|
|
|
|
pos.y < rectIndices.endCol)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool CheckPlaceValid(this MapComponent self, ref RectIndices rectIndices)
|
|
|
|
{
|
|
|
|
for (int i = rectIndices.startRow; i < rectIndices.endRow; i++)
|
|
|
|
{
|
|
|
|
for (int j = rectIndices.startCol; j < rectIndices.endCol; j++)
|
|
|
|
{
|
|
|
|
if (self.OccupyPlaceMap[i, j])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static bool IsPlaceValid(this MapComponent self, Vector3 worldPos, Vector2Int size)
|
|
|
|
{
|
|
|
|
RectIndices rectIndices = self.GetUnitRectIndices(worldPos, size);
|
|
|
|
|
|
|
|
return self.CheckPlaceValid(ref rectIndices);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void UpdateIndicator(this MapComponent self,Vector3 worldPos, Vector2Int size)
|
|
|
|
{
|
|
|
|
var isValid = self.IsPlaceValid(worldPos, size);
|
|
|
|
if (isValid)
|
|
|
|
{
|
|
|
|
self.OccupyPlaceIndicatorMR.material.color = self.ValidColor;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
self.OccupyPlaceIndicatorMR.material.color = self.InvalidColor;
|
|
|
|
}
|
|
|
|
|
|
|
|
BuildingViewHelper.UpdateIndicatorLocal(self.OccupyPlaceInidcator, self, worldPos, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void ShowIndicator(this MapComponent self)
|
|
|
|
{
|
|
|
|
self.OccupyPlaceInidcator.SetActive(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void HideIndicator(this MapComponent self)
|
|
|
|
{
|
|
|
|
self.OccupyPlaceInidcator.SetActive(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 对齐坐标到格子上
|
|
|
|
public static Vector3 AlignPlacePosition(this MapComponent self, Vector3 worldPos, Vector2Int size)
|
|
|
|
{
|
|
|
|
Vector2Int bottomPos = self.WorldToMapPos(worldPos);
|
|
|
|
int x = Mathf.Clamp(bottomPos.x, 0, self.MaxTileX - size.x);
|
|
|
|
int y = Mathf.Clamp(bottomPos.y, 0, self.MaxTileY - size.y);
|
|
|
|
|
|
|
|
|
|
|
|
return self.MapToWorldPos(x, y);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void MarkPlaceOnGrid(this MapComponent self, Vector3 pos, Vector2Int size, bool marked = true)
|
|
|
|
{
|
|
|
|
RectIndices rectIndices = self.GetUnitRectIndices(pos, size);
|
|
|
|
|
|
|
|
for (int i = rectIndices.startRow; i < rectIndices.endRow; i++)
|
|
|
|
{
|
|
|
|
Mathf.Clamp(i, 0, self.MaxTileX - 1);
|
|
|
|
for (int j = rectIndices.startCol; j < rectIndices.endCol; j++)
|
|
|
|
{
|
|
|
|
Mathf.Clamp(j, 0, self.MaxTileY - 1);
|
|
|
|
self.OccupyPlaceMap[i, j] = marked;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void UpdateNavMesh2d(this MapComponent self)
|
|
|
|
{
|
|
|
|
self.NavMesh2d.BuildNavMesh();
|
|
|
|
}
|
|
|
|
|
|
|
|
// sprite的局部坐标系的原点为底部中点
|
|
|
|
public static Vector2Int LocalToMapPos(this MapComponent self, Vector2 topPos)
|
|
|
|
{
|
|
|
|
Vector2Int mapPos = new Vector2Int();
|
|
|
|
var tileWidth = self.TileWidth;
|
|
|
|
var tileHeight = self.TileHeight;
|
|
|
|
int row = Mathf.RoundToInt(topPos.y / tileHeight - topPos.x / tileWidth);
|
|
|
|
int col = Mathf.RoundToInt(topPos.y / tileHeight + topPos.x / tileWidth);
|
|
|
|
mapPos.x = row;
|
|
|
|
mapPos.y = col;
|
|
|
|
|
|
|
|
return mapPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Vector2 MapToLocalPos(this MapComponent self, int row, int col)
|
|
|
|
{
|
|
|
|
Vector2 localPos = new Vector2();
|
|
|
|
localPos.x = (col - row) * self.HalfTileWidth;
|
|
|
|
localPos.y = (row + col) * self.HalfTileHeight;
|
|
|
|
return localPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Vector2Int GetSizeBySpriteCollider(this MapComponent self, SpriteRenderer spriteRenderer)
|
|
|
|
{
|
|
|
|
|
|
|
|
PolygonCollider2D polygonCollider2D = spriteRenderer.GetComponent<PolygonCollider2D>();
|
|
|
|
if (polygonCollider2D == null)
|
|
|
|
{
|
|
|
|
Log.Warning("Sprite don't has a polygoncollider");
|
|
|
|
return Vector2Int.zero;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2 约定为多边形碰撞盒的顶点, 由工具生成
|
|
|
|
Vector2Int size = self.LocalToMapPos(polygonCollider2D.points[2]);
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static async ETTask UpdateBuildingData(this MapComponent self)
|
|
|
|
{
|
|
|
|
Unit unit = UnitHelper.GetMyUnitFromZoneScene(self.ZoneScene());
|
|
|
|
await BuildingHelper.GetBuildingDurable(unit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|