데이터 파이프라인 추가 및 수정 + 크립 및 크립 캠프 배치 자동화
Hierachy > System > MapGenerator 에서 크립 관련 변수 설정 가능 Kaykit PlantWarrior 애셋 추가
This commit is contained in:
@@ -86,6 +86,27 @@ namespace Northbound
|
||||
[Tooltip("배치 시도 최대 횟수")]
|
||||
[SerializeField] private int maxObstacleSpawnAttempts = 50;
|
||||
|
||||
[Header("Creep Camp Settings")]
|
||||
[Tooltip("크립 캠프 프리팹")]
|
||||
public GameObject creepCampPrefab;
|
||||
[Tooltip("크립 캠프 간 최소 거리")]
|
||||
[SerializeField] private float minDistanceBetweenCamps = 30f;
|
||||
[Tooltip("코어와의 최소 거리")]
|
||||
[SerializeField] private float minDistanceFromCoreCamps = 30f;
|
||||
[Tooltip("막사와의 최소 거리")]
|
||||
[SerializeField] private float minDistanceFromBarracksCamps = 30f;
|
||||
[Tooltip("초기 자원과의 최소 거리")]
|
||||
[SerializeField] private float minDistanceFromInitialResource = 30f;
|
||||
[Tooltip("추가 크립 캠프 개수")]
|
||||
[Range(0, 10)]
|
||||
[SerializeField] private int additionalCreepCampCount = 5;
|
||||
[Tooltip("크립 캠프 강도 기본값")]
|
||||
[SerializeField] private float baseCampStrength = 1f;
|
||||
[Tooltip("Z 위치에 따른 강도 증가율 (Z 100당)")]
|
||||
[SerializeField] private float strengthIncreasePerZ100 = 0.2f;
|
||||
[Tooltip("자원 보호 캠프 강도 보너스 (far camp보다 얼마나 강할지)")]
|
||||
[SerializeField] private float resourceCampStrengthBonus = 0.5f;
|
||||
|
||||
[Header("Generation Order")]
|
||||
[Tooltip("자원 먼저 생성 후 장애물 생성 (true) 또는 그 반대 (false)")]
|
||||
[SerializeField] private bool generateResourcesFirst = true;
|
||||
@@ -93,6 +114,8 @@ namespace Northbound
|
||||
private ResourceData[] _generatedResources;
|
||||
private float _globalProductionMultiplier = 1f;
|
||||
private List<Vector3> _spawnedPositions = new List<Vector3>();
|
||||
private List<Vector3> _creepCampPositions = new List<Vector3>();
|
||||
private List<GameObject> _creepPrefabs = new List<GameObject>();
|
||||
private Transform _objectsParent;
|
||||
|
||||
[System.Serializable]
|
||||
@@ -177,6 +200,7 @@ namespace Northbound
|
||||
}
|
||||
|
||||
_spawnedPositions.Clear();
|
||||
_creepCampPositions.Clear();
|
||||
|
||||
if (generateResourcesFirst)
|
||||
{
|
||||
@@ -189,6 +213,8 @@ namespace Northbound
|
||||
GenerateResources();
|
||||
}
|
||||
|
||||
GenerateCreepCamps();
|
||||
|
||||
Debug.Log($"[MapGenerator] Map generation complete!");
|
||||
}
|
||||
|
||||
@@ -658,6 +684,241 @@ namespace Northbound
|
||||
|
||||
#endregion
|
||||
|
||||
#region Creep Camp Generation
|
||||
|
||||
private void GenerateCreepCamps()
|
||||
{
|
||||
if (creepCampPrefab == null)
|
||||
{
|
||||
Debug.LogWarning("[MapGenerator] Creep camp prefab not assigned, skipping creep camp generation.");
|
||||
return;
|
||||
}
|
||||
|
||||
LoadCreepPrefabs();
|
||||
|
||||
if (_creepPrefabs.Count == 0)
|
||||
{
|
||||
Debug.LogWarning("[MapGenerator] No creep prefabs found in Assets/Prefabs/Creep/, skipping creep camp generation.");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log($"[MapGenerator] Starting creep camp generation. Resources: {_generatedResources.Length}, Additional camps: {additionalCreepCampCount}");
|
||||
|
||||
int totalCampsSpawned = 0;
|
||||
|
||||
for (int i = 0; i < _generatedResources.Length; i++)
|
||||
{
|
||||
Vector3 campPosition = FindValidCampPositionForResource(_generatedResources[i].position);
|
||||
if (campPosition != Vector3.zero)
|
||||
{
|
||||
float strength = CalculateCampStrength(_generatedResources[i].position.y, isResourceCamp: true);
|
||||
Debug.Log($"[MapGenerator] Spawning resource camp {i + 1} for resource at {_generatedResources[i].position}, position: {campPosition}, strength: {strength:F2} (with bonus)");
|
||||
SpawnCreepCamp(campPosition, strength);
|
||||
_creepCampPositions.Add(campPosition);
|
||||
totalCampsSpawned++;
|
||||
}
|
||||
}
|
||||
|
||||
int additionalSpawned = 0;
|
||||
for (int i = 0; i < additionalCreepCampCount; i++)
|
||||
{
|
||||
Vector3 campPosition = FindValidCampPosition();
|
||||
if (campPosition != Vector3.zero)
|
||||
{
|
||||
float strength = CalculateCampStrength(campPosition.z, isResourceCamp: false);
|
||||
Debug.Log($"[MapGenerator] Spawning additional camp {i + 1}, position: {campPosition}, strength: {strength:F2}");
|
||||
SpawnCreepCamp(campPosition, strength);
|
||||
_creepCampPositions.Add(campPosition);
|
||||
additionalSpawned++;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log($"[MapGenerator] Spawned {totalCampsSpawned} resource-based camps and {additionalSpawned} additional camps. Total: {totalCampsSpawned + additionalSpawned}");
|
||||
}
|
||||
|
||||
private void LoadCreepPrefabs()
|
||||
{
|
||||
Debug.Log($"[MapGenerator] LoadCreepPrefabs called, current count: {_creepPrefabs.Count}");
|
||||
|
||||
if (_creepPrefabs.Count > 0)
|
||||
{
|
||||
Debug.Log($"[MapGenerator] Skipping load, already have {_creepPrefabs.Count} prefabs");
|
||||
return;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
string[] prefabGuids = UnityEditor.AssetDatabase.FindAssets("t:Prefab", new[] { "Assets/Prefabs/Creep" });
|
||||
Debug.Log($"[MapGenerator] Found {prefabGuids.Length} prefabs in Assets/Prefabs/Creep/");
|
||||
_creepPrefabs.Clear();
|
||||
|
||||
foreach (string guid in prefabGuids)
|
||||
{
|
||||
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
|
||||
GameObject prefab = UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
||||
|
||||
if (prefab != null && prefab.GetComponent<CreepDataComponent>() != null)
|
||||
{
|
||||
_creepPrefabs.Add(prefab);
|
||||
Debug.Log($"[MapGenerator] Added creep prefab: {prefab.name}");
|
||||
}
|
||||
}
|
||||
#else
|
||||
Debug.LogWarning("[MapGenerator] Creep prefabs not loaded in build. Please assign creep prefabs manually in Inspector.");
|
||||
#endif
|
||||
|
||||
if (_creepPrefabs.Count > 0)
|
||||
{
|
||||
Debug.Log($"[MapGenerator] Loaded {_creepPrefabs.Count} creep prefabs from Assets/Prefabs/Creep/");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("[MapGenerator] No creep prefabs loaded!");
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 FindValidCampPosition()
|
||||
{
|
||||
int maxAttempts = 200;
|
||||
|
||||
for (int attempt = 0; attempt < maxAttempts; attempt++)
|
||||
{
|
||||
Vector3 candidatePosition = GetRandomPositionInPlayableArea();
|
||||
|
||||
if (IsValidCreepCampPosition(candidatePosition))
|
||||
{
|
||||
return candidatePosition;
|
||||
}
|
||||
}
|
||||
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
private bool IsValidCreepCampPosition(Vector3 position)
|
||||
{
|
||||
if (Vector2.Distance(new Vector2(position.x, position.z), _corePosition) < minDistanceFromCoreCamps)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Vector2.Distance(new Vector2(position.x, position.z), _barracksPosition) < minDistanceFromBarracksCamps)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Vector2.Distance(new Vector2(position.x, position.z), _initialResourcePosition) < minDistanceFromInitialResource)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var campPos in _creepCampPositions)
|
||||
{
|
||||
if (Vector3.Distance(position, campPos) < minDistanceBetweenCamps)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (position.x < -playableAreaWidth / 2f || position.x > playableAreaWidth / 2f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (position.z < startZ || position.z > endZ)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private Vector3 FindValidCampPositionForResource(Vector2 resourcePosition)
|
||||
{
|
||||
Vector3 bestPosition = Vector3.zero;
|
||||
float bestDistance = float.MaxValue;
|
||||
int maxAttempts = 50;
|
||||
|
||||
Debug.Log($"[MapGenerator] FindValidCampPositionForResource: Resource at {resourcePosition}, bounds: X:[{-playableAreaWidth/2f}, {playableAreaWidth/2f}], Z:[{startZ}, {endZ}]");
|
||||
|
||||
for (int attempt = 0; attempt < maxAttempts; attempt++)
|
||||
{
|
||||
float angle = Random.Range(0f, 360f);
|
||||
float distance = Random.Range(8f, 20f);
|
||||
Vector3 candidatePosition = new Vector3(
|
||||
resourcePosition.x + Mathf.Cos(angle * Mathf.Deg2Rad) * distance,
|
||||
1f,
|
||||
resourcePosition.y + Mathf.Sin(angle * Mathf.Deg2Rad) * distance
|
||||
);
|
||||
|
||||
if (IsValidCreepCampPosition(candidatePosition))
|
||||
{
|
||||
if (Vector3.Distance(candidatePosition, new Vector3(resourcePosition.x, 0, resourcePosition.y)) < bestDistance)
|
||||
{
|
||||
bestDistance = Vector3.Distance(candidatePosition, new Vector3(resourcePosition.x, 0, resourcePosition.y));
|
||||
bestPosition = candidatePosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestPosition == Vector3.zero)
|
||||
{
|
||||
Debug.LogWarning($"[MapGenerator] Failed to find camp position for resource at {resourcePosition} after {maxAttempts} attempts");
|
||||
}
|
||||
|
||||
return bestPosition;
|
||||
}
|
||||
|
||||
private float CalculateCampStrength(float zPosition, bool isResourceCamp = false)
|
||||
{
|
||||
float normalizedZ = (zPosition - startZ) / (endZ - startZ);
|
||||
float strengthMultiplier = baseCampStrength + (normalizedZ * (strengthIncreasePerZ100 * (endZ - startZ) / 100f));
|
||||
|
||||
if (isResourceCamp)
|
||||
{
|
||||
strengthMultiplier *= resourceCampStrengthBonus;
|
||||
}
|
||||
|
||||
return strengthMultiplier;
|
||||
}
|
||||
|
||||
private void SpawnCreepCamp(Vector3 position, float strength)
|
||||
{
|
||||
GameObject campObj = Instantiate(creepCampPrefab, position, Quaternion.identity);
|
||||
|
||||
CreepCamp creepCamp = campObj.GetComponent<CreepCamp>();
|
||||
if (creepCamp == null)
|
||||
{
|
||||
Debug.LogError($"[MapGenerator] Creep camp prefab doesn't have CreepCamp component!");
|
||||
Destroy(campObj);
|
||||
return;
|
||||
}
|
||||
|
||||
creepCamp.InitializeCamp(position.z, strength);
|
||||
creepCamp.SetCreepPrefabs(_creepPrefabs);
|
||||
Debug.Log($"[MapGenerator] Camp initialized with {_creepPrefabs.Count} creep prefabs");
|
||||
|
||||
NetworkObject networkObj = campObj.GetComponent<NetworkObject>();
|
||||
if (networkObj == null)
|
||||
{
|
||||
networkObj = campObj.AddComponent<NetworkObject>();
|
||||
}
|
||||
|
||||
networkObj.Spawn();
|
||||
|
||||
if (groupUnderParent && _objectsParent != null)
|
||||
{
|
||||
campObj.transform.SetParent(_objectsParent);
|
||||
}
|
||||
|
||||
if (campObj.GetComponent<FogOfWarVisibility>() == null)
|
||||
{
|
||||
var visibility = campObj.AddComponent<FogOfWarVisibility>();
|
||||
visibility.showInExploredAreas = false;
|
||||
visibility.updateInterval = 0.2f;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public float GetTotalProduction()
|
||||
@@ -758,6 +1019,15 @@ namespace Northbound
|
||||
Gizmos.color = Color.blue;
|
||||
Gizmos.DrawWireSphere(new Vector3(_initialResourcePosition.x, 0, _initialResourcePosition.y), 5f);
|
||||
}
|
||||
|
||||
if (creepCampPrefab != null)
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
foreach (var campPos in _creepCampPositions)
|
||||
{
|
||||
Gizmos.DrawWireSphere(campPos, 8f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user