데이터 파이프라인 추가 및 수정 + 크립 및 크립 캠프 배치 자동화

Hierachy > System > MapGenerator 에서 크립 관련 변수 설정 가능
Kaykit PlantWarrior 애셋 추가
This commit is contained in:
2026-02-02 19:50:30 +09:00
parent 106fe81c88
commit dc4d71d4b6
81 changed files with 4744 additions and 174 deletions

View File

@@ -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
}