update
This commit is contained in:
30
Assets/Plugins/Native/BackroomsNoise/README.md
Normal file
30
Assets/Plugins/Native/BackroomsNoise/README.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# BackroomsNoise C++ Plugin
|
||||||
|
|
||||||
|
This native plugin provides high-performance noise generation for the Backrooms map system using **FastNoiseLite**.
|
||||||
|
|
||||||
|
## Files
|
||||||
|
- `BackroomsNoise.cpp`: C wrapper for Unity P/Invoke.
|
||||||
|
- `FastNoiseLite.h`: The noise library (ensure you have the full version from [GitHub](https://github.com/Auburn/FastNoiseLite)).
|
||||||
|
|
||||||
|
## How to Build (Windows MSVC)
|
||||||
|
|
||||||
|
1. Open **Developer Command Prompt for VS**.
|
||||||
|
2. Navigate to this directory.
|
||||||
|
3. Run:
|
||||||
|
```cmd
|
||||||
|
cl /LD /O2 /EHsc BackroomsNoise.cpp /Fe:BackroomsNoise.dll
|
||||||
|
```
|
||||||
|
4. Copy `BackroomsNoise.dll` to the `Assets/Plugins/` folder in Unity.
|
||||||
|
|
||||||
|
## How to Build (Cross-platform with CMake)
|
||||||
|
|
||||||
|
1. Create a `CMakeLists.txt`:
|
||||||
|
```cmake
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(BackroomsNoise)
|
||||||
|
add_library(BackroomsNoise SHARED BackroomsNoise.cpp)
|
||||||
|
```
|
||||||
|
2. Build as usual.
|
||||||
|
|
||||||
|
## Usage in Unity
|
||||||
|
The `NativeNoiseProvider.cs` script will automatically attempt to load `BackroomsNoise.dll`. If it fails, it will fall back to Unity's built-in `Mathf.PerlinNoise`.
|
||||||
7
Assets/Plugins/Native/BackroomsNoise/README.md.meta
Normal file
7
Assets/Plugins/Native/BackroomsNoise/README.md.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ebf9d2e10b290754b8cae46ebb44cbb0
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -11,7 +11,7 @@ namespace Hallucinate.GameSetup.Maze
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MazeManager : MonoBehaviour
|
public class MazeManager : MonoBehaviour
|
||||||
{
|
{
|
||||||
public enum AlgorithmType { Recursive, Wilsons, Prims, Crawler }
|
public enum AlgorithmType { Recursive, Wilsons, Prims, Crawler, NoiseRecursive }
|
||||||
|
|
||||||
[BoxGroup("Generation")]
|
[BoxGroup("Generation")]
|
||||||
[InfoBox("Set the array size to control how many maze floors are generated. Runtime grid data is rebuilt when Regenerate runs.")]
|
[InfoBox("Set the array size to control how many maze floors are generated. Runtime grid data is rebuilt when Regenerate runs.")]
|
||||||
@@ -215,6 +215,7 @@ namespace Hallucinate.GameSetup.Maze
|
|||||||
AlgorithmType.Wilsons => new WilsonsAlgorithm(),
|
AlgorithmType.Wilsons => new WilsonsAlgorithm(),
|
||||||
AlgorithmType.Prims => new PrimsAlgorithm(),
|
AlgorithmType.Prims => new PrimsAlgorithm(),
|
||||||
AlgorithmType.Crawler => new CrawlerAlgorithm(),
|
AlgorithmType.Crawler => new CrawlerAlgorithm(),
|
||||||
|
AlgorithmType.NoiseRecursive => new NoiseRecursiveGenerator(),
|
||||||
_ => new RecursiveAlgorithm()
|
_ => new RecursiveAlgorithm()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
152
Assets/Scripts/GameSetup/Maze/NoiseRecursiveGenerator.cs
Normal file
152
Assets/Scripts/GameSetup/Maze/NoiseRecursiveGenerator.cs
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Hallucinate.GameSetup.Maze.Extensions;
|
||||||
|
using Hallucinate.GameSetup.Maze.Native;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Hallucinate.GameSetup.Maze
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Advanced generator that combines C++ Native Noise with a Recursive Backtracking algorithm.
|
||||||
|
/// Creates a hybrid layout of large rooms and chaotic corridors.
|
||||||
|
/// </summary>
|
||||||
|
public class NoiseRecursiveGenerator : IMazeAlgorithm
|
||||||
|
{
|
||||||
|
private readonly List<MapLocation> _directions = MapLocation.Directions;
|
||||||
|
private float[] _noiseMap;
|
||||||
|
private int _seed = 1337;
|
||||||
|
|
||||||
|
// Thresholds
|
||||||
|
private const float RoomThreshold = 0.5f;
|
||||||
|
private const float CorridorThreshold = -0.3f;
|
||||||
|
private const int DeadEndNeighbourThreshold = 2;
|
||||||
|
|
||||||
|
public void Generate(MazeGrid grid)
|
||||||
|
{
|
||||||
|
InitializeNoise(grid);
|
||||||
|
|
||||||
|
// Step 1: Pre-place rooms based on noise peaks
|
||||||
|
for (int z = 0; z < grid.Depth; z++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < grid.Width; x++)
|
||||||
|
{
|
||||||
|
float noise = GetNoiseAt(x, z, grid.Width);
|
||||||
|
if (noise > RoomThreshold)
|
||||||
|
{
|
||||||
|
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Run recursive carving in the "connectable" zones
|
||||||
|
// We start from a few points to ensure coverage
|
||||||
|
for (int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
int startX = Random.Range(1, grid.Width - 1);
|
||||||
|
int startZ = Random.Range(1, grid.Depth - 1);
|
||||||
|
GenerateRecursive(grid, startX, startZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator GenerateStepByStep(MazeGrid grid, float interval)
|
||||||
|
{
|
||||||
|
InitializeNoise(grid);
|
||||||
|
|
||||||
|
// Visual feedback for noise pre-placement
|
||||||
|
for (int z = 0; z < grid.Depth; z++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < grid.Width; x++)
|
||||||
|
{
|
||||||
|
float noise = GetNoiseAt(x, z, grid.Width);
|
||||||
|
if (noise > RoomThreshold)
|
||||||
|
{
|
||||||
|
grid.SetCell(x, z, MazeCellType.Processing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (z % 5 == 0) yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int z = 0; z < grid.Depth; z++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < grid.Width; x++)
|
||||||
|
{
|
||||||
|
if (grid.GetCell(x, z) == MazeCellType.Processing)
|
||||||
|
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return GenerateRecursiveStepByStep(grid, 5, 5, interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeNoise(MazeGrid grid)
|
||||||
|
{
|
||||||
|
_noiseMap = new float[grid.Width * grid.Depth];
|
||||||
|
using (var provider = new NativeNoiseProvider(_seed, 0.05f))
|
||||||
|
{
|
||||||
|
if (provider.IsInitialized)
|
||||||
|
{
|
||||||
|
provider.FillBuffer(0, 0, grid.Width, grid.Depth, _noiseMap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback to Unity Perlin
|
||||||
|
for (int z = 0; z < grid.Depth; z++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < grid.Width; x++)
|
||||||
|
{
|
||||||
|
_noiseMap[z * grid.Width + x] = Mathf.PerlinNoise(x * 0.1f, z * 0.1f) * 2f - 1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetNoiseAt(int x, int z, int width)
|
||||||
|
{
|
||||||
|
if (_noiseMap == null) return 0f;
|
||||||
|
return _noiseMap[z * width + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateRecursive(MazeGrid grid, int x, int z)
|
||||||
|
{
|
||||||
|
// Boundary and Noise check
|
||||||
|
if (!grid.IsInBounds(x, z)) return;
|
||||||
|
if (GetNoiseAt(x, z, grid.Width) < CorridorThreshold) return;
|
||||||
|
if (grid.GetCell(x, z) == MazeCellType.Corridor) return;
|
||||||
|
|
||||||
|
if (grid.CountSquareNeighbours(x, z, MazeCellType.Corridor) >= DeadEndNeighbourThreshold) return;
|
||||||
|
|
||||||
|
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||||
|
|
||||||
|
List<MapLocation> shuffledDirs = new List<MapLocation>(_directions);
|
||||||
|
shuffledDirs.Shuffle();
|
||||||
|
|
||||||
|
foreach (var dir in shuffledDirs)
|
||||||
|
{
|
||||||
|
GenerateRecursive(grid, x + dir.x, z + dir.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerator GenerateRecursiveStepByStep(MazeGrid grid, int x, int z, float interval)
|
||||||
|
{
|
||||||
|
if (!grid.IsInBounds(x, z)) yield break;
|
||||||
|
if (GetNoiseAt(x, z, grid.Width) < CorridorThreshold) yield break;
|
||||||
|
if (grid.GetCell(x, z) == MazeCellType.Corridor) yield break;
|
||||||
|
|
||||||
|
if (grid.CountSquareNeighbours(x, z, MazeCellType.Corridor) >= DeadEndNeighbourThreshold) yield break;
|
||||||
|
|
||||||
|
grid.SetCell(x, z, MazeCellType.Processing);
|
||||||
|
if (interval > 0) yield return new WaitForSeconds(interval);
|
||||||
|
|
||||||
|
grid.SetCell(x, z, MazeCellType.Corridor);
|
||||||
|
|
||||||
|
List<MapLocation> shuffledDirs = new List<MapLocation>(_directions);
|
||||||
|
shuffledDirs.Shuffle();
|
||||||
|
|
||||||
|
foreach (var dir in shuffledDirs)
|
||||||
|
{
|
||||||
|
yield return GenerateRecursiveStepByStep(grid, x + dir.x, z + dir.z, interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 22e17049420e98f43a692fd3e7d7d261
|
||||||
Reference in New Issue
Block a user