using System; using System.Collections.Generic; using System.Text; using UnityEngine; // ReSharper disable once CheckNamespace namespace BlueWaterProject { [Serializable] public class UnitMatrix { public int soldiers; // 부대 안의 병사 수 public int rows; // 배치될 행의 갯수 public int columns; // 배치될 열의 갯수 //public int centerNum; // 부대의 중심 번호 public UnitMatrix(int soldiers, int rows, int columns) { this.soldiers = soldiers; this.rows = rows; this.columns = columns; } } public class UnitManager : Singleton { #region Property and variable [Tooltip("바닥 레이어")] [field: SerializeField] public LayerMask GroundLayer { get; private set; } [Tooltip("바닥과의 최대 허용 거리")] [field: SerializeField] public float MaxGroundDistance { get; private set; } = 0.5f; [Tooltip("병력 간의 간격")] [field: SerializeField] public float SoldierSpacing { get; private set; } = 0.5f; [Tooltip("부대 배치 행렬")] [field: SerializeField] public List UnitMatrices { get; private set; } = new(9); [Tooltip("병력들의 프리팹 리스트(순서 중요)")] [SerializeField] private List soliderPrefabList = new(10); #endregion #region Unity built-in function protected override void Awake() { base.Awake(); GroundLayer = LayerMask.GetMask("Ground"); InitUnitMatrices(); } private void Reset() { GroundLayer = LayerMask.GetMask("Ground"); MaxGroundDistance = 0.5f; SoldierSpacing = 0.5f; soliderPrefabList = new List(10); // TODO : 프리팹 자동 리셋화 필요 InitUnitMatrices(); } #endregion #region Custom function /// /// 부대 배치 행렬 초기화 함수 /// [ContextMenu("InitUnitMatrices")] public void InitUnitMatrices() { UnitMatrices = new List(9) { new(1, 1, 1), new(2, 1, 2), new(3, 1, 3), new(4, 2, 2), new(6, 2, 3), new(8, 2, 4), new(9, 3, 3), new(12, 3, 4), new(16, 4, 4), }; } /// /// 부대 생성 함수 /// public void CreateUnit(UnitController unitController, Unit unit) { DestroyDeployedSoldiers(unitController); unitController.gameObject.name = unit.unitName; unitController.gameObject.layer = LayerMask.NameToLayer("Unit"); unit.soldierList = new List(unit.soliderCount); var objectNameBuilder = new StringBuilder(); var matrix = UnitMatrices.Find(um => um.soldiers == unit.soliderCount); if (matrix == null) { Debug.LogError("사용할 수 없는 병력의 숫자입니다. UnitManager의 UnitMatrices를 확인해주세요."); return; } for (var i = 0; i < unit.soliderCount; i++) { var row = i / matrix.columns; var column = i % matrix.columns; var xOffset = (column - (matrix.columns - 1) / 2.0f) * SoldierSpacing; var zOffset = (row - (matrix.rows - 1) / 2.0f) * SoldierSpacing; var spawnPosition = unitController.transform.position + new Vector3(xOffset, 0, zOffset); var ray = new Ray(spawnPosition, Vector3.down); if (Physics.Raycast(ray, out var hit, MaxGroundDistance, GroundLayer)) { spawnPosition.y = hit.point.y; } else { Debug.LogError("병력이 땅과 맞닿아 있지 않아 배치할 수 없는 위치입니다."); DestroyDeployedSoldiers(unitController); return; } var soldierObject = Instantiate(soliderPrefabList[(int)unit.unitType - 1], spawnPosition, Quaternion.identity, unitController.transform).GetComponent(); objectNameBuilder.Clear(); objectNameBuilder.Append(soliderPrefabList[(int)unit.unitType - 1].name); objectNameBuilder.Append("_"); objectNameBuilder.AppendFormat("{0:00}", i + 1); soldierObject.name = objectNameBuilder.ToString(); unit.soldierList.Add(soldierObject); } // var boxCollider = unitController.gameObject.AddComponent(); // boxCollider.isTrigger = true; // boxCollider.center = new Vector3(0f, 0.3f, 0f); // boxCollider.size = new Vector3(matrix.columns * 0.5f, 1f, matrix.rows * 0.5f); } /// /// 기존에 생성된 부대 병력들이 있으면 확인해서 삭제해주는 함수 /// private void DestroyDeployedSoldiers(UnitController unitController) { if (unitController.transform.childCount <= 0) return; for (var i = unitController.transform.childCount - 1; i >= 0; i--) { if (Application.isPlaying) { Destroy(unitController.transform.GetChild(i).gameObject); } else { DestroyImmediate(unitController.transform.GetChild(i).gameObject); } } // var boxColliders = unitController.GetComponents(); // foreach (var boxCollider in boxColliders) // { // if (Application.isPlaying) // { // Destroy(boxCollider); // } // else // { // DestroyImmediate(boxCollider); // } // } } #endregion } }