119 lines
4.2 KiB
C#
119 lines
4.2 KiB
C#
using UnityEngine;
|
|
using Unity.Netcode;
|
|
|
|
public class UndergroundGenerator : NetworkBehaviour
|
|
{
|
|
[Header("Generation Range")]
|
|
[SerializeField] private Vector3Int generationRange = new Vector3Int(20, 30, 10);
|
|
[SerializeField] private float noiseScale = 0.12f;
|
|
|
|
[Header("Thresholds (0 to 1)")]
|
|
[SerializeField, Range(0, 1)] private float hollowThreshold = 0.35f;
|
|
[SerializeField, Range(0, 1)] private float baseResourceThreshold = 0.8f;
|
|
|
|
[Header("Depth Settings")]
|
|
[SerializeField] private float depthFactor = 0.005f; // 깊어질수록 임계값 감소 (자원 증가)
|
|
|
|
[Header("Prefabs")]
|
|
[SerializeField] private GameObject normalBlockPrefab;
|
|
[SerializeField] private GameObject resourceBlockPrefab;
|
|
|
|
[Header("Organization")]
|
|
[SerializeField] private string containerName = "UndergroundBlocks";
|
|
private Transform _blockContainer; // 블록들을 담을 부모 오브젝트
|
|
|
|
private float _seedX, _seedY, _seedZ;
|
|
|
|
private void Awake()
|
|
{
|
|
_seedX = Random.Range(0f, 99999f);
|
|
_seedY = Random.Range(0f, 99999f);
|
|
_seedZ = Random.Range(0f, 99999f);
|
|
|
|
// Hierarchy 정리를 위한 컨테이너 생성
|
|
_blockContainer = new GameObject(containerName).transform;
|
|
}
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
if (IsServer) GenerateFromGeneratorPivot();
|
|
}
|
|
|
|
private void GenerateFromGeneratorPivot()
|
|
{
|
|
Vector3Int originGrid = BuildManager.Instance.WorldToGrid3D(transform.position);
|
|
|
|
for (int x = 0; x < generationRange.x; x++)
|
|
{
|
|
for (int y = 0; y > -generationRange.y; y--)
|
|
{
|
|
for (int z = 0; z < generationRange.z; z++)
|
|
{
|
|
Vector3Int targetGridPos = originGrid + new Vector3Int(x, y, z);
|
|
float noise = Get3DNoise(targetGridPos.x, targetGridPos.y, targetGridPos.z);
|
|
|
|
if (noise < hollowThreshold) continue;
|
|
|
|
float currentThreshold = baseResourceThreshold + (y * depthFactor);
|
|
GameObject prefab = (noise > currentThreshold) ? resourceBlockPrefab : normalBlockPrefab;
|
|
|
|
SpawnBlock(prefab, targetGridPos);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SpawnBlock(GameObject prefab, Vector3Int gridPos)
|
|
{
|
|
if (prefab == null) return;
|
|
|
|
Vector3 worldPos = BuildManager.Instance.GridToWorld(gridPos);
|
|
|
|
// 1. 생성 시 부모(Container)를 지정하여 Hierarchy 정리
|
|
GameObject block = Instantiate(prefab, worldPos, Quaternion.identity);
|
|
|
|
// 2. 네트워크 스폰 (Netcode for GameObjects)
|
|
block.GetComponent<NetworkObject>().Spawn();
|
|
}
|
|
|
|
private float Get3DNoise(int x, int y, int z)
|
|
{
|
|
// 대칭 방지를 위한 10000 오프셋 및 시드 적용
|
|
float xCoord = (x + _seedX + 10000f) * noiseScale;
|
|
float yCoord = (y + _seedY + 10000f) * noiseScale;
|
|
float zCoord = (z + _seedZ + 10000f) * noiseScale;
|
|
|
|
float ab = Mathf.PerlinNoise(xCoord, yCoord);
|
|
float bc = Mathf.PerlinNoise(yCoord, zCoord);
|
|
float ac = Mathf.PerlinNoise(xCoord, zCoord);
|
|
|
|
return (ab + bc + ac) / 3f;
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
BuildManager bm = BuildManager.Instance;
|
|
if (bm == null) bm = FindFirstObjectByType<BuildManager>(); // 에러 방지 안전장치
|
|
if (bm == null) return;
|
|
|
|
Vector3Int originGrid = bm.WorldToGrid3D(transform.position);
|
|
|
|
for (int x = 0; x < generationRange.x; x += 2)
|
|
{
|
|
for (int y = -generationRange.y; y < 0; y += 2)
|
|
{
|
|
for (int z = 0; z < generationRange.z; z += 2)
|
|
{
|
|
Vector3Int targetGridPos = originGrid + new Vector3Int(x, y, z);
|
|
float noise = Get3DNoise(targetGridPos.x, targetGridPos.y, targetGridPos.z);
|
|
|
|
if (noise < hollowThreshold) continue;
|
|
|
|
Gizmos.color = (noise > baseResourceThreshold) ? Color.yellow : new Color(0.5f, 0.5f, 0.5f, 0.2f);
|
|
Vector3 pos = bm.GridToWorld(targetGridPos);
|
|
Gizmos.DrawSphere(pos, 0.2f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |