Files
Northbound/Assets/Scripts/CreepCamp.cs
dal4segno dc4d71d4b6 데이터 파이프라인 추가 및 수정 + 크립 및 크립 캠프 배치 자동화
Hierachy > System > MapGenerator 에서 크립 관련 변수 설정 가능
Kaykit PlantWarrior 애셋 추가
2026-02-02 19:50:30 +09:00

216 lines
7.0 KiB
C#

using Northbound.Data;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
namespace Northbound
{
public class CreepCamp : NetworkBehaviour
{
[Header("Camp Settings")]
[Tooltip("Creep prefabs available to spawn")]
[SerializeField] private List<GameObject> creepPrefabs = new List<GameObject>();
[Header("Spawning Settings")]
[Tooltip("Camp strength multiplier (higher = stronger creeps)")]
[SerializeField] private float campStrength = 1f;
[Tooltip("Cost budget for spawning creeps")]
[SerializeField] private float campCostBudget = 10f;
[Tooltip("Spawn radius around camp")]
[SerializeField] private float spawnRadius = 5f;
[Tooltip("Max creep spawn attempts")]
[SerializeField] private int maxSpawnAttempts = 50;
private float _zPosition;
public override void OnNetworkSpawn()
{
if (IsServer)
{
SpawnCreeps();
}
}
public void InitializeCamp(float zPosition, float strengthMultiplier)
{
_zPosition = zPosition;
campStrength = strengthMultiplier;
}
public void SetCreepPrefabs(List<GameObject> prefabs)
{
creepPrefabs.Clear();
creepPrefabs.AddRange(prefabs);
Debug.Log($"[CreepCamp] SetCreepPrefabs called with {prefabs.Count} prefabs. Current count: {creepPrefabs.Count}");
}
private void SpawnCreeps()
{
Debug.Log($"[CreepCamp] Starting creep spawn at Z={_zPosition:F1}, strength={campStrength:F2}x, prefabs={creepPrefabs.Count}");
if (creepPrefabs.Count == 0)
{
Debug.LogWarning($"[CreepCamp] No creep prefabs assigned!");
return;
}
float remainingCost = campCostBudget * campStrength;
Debug.Log($"[CreepCamp] Cost budget: {campCostBudget} x {campStrength:F2} = {remainingCost:F2}");
int spawnedCount = 0;
for (int attempt = 0; attempt < maxSpawnAttempts && remainingCost > 0; attempt++)
{
GameObject selectedCreep = SelectCreepByCost(remainingCost);
if (selectedCreep == null)
{
Debug.LogWarning($"[CreepCamp] Could not select creep (attempt {attempt + 1}/{maxSpawnAttempts}), remaining cost: {remainingCost:F2}");
break;
}
CreepData creepData = GetCreepDataFromPrefab(selectedCreep);
if (creepData == null)
{
Debug.LogWarning($"[CreepCamp] Could not get creep data from {selectedCreep.name}");
continue;
}
if (creepData.cost > remainingCost)
{
if (!CanSpawnAnyCreep(remainingCost))
{
Debug.LogWarning($"[CreepCamp] No affordable creeps found. Remaining cost: {remainingCost:F2}");
break;
}
continue;
}
Debug.Log($"[CreepCamp] Spawning {selectedCreep.name} (cost: {creepData.cost}, remaining: {remainingCost:F2})");
SpawnCreep(selectedCreep);
remainingCost -= creepData.cost;
spawnedCount++;
}
Debug.Log($"[CreepCamp] Spawned {spawnedCount} creeps at Z={_zPosition:F1} with strength {campStrength:F2}x");
}
private GameObject SelectCreepByCost(float remainingCost)
{
List<GameObject> affordableCreeps = new List<GameObject>();
foreach (var prefab in creepPrefabs)
{
CreepData creepData = GetCreepDataFromPrefab(prefab);
if (creepData != null && creepData.cost <= remainingCost)
{
affordableCreeps.Add(prefab);
}
}
if (affordableCreeps.Count == 0)
{
return null;
}
float totalWeight = 0f;
foreach (var prefab in affordableCreeps)
{
CreepData creepData = GetCreepDataFromPrefab(prefab);
if (creepData != null)
{
totalWeight += creepData.weight;
}
}
if (totalWeight == 0f)
{
return affordableCreeps[Random.Range(0, affordableCreeps.Count)];
}
float randomValue = Random.Range(0f, totalWeight);
float cumulativeWeight = 0f;
foreach (var prefab in affordableCreeps)
{
CreepData creepData = GetCreepDataFromPrefab(prefab);
if (creepData != null)
{
cumulativeWeight += creepData.weight;
if (randomValue <= cumulativeWeight)
{
return prefab;
}
}
}
return affordableCreeps[Random.Range(0, affordableCreeps.Count)];
}
private bool CanSpawnAnyCreep(float remainingCost)
{
foreach (var prefab in creepPrefabs)
{
CreepData creepData = GetCreepDataFromPrefab(prefab);
if (creepData != null && creepData.cost <= remainingCost)
{
return true;
}
}
return false;
}
private CreepData GetCreepDataFromPrefab(GameObject prefab)
{
if (prefab == null) return null;
CreepDataComponent component = prefab.GetComponent<CreepDataComponent>();
if (component != null)
{
return component.creepData;
}
return null;
}
private void SpawnCreep(GameObject prefab)
{
Vector3 spawnOffset = Random.insideUnitSphere * spawnRadius;
spawnOffset.y = 0;
GameObject creep = Instantiate(prefab, transform.position + spawnOffset, Quaternion.identity);
if (creep.GetComponent<FogOfWarVisibility>() == null)
{
var visibility = creep.AddComponent<FogOfWarVisibility>();
visibility.showInExploredAreas = false;
visibility.updateInterval = 0.2f;
}
NetworkObject networkObj = creep.GetComponent<NetworkObject>();
if (networkObj == null)
{
networkObj = creep.AddComponent<NetworkObject>();
}
networkObj.Spawn();
creep.transform.SetParent(transform);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, spawnRadius);
}
private void OnDrawGizmosSelected()
{
Gizmos.color = new Color(1f, 0f, 0f, 0.3f);
Gizmos.DrawSphere(transform.position, spawnRadius);
}
}
}