[Add] TextMeshPro & Chunk maker
This commit is contained in:
@@ -35,6 +35,10 @@ namespace InfiniteWorld
|
||||
[SerializeField] private float environmentNoiseScale = 0.19f;
|
||||
[SerializeField] private float environmentThreshold = 0.7f;
|
||||
|
||||
[Header("Random Objects")]
|
||||
[SerializeField, Range(0f, 1f)] private float randomPrefabChance = 0.06f;
|
||||
[SerializeField] private float randomPrefabZOffset = -0.1f;
|
||||
|
||||
[Header("Streaming")]
|
||||
[SerializeField, Min(1)] private int maxAsyncChunkJobs = 2;
|
||||
[SerializeField, Min(1)] private int maxChunkRendersPerFrame = 1;
|
||||
@@ -92,6 +96,36 @@ namespace InfiniteWorld
|
||||
SetLoadingPaused(false);
|
||||
}
|
||||
|
||||
public bool UsesProfile(WorldAutotileProfile candidateProfile)
|
||||
{
|
||||
return profile == candidateProfile;
|
||||
}
|
||||
|
||||
public void EditorRefreshFromProfile()
|
||||
{
|
||||
EnsureSceneInfrastructure();
|
||||
EnsureRuntimeData();
|
||||
cachedGroundTile = null;
|
||||
cachedGroundTiles = null;
|
||||
|
||||
List<Vector2Int> coords = new List<Vector2Int>(chunks.Keys);
|
||||
for (int i = 0; i < coords.Count; i++)
|
||||
{
|
||||
if (!chunks.TryGetValue(coords[i], out ChunkRuntime runtime) || !runtime.HasData)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
runtime.State = ChunkState.ReadyToRender;
|
||||
RenderChunk(coords[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < coords.Count; i++)
|
||||
{
|
||||
RefreshNeighborBorders(coords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureSceneInfrastructure()
|
||||
{
|
||||
grid = GetComponentInChildren<Grid>();
|
||||
@@ -120,7 +154,10 @@ namespace InfiniteWorld
|
||||
if (profile == null || !profile.HasAnyAssignedTiles())
|
||||
{
|
||||
runtimeFallbackProfile = RuntimeWorldProfileFactory.CreateFallbackProfile();
|
||||
return;
|
||||
}
|
||||
|
||||
runtimeFallbackProfile = null;
|
||||
}
|
||||
|
||||
private bool TryFindPlayer()
|
||||
@@ -215,8 +252,10 @@ namespace InfiniteWorld
|
||||
Tilemap ground = CreateTilemap("Ground", chunkObject.transform, 0, false);
|
||||
Tilemap walls = CreateTilemap("Walls", chunkObject.transform, 1, true);
|
||||
Tilemap environment = CreateTilemap("Environment", chunkObject.transform, 2, false);
|
||||
Transform objectsRoot = new GameObject("Objects").transform;
|
||||
objectsRoot.SetParent(chunkObject.transform, false);
|
||||
|
||||
return new GeneratedChunk(chunkObject.transform, ground, walls, environment);
|
||||
return new GeneratedChunk(chunkObject.transform, ground, walls, environment, objectsRoot);
|
||||
}
|
||||
|
||||
private Tilemap CreateTilemap(string name, Transform parent, int sortingOrder, bool addCollision)
|
||||
@@ -473,6 +512,7 @@ namespace InfiniteWorld
|
||||
chunk.Ground.SetTilesBlock(bounds, groundTiles);
|
||||
chunk.Walls.SetTilesBlock(bounds, wallTiles);
|
||||
chunk.Environment.SetTilesBlock(bounds, environmentTiles);
|
||||
RenderRandomPrefabs(coord, runtime, activeProfile);
|
||||
runtime.State = ChunkState.Rendered;
|
||||
}
|
||||
|
||||
@@ -620,6 +660,102 @@ namespace InfiniteWorld
|
||||
return activeProfile.environmentTiles[0].tile;
|
||||
}
|
||||
|
||||
private void RenderRandomPrefabs(Vector2Int coord, ChunkRuntime runtime, WorldAutotileProfile activeProfile)
|
||||
{
|
||||
if (runtime.Chunk.ObjectsRoot == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearSpawnedObjects(runtime.Chunk.ObjectsRoot);
|
||||
if (randomPrefabChance <= 0f || activeProfile.randomPrefabs == null || activeProfile.randomPrefabs.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int y = 0; y < chunkSize; y++)
|
||||
{
|
||||
for (int x = 0; x < chunkSize; x++)
|
||||
{
|
||||
if (runtime.WallMask[x, y] || runtime.EnvironmentMask[x, y])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector2Int worldCell = ChunkToWorldCell(coord, x, y);
|
||||
if (Hash01(worldCell.x, worldCell.y, seed + 1103) > randomPrefabChance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GameObject prefab = PickRandomPrefab(worldCell, activeProfile);
|
||||
if (prefab == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GameObject instance = Instantiate(prefab, runtime.Chunk.ObjectsRoot);
|
||||
instance.transform.localPosition = new Vector3(x + 0.5f, y + 0.5f, randomPrefabZOffset);
|
||||
instance.transform.localRotation = Quaternion.identity;
|
||||
instance.name = prefab.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject PickRandomPrefab(Vector2Int worldCell, WorldAutotileProfile activeProfile)
|
||||
{
|
||||
float total = 0f;
|
||||
for (int i = 0; i < activeProfile.randomPrefabs.Count; i++)
|
||||
{
|
||||
RandomPrefabEntry entry = activeProfile.randomPrefabs[i];
|
||||
if (entry != null && entry.prefab != null)
|
||||
{
|
||||
total += Mathf.Max(0.01f, entry.weight);
|
||||
}
|
||||
}
|
||||
|
||||
if (total <= 0f)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
float selector = Hash01(worldCell.x, worldCell.y, seed + 1409) * total;
|
||||
float cumulative = 0f;
|
||||
for (int i = 0; i < activeProfile.randomPrefabs.Count; i++)
|
||||
{
|
||||
RandomPrefabEntry entry = activeProfile.randomPrefabs[i];
|
||||
if (entry == null || entry.prefab == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
cumulative += Mathf.Max(0.01f, entry.weight);
|
||||
if (selector <= cumulative)
|
||||
{
|
||||
return entry.prefab;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < activeProfile.randomPrefabs.Count; i++)
|
||||
{
|
||||
RandomPrefabEntry entry = activeProfile.randomPrefabs[i];
|
||||
if (entry != null && entry.prefab != null)
|
||||
{
|
||||
return entry.prefab;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void ClearSpawnedObjects(Transform root)
|
||||
{
|
||||
for (int i = root.childCount - 1; i >= 0; i--)
|
||||
{
|
||||
UnityEngine.Object.Destroy(root.GetChild(i).gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2Int WorldToChunk(Vector3 position)
|
||||
{
|
||||
return new Vector2Int(
|
||||
@@ -872,18 +1008,20 @@ namespace InfiniteWorld
|
||||
|
||||
private readonly struct GeneratedChunk
|
||||
{
|
||||
public GeneratedChunk(Transform root, Tilemap ground, Tilemap walls, Tilemap environment)
|
||||
public GeneratedChunk(Transform root, Tilemap ground, Tilemap walls, Tilemap environment, Transform objectsRoot)
|
||||
{
|
||||
Root = root;
|
||||
Ground = ground;
|
||||
Walls = walls;
|
||||
Environment = environment;
|
||||
ObjectsRoot = objectsRoot;
|
||||
}
|
||||
|
||||
public Transform Root { get; }
|
||||
public Tilemap Ground { get; }
|
||||
public Tilemap Walls { get; }
|
||||
public Tilemap Environment { get; }
|
||||
public Transform ObjectsRoot { get; }
|
||||
}
|
||||
|
||||
private sealed class ChunkRuntime
|
||||
|
||||
Reference in New Issue
Block a user