using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Serialization; namespace Game { public enum EShapeType { Dot, Circle, Sector, Box, } public class Shape { public EShapeType Type; public Vector3 Offset; public float Height; public float SizeX; public float SizeY; public float Radius; public float Angle; private List vertices = new List(); public static Shape NewDot(Vector3 offset) { var shape = new Shape { Type = EShapeType.Dot, Offset = offset, }; return shape; } public static Shape NewCircle(Vector3 offset, float height, float radius) { var shape = new Shape { Type = EShapeType.Circle, Offset = offset, Height = height, Radius = radius }; return shape; } public static Shape NewSector(Vector3 offset, float height, float radius, float angle) { var shape = new Shape { Type = EShapeType.Sector, Offset = offset, Height = height, Radius = radius, Angle = angle }; return shape; } public static Shape NewBox(Vector3 offset, float height, float sizeX, float sizeY) { Util.Print("offset", offset); var shape = new Shape { Type = EShapeType.Box, Offset = offset, Height = height, SizeX = sizeX, SizeY = sizeY }; return shape; } public Vector4 GetAABB(Vector3 direction) { var aabb = Vector4.zero; switch (Type) { case EShapeType.Circle: case EShapeType.Sector: aabb = new Vector4(-Radius, Radius, -Radius, Radius); break; case EShapeType.Box: ForeachVertices(direction, (vertex) => { if (vertex.x < aabb.x) aabb.x = vertex.x; if (vertex.x > aabb.y) aabb.y = vertex.x; if (vertex.z < aabb.z) aabb.z = vertex.z; if (vertex.z > aabb.w) aabb.w = vertex.z; }); break; } return aabb; } public void SetVertices(Vector3 direction) { vertices.Clear(); switch (Type) { case EShapeType.Circle: for (var i = 0; i < 360; i += 15) { var angle = i * Mathf.Deg2Rad; var x = Mathf.Cos(angle) * Radius; var z = Mathf.Sin(angle) * Radius; vertices.Add(new Vector3(x, 0, z)); } break; case EShapeType.Sector: var rotAdd = Util.Vec3ToRot(direction); vertices.Add(Vector3.zero); var vertNum = (int)(Angle / 15); var anglePerVertex = Angle / vertNum; for (var i = 0; i <= vertNum; i++) { var angle = (i * anglePerVertex + rotAdd - Angle / 2) * Mathf.Deg2Rad; var x = Mathf.Cos(angle) * Radius; var z = Mathf.Sin(angle) * Radius; vertices.Add(new Vector3(x, 0, z)); } break; case EShapeType.Box: var (halfX, halfY) = (SizeX / 2, SizeY / 2); var up = new Vector3(direction.z, 0, direction.x); var right = new Vector3(direction.x, 0, -direction.z); var topLeft = right * halfX - up * halfY; var topRight = right * halfX + up * halfY; var bottomLeft = -right * halfX - up * halfY; var bottomRight = -right * halfX + up * halfY; vertices.Add(topLeft); vertices.Add(topRight); vertices.Add(bottomLeft); vertices.Add(bottomRight); break; } } public void ForeachVertices(Vector3 direction, Action action) { SetVertices(direction); foreach (var item in vertices) { action(item); } } public void ForeachVerticesPair(Vector3 direction, Action action) { SetVertices(direction); for (var i = 0; i < vertices.Count; i++) { var next = i + 1; if (next >= vertices.Count) next = 0; action(vertices[i], vertices[next]); } } } }