2023-08-15 20:36:04 +00:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Text;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityEngine.Serialization;
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
|
|
|
|
// 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 : MonoBehaviour
|
|
|
|
{
|
|
|
|
#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<UnitMatrix> UnitMatrices { get; private set; } = new(9);
|
|
|
|
|
|
|
|
[Tooltip("병력들의 프리팹 리스트(순서 중요)")]
|
|
|
|
[SerializeField] private List<GameObject> soliderPrefabList = new(10);
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Unity built-in function
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
{
|
|
|
|
GroundLayer = LayerMask.GetMask("Ground");
|
|
|
|
InitUnitMatrices();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void Reset()
|
|
|
|
{
|
|
|
|
GroundLayer = LayerMask.GetMask("Ground");
|
|
|
|
MaxGroundDistance = 0.5f;
|
|
|
|
SoldierSpacing = 0.5f;
|
|
|
|
soliderPrefabList = new List<GameObject>(10); // TODO : 프리팹 자동 리셋화 필요
|
|
|
|
InitUnitMatrices();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Custom function
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 부대 배치 행렬 초기화 함수
|
|
|
|
/// </summary>
|
|
|
|
[ContextMenu("InitUnitMatrices")]
|
|
|
|
public void InitUnitMatrices()
|
|
|
|
{
|
|
|
|
UnitMatrices = new List<UnitMatrix>(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),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 부대 생성 함수
|
|
|
|
/// </summary>
|
|
|
|
public void CreateUnit(UnitController unitController, Unit unit)
|
|
|
|
{
|
|
|
|
DestroyDeployedSoldiers(unitController);
|
|
|
|
|
|
|
|
unitController.gameObject.name = unit.unitName;
|
|
|
|
unitController.gameObject.layer = LayerMask.NameToLayer("Unit");
|
|
|
|
unit.soldierList = new List<AiController>(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;
|
|
|
|
}
|
|
|
|
|
2023-08-16 05:40:33 +00:00
|
|
|
var soldierObject = Instantiate(soliderPrefabList[(int)unit.unitType - 1], spawnPosition, Quaternion.identity, unitController.transform).GetComponent<AiController>();
|
2023-08-15 20:36:04 +00:00
|
|
|
|
|
|
|
objectNameBuilder.Clear();
|
|
|
|
objectNameBuilder.Append(soliderPrefabList[(int)unit.unitType].name);
|
|
|
|
objectNameBuilder.Append("_");
|
|
|
|
objectNameBuilder.AppendFormat("{0:00}", i + 1);
|
|
|
|
|
|
|
|
soldierObject.name = objectNameBuilder.ToString();
|
|
|
|
unit.soldierList.Add(soldierObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
// var boxCollider = unitController.gameObject.AddComponent<BoxCollider>();
|
|
|
|
// boxCollider.isTrigger = true;
|
|
|
|
// boxCollider.center = new Vector3(0f, 0.3f, 0f);
|
|
|
|
// boxCollider.size = new Vector3(matrix.columns * 0.5f, 1f, matrix.rows * 0.5f);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 기존에 생성된 부대 병력들이 있으면 확인해서 삭제해주는 함수
|
|
|
|
/// </summary>
|
|
|
|
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<BoxCollider>();
|
|
|
|
// foreach (var boxCollider in boxColliders)
|
|
|
|
// {
|
|
|
|
// if (Application.isPlaying)
|
|
|
|
// {
|
|
|
|
// Destroy(boxCollider);
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// DestroyImmediate(boxCollider);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|