[Add] Thread fix

This commit is contained in:
2026-04-08 09:34:45 +07:00
parent 12430cdf4f
commit 50831947b9
8 changed files with 181 additions and 189 deletions
@@ -9,7 +9,7 @@ namespace InfiniteWorld.VoxelWorld
int worldSeed,
Vector2Int chunkCoord,
int chunkSize,
IReadOnlyList<WorldPrefabCollection> collections,
IReadOnlyList<WorldPrefabCollectionRuntime> collections,
System.Func<Vector2Int, int> getBaseHeight)
{
if (collections == null || collections.Count == 0)
@@ -25,15 +25,15 @@ namespace InfiniteWorld.VoxelWorld
for (int collectionIndex = 0; collectionIndex < collections.Count; collectionIndex++)
{
WorldPrefabCollection collection = collections[collectionIndex];
if (collection == null || collection.entries == null || collection.entries.Count == 0 || collection.maxPlacementsPerChunk <= 0)
WorldPrefabCollectionRuntime collection = collections[collectionIndex];
if (collection == null || collection.Entries == null || collection.Entries.Count == 0 || collection.MaxPlacementsPerChunk <= 0)
{
continue;
}
for (int placementIndex = 0; placementIndex < collection.maxPlacementsPerChunk; placementIndex++)
for (int placementIndex = 0; placementIndex < collection.MaxPlacementsPerChunk; placementIndex++)
{
if (!TryPickEntry(collection, worldSeed, chunkCoord, collectionIndex, placementIndex, out int entryIndex, out WorldPrefabEntry entry))
if (!TryPickEntry(collection, worldSeed, chunkCoord, collectionIndex, placementIndex, out int entryIndex, out WorldPrefabEntryRuntime entry))
{
continue;
}
@@ -71,18 +71,18 @@ namespace InfiniteWorld.VoxelWorld
return new WorldChunkPlacementPlan(spawnPoints, terrainPatches, flattenedCells.Count > 0 ? flattenedCells : null);
}
private static bool TryPickEntry(WorldPrefabCollection collection, int worldSeed, Vector2Int chunkCoord, int collectionIndex, int placementIndex, out int entryIndex, out WorldPrefabEntry entry)
private static bool TryPickEntry(WorldPrefabCollectionRuntime collection, int worldSeed, Vector2Int chunkCoord, int collectionIndex, int placementIndex, out int entryIndex, out WorldPrefabEntryRuntime entry)
{
float totalWeight = 0f;
for (int i = 0; i < collection.entries.Count; i++)
for (int i = 0; i < collection.Entries.Count; i++)
{
WorldPrefabEntry candidate = collection.entries[i];
if (candidate == null || candidate.prefab == null || candidate.weight <= 0f)
WorldPrefabEntryRuntime candidate = collection.Entries[i];
if (candidate == null || !candidate.HasPrefab || candidate.Weight <= 0f)
{
continue;
}
totalWeight += candidate.weight;
totalWeight += candidate.Weight;
}
if (totalWeight <= 0f)
@@ -94,15 +94,15 @@ namespace InfiniteWorld.VoxelWorld
float pick = WorldSeedUtility.Value01(WorldSeedUtility.Hash(worldSeed, chunkCoord.x, chunkCoord.y, collectionIndex, placementIndex, 1)) * totalWeight;
float accumulated = 0f;
for (int i = 0; i < collection.entries.Count; i++)
for (int i = 0; i < collection.Entries.Count; i++)
{
WorldPrefabEntry candidate = collection.entries[i];
if (candidate == null || candidate.prefab == null || candidate.weight <= 0f)
WorldPrefabEntryRuntime candidate = collection.Entries[i];
if (candidate == null || !candidate.HasPrefab || candidate.Weight <= 0f)
{
continue;
}
accumulated += candidate.weight;
accumulated += candidate.Weight;
if (pick <= accumulated)
{
entryIndex = i;
@@ -111,10 +111,10 @@ namespace InfiniteWorld.VoxelWorld
}
}
for (int i = collection.entries.Count - 1; i >= 0; i--)
for (int i = collection.Entries.Count - 1; i >= 0; i--)
{
WorldPrefabEntry candidate = collection.entries[i];
if (candidate == null || candidate.prefab == null || candidate.weight <= 0f)
WorldPrefabEntryRuntime candidate = collection.Entries[i];
if (candidate == null || !candidate.HasPrefab || candidate.Weight <= 0f)
{
continue;
}
@@ -129,36 +129,36 @@ namespace InfiniteWorld.VoxelWorld
return false;
}
private static bool PassesSpawnChance(WorldPrefabEntry entry, int worldSeed, Vector2Int chunkCoord, int collectionIndex, int placementIndex)
private static bool PassesSpawnChance(WorldPrefabEntryRuntime entry, int worldSeed, Vector2Int chunkCoord, int collectionIndex, int placementIndex)
{
if (entry == null)
{
return false;
}
if (entry.spawnChancePercent <= 0f)
if (entry.SpawnChancePercent <= 0f)
{
return false;
}
if (entry.spawnChancePercent >= 100f)
if (entry.SpawnChancePercent >= 100f)
{
return true;
}
float roll = WorldSeedUtility.Value01(WorldSeedUtility.Hash(worldSeed, chunkCoord.x, chunkCoord.y, collectionIndex, placementIndex, 11)) * 100f;
return roll <= entry.spawnChancePercent;
return roll <= entry.SpawnChancePercent;
}
private static bool TryPlanPlacement(
int worldSeed,
Vector2Int chunkCoord,
int chunkSize,
WorldPrefabCollection collection,
WorldPrefabCollectionRuntime collection,
int collectionIndex,
int placementIndex,
int entryIndex,
WorldPrefabEntry entry,
WorldPrefabEntryRuntime entry,
int spawnOrdinal,
HashSet<Vector2Int> occupiedCells,
HashSet<Vector2Int> flattenedCells,
@@ -172,20 +172,20 @@ namespace InfiniteWorld.VoxelWorld
patch = null;
Vector2Int chunkOrigin = new Vector2Int(chunkCoord.x * chunkSize, chunkCoord.y * chunkSize);
int attempts = Mathf.Max(1, collection.attemptsPerPlacement);
int attempts = Mathf.Max(1, collection.AttemptsPerPlacement);
for (int attempt = 0; attempt < attempts; attempt++)
{
int rotationSteps = entry.allowRotations ? WorldSeedUtility.Range(WorldSeedUtility.Hash(worldSeed, chunkCoord.x, chunkCoord.y, collectionIndex, placementIndex, attempt, 2), 0, 4) : 0;
Vector2Int footprint = GetFootprint(entry.footprint, rotationSteps);
int rotationSteps = entry.AllowRotations ? WorldSeedUtility.Range(WorldSeedUtility.Hash(worldSeed, chunkCoord.x, chunkCoord.y, collectionIndex, placementIndex, attempt, 2), 0, 4) : 0;
Vector2Int footprint = GetFootprint(entry.Footprint, rotationSteps);
if (footprint.x <= 0 || footprint.y <= 0)
{
continue;
}
int localMinX = collection.chunkEdgePadding;
int localMinZ = collection.chunkEdgePadding;
int localMaxX = chunkSize - collection.chunkEdgePadding - footprint.x;
int localMaxZ = chunkSize - collection.chunkEdgePadding - footprint.y;
int localMinX = collection.ChunkEdgePadding;
int localMinZ = collection.ChunkEdgePadding;
int localMaxX = chunkSize - collection.ChunkEdgePadding - footprint.x;
int localMaxZ = chunkSize - collection.ChunkEdgePadding - footprint.y;
if (localMaxX < localMinX || localMaxZ < localMinZ)
{
continue;
@@ -194,14 +194,14 @@ namespace InfiniteWorld.VoxelWorld
int localX = WorldSeedUtility.Range(WorldSeedUtility.Hash(worldSeed, chunkCoord.x, chunkCoord.y, collectionIndex, placementIndex, attempt, 3), localMinX, localMaxX + 1);
int localZ = WorldSeedUtility.Range(WorldSeedUtility.Hash(worldSeed, chunkCoord.x, chunkCoord.y, collectionIndex, placementIndex, attempt, 4), localMinZ, localMaxZ + 1);
RectInt footprintRect = new RectInt(localX, localZ, footprint.x, footprint.y);
RectInt reservedRect = ExpandRect(footprintRect, Mathf.Max(0, entry.clearance), chunkSize);
RectInt reservedRect = ExpandRect(footprintRect, Mathf.Max(0, entry.Clearance), chunkSize);
if (IntersectsOccupied(chunkOrigin, reservedRect, occupiedCells))
{
continue;
}
if (entry.placementMode == WorldPlacementMode.GroundOnly)
if (entry.PlacementMode == WorldPlacementMode.GroundOnly)
{
if (!IsGroundArea(chunkOrigin, reservedRect, flattenedCells, getBaseHeight))
{
@@ -227,7 +227,7 @@ namespace InfiniteWorld.VoxelWorld
long spawnId = WorldSeedUtility.ToStableId(
WorldSeedUtility.Hash(worldSeed, chunkCoord.x, chunkCoord.y, collectionIndex),
WorldSeedUtility.Hash(entryIndex, placementIndex, spawnOrdinal, footprintRect.x, footprintRect.y));
spawnPoint = new WorldSpawnPoint(spawnId, chunkCoord, spawnOrdinal, collectionIndex, entryIndex, entry, position, Quaternion.Euler(0f, rotationY, 0f));
spawnPoint = new WorldSpawnPoint(spawnId, chunkCoord, spawnOrdinal, collectionIndex, entryIndex, entry.Id, position, Quaternion.Euler(0f, rotationY, 0f));
return true;
}
@@ -239,14 +239,14 @@ namespace InfiniteWorld.VoxelWorld
int chunkSize,
RectInt footprintRect,
RectInt reservedRect,
WorldPrefabEntry entry,
WorldPrefabEntryRuntime entry,
HashSet<Vector2Int> occupiedCells,
HashSet<Vector2Int> flattenedCells,
System.Func<Vector2Int, int> getBaseHeight,
out WorldTerrainPatch patch,
out List<Vector2Int> reservedCells)
{
int flattenPadding = Mathf.Max(entry.clearance, entry.flattenPadding);
int flattenPadding = Mathf.Max(entry.Clearance, entry.FlattenPadding);
RectInt flattenRect = ExpandRect(footprintRect, flattenPadding, chunkSize);
List<Vector2Int> flattened = CollectCells(chunkOrigin, flattenRect);
if (IntersectsOccupied(flattened, occupiedCells))
@@ -256,7 +256,7 @@ namespace InfiniteWorld.VoxelWorld
return false;
}
List<Vector2Int> corridor = TryBuildAccessCorridor(chunkOrigin, chunkSize, flattenRect, Mathf.Max(1, entry.flattenSearchRadius), occupiedCells, flattenedCells, getBaseHeight);
List<Vector2Int> corridor = TryBuildAccessCorridor(chunkOrigin, chunkSize, flattenRect, Mathf.Max(1, entry.FlattenSearchRadius), occupiedCells, flattenedCells, getBaseHeight);
if (corridor == null)
{
patch = null;