This commit is contained in:
2026-06-26 02:04:50 +07:00
parent 4fa3fb2c15
commit e0d2b83bd1
16 changed files with 94725 additions and 66906 deletions

View File

@@ -1,75 +0,0 @@
{
"itemReferences": [
{
"amount": 1,
"id": 10,
"attributes": [
{
"name": 2,
"value": 36,
"isOpen": false,
"isBool": false
},
{
"name": 6,
"value": 8,
"isOpen": false,
"isBool": false
}
]
}
],
"equipAreas": [
{
"slotsData": [
{
"hasItem": true,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
}
],
"indexOfSelectedSlot": 0
},
{
"slotsData": [
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
}
],
"indexOfSelectedSlot": 0
},
{
"slotsData": [
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
},
{
"hasItem": false,
"indexOfItem": 0
}
],
"indexOfSelectedSlot": 0
}
]
}

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 483c40951adc9304e9b7eb93949ca573
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 5406a61fe100b3c439cfe3758f1fc27a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -1,242 +0,0 @@
fileFormatVersion: 2
guid: 08e51b23346827c44b016cb3d26fbbcc
ModelImporter:
serializedVersion: 21202
internalIDToNameTable: []
externalObjects:
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Coins_1
second: {fileID: 2100000, guid: 9a8856d5fe5ba2744bfa0599b6a3942b, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Coins_2
second: {fileID: 2100000, guid: 89a51571414879b43ab9c80460f4f28c, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Gem_1
second: {fileID: 2100000, guid: 11e4cd284e404c94da38dad9f7133ec4, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Gem_2
second: {fileID: 2100000, guid: 91b6a46b6114c3f46a9bbd586c781a24, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Gem_3
second: {fileID: 2100000, guid: 6724d458b7297e94b9cbbde94a44defb, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest
second: {fileID: 2100000, guid: b3983a4b16228e74f87bf58f1ccea446, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_1_1
second: {fileID: 2100000, guid: 46a32cda757f20149bf12e9ca51cfbb2, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_1_2
second: {fileID: 2100000, guid: 28c1d315d235bed4cb55d60c34796221, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_1_3
second: {fileID: 2100000, guid: 045cf2b3e47d6fd448854552c89a9917, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_1_4
second: {fileID: 2100000, guid: 99db74b129011a546a25bc30433010a5, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_2_1
second: {fileID: 2100000, guid: baee22647928c7b46aba1baa64df55be, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_2_2
second: {fileID: 2100000, guid: 5838bc34ca5dc0643a092941693e5ea7, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_2_3
second: {fileID: 2100000, guid: 3993c8edfded0fe40a05a6e267203f9c, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_2_4
second: {fileID: 2100000, guid: d5376b505f9c09b409633d1e8af20bbb, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_3_1
second: {fileID: 2100000, guid: 78c6981d17edc2c43abaac5f512419d3, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_3_2
second: {fileID: 2100000, guid: 7d583cb3a63015441a516b612b69b8e6, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_3_3
second: {fileID: 2100000, guid: 665894e14a45295428b2d253fa81ed5d, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_3_4
second: {fileID: 2100000, guid: 7d132b3dfd53cb3409b94971fc69bc79, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_4_1
second: {fileID: 2100000, guid: ce6cf67dce6dd9247b19a8ca01d027df, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_4_2
second: {fileID: 2100000, guid: 5baefc1d9506f3c4baded98c43884d0a, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_4_3
second: {fileID: 2100000, guid: 2e168758f2e461d43bb947334ffa0ce3, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_4_4
second: {fileID: 2100000, guid: 09c9e31516ca54749b5523526afe1081, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_5_1
second: {fileID: 2100000, guid: bfdcb9cfe97f7ae47b6b0094830c6d07, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_5_2
second: {fileID: 2100000, guid: 2799dfc2ffc4c154497171da4796017c, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_5_3
second: {fileID: 2100000, guid: c61b2c24544b0744d8e979472877c0ec, type: 2}
- first:
type: UnityEngine:Material
assembly: UnityEngine.CoreModule
name: Treasure Chest_5_4
second: {fileID: 2100000, guid: 08bc96c63c146bd4fb8f00c6844c53b4, type: 2}
materials:
materialImportMode: 2
materialName: 0
materialSearch: 1
materialLocation: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
removeConstantScaleCurves: 1
motionNodeName:
rigImportErrors:
rigImportWarnings:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
useSRGBMaterialColor: 1
sortHierarchyByName: 1
importVisibility: 1
importBlendShapes: 1
importCameras: 1
importLights: 1
nodeNameCollisionStrategy: 1
fileIdsGeneration: 2
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
keepQuads: 0
weldVertices: 1
bakeAxisConversion: 0
preserveHierarchy: 0
skinWeightsMode: 0
maxBonesPerVertex: 4
minBoneWeight: 0.001
optimizeBones: 1
meshOptimizationFlags: -1
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVMarginMethod: 1
secondaryUVMinLightmapResolution: 40
secondaryUVMinObjectScale: 1
secondaryUVPackMargin: 4
useFileScale: 1
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
blendShapeNormalImportMode: 1
normalSmoothingSource: 0
referencedClips: []
importAnimation: 0
humanDescription:
serializedVersion: 3
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
globalScale: 1
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 1
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
autoGenerateAvatarMappingIfUnspecified: 1
animationType: 0
humanoidOversampling: 1
avatarSetup: 0
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 280107
packageName: POLY STYLE - Fantasy Treasure Chest
packageVersion: 1.15
assetPath: Assets/POLY STYLE - Fantasy Treasure Chest/Fantasy Treasure Chest_URP/Art/Meshes/Chest/Meshes.fbx
uploadId: 651570

View File

@@ -16,18 +16,24 @@ MonoBehaviour:
cornerOffset: 180
deadEndOffset: 0
stairsOffset: 180
wallPrefab: {fileID: 865692088774546613, guid: c49f25c5b1c3e4b43a2bc56717387124, type: 3}
corridorPrefab: {fileID: 919132149155446097, guid: 31c4154f4868c31419e8c1be5681fea1, type: 3}
processingPrefab: {fileID: 1560533784803380970, guid: 1e8b6ed6b01405e4b9e358abc8f7a058, type: 3}
pathPrefab: {fileID: 0}
startPrefab: {fileID: 0}
endPrefab: {fileID: 0}
stairUpPrefab: {fileID: 931007308557375819, guid: 0ebe74534e32a164aa6bf410d377bf86, type: 3}
stairDownPrefab: {fileID: 919132149155446097, guid: 0d3d98145a7d95240aaa356b16f42c5d, type: 3}
corridorStraight: {fileID: 919132149155446097, guid: 31c4154f4868c31419e8c1be5681fea1, type: 3}
corridorCorner: {fileID: 919132149155446097, guid: 9a0138c4a172272478edaf689ad99cb3, type: 3}
corridorTJunction: {fileID: 919132149155446097, guid: 7957821753825954a8aad1fa25d0c745, type: 3}
corridorCross: {fileID: 919132149155446097, guid: 1cf27220912cd864db887717648aef89, type: 3}
corridorDeadEnd: {fileID: 919132149155446097, guid: b5922ad5a43ff5944bff949bf0f742b8, type: 3}
wallPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
corridorPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
processingPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
pathPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
startPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
endPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
stairUpPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
stairDownPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
corridorStraight: {fileID: 1264748121136002, guid: 1652aa5a752a65148a198afb1c8933d2, type: 3}
corridorCorner: {fileID: 1031289983165790, guid: 27b5bfd692a61f64f92a875a55f28376, type: 3}
corridorTJunction: {fileID: 1907757158894496, guid: 95d0988761bfc144e9325a126719df2b, type: 3}
corridorCross: {fileID: 1031289983165790, guid: 27b5bfd692a61f64f92a875a55f28376, type: 3}
corridorDeadEnd: {fileID: 1432061068797346, guid: c64b847edeb2eb94da5ba81384d3f8fc, type: 3}
roomFloorPrefab: {fileID: 1392295376913288, guid: 68316adad77ca6b4abdd0cc62cb4ba24, type: 3}
roomWallPrefab: {fileID: 1703145814520204, guid: 831ba33ea3bd614499bcbc3e5b9188b8, type: 3}
roomCeilingPrefab: {fileID: 1811263594973386, guid: 00bce47c2b02a1e49928328f8a27c7cd, type: 3}
roomDoorwayPrefab: {fileID: 1863703931977514, guid: b484ab835d98f164492ed07a36da9fd6, type: 3}
scale: 1
nodeSpacing: 20
deadEndShift: 1
animationDuration: 1000

View File

@@ -0,0 +1,39 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d3ff96571406a624381b7b0e596a4d1b, type: 3}
m_Name: TestMazeProfile
m_EditorClassIdentifier: Assembly-CSharp::Hallucinate.GameSetup.Maze.MazeVisualProfile
tJunctionOffset: 0
cornerOffset: 180
deadEndOffset: 0
stairsOffset: 180
wallPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
corridorPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
processingPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
pathPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
startPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
endPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
stairUpPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
stairDownPrefab: {fileID: 100000, guid: 8fb11e307b50ccc42a39120e3c49b4a1, type: 3}
corridorStraight: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
corridorCorner: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
corridorTJunction: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
corridorCross: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
corridorDeadEnd: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
roomFloorPrefab: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
roomWallPrefab: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
roomCeilingPrefab: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
roomDoorwayPrefab: {fileID: 1232322618620288, guid: d31379ea41af1e14184ac8deaa704fcf, type: 3}
scale: 1
nodeSpacing: 20
deadEndShift: 1
animationDuration: 1000

View File

@@ -1,7 +1,8 @@
fileFormatVersion: 2
guid: 760274f8c30c80848a1fb1c5dc64a2d5
TextScriptImporter:
guid: 3886a13498ec73b4bbc588f8c60d2c31
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,8 @@ namespace Hallucinate.GameSetup.Maze
Start, // Entry point
End, // Exit point
StairsUp,
StairsDown
StairsDown,
Room
}
public enum PieceType
{

View File

@@ -61,6 +61,18 @@ namespace Hallucinate.GameSetup.Maze
[Required]
[SerializeField] private MazeRenderer mazeRenderer;
[BoxGroup("Rooms (Phase 2)")]
public bool generateRooms = true;
[BoxGroup("Rooms (Phase 2)")]
[ShowIf(nameof(generateRooms))]
public int numberOfRooms = 2;
[BoxGroup("Rooms (Phase 2)")]
[ShowIf(nameof(generateRooms))]
public Vector2Int minRoomSize = new Vector2Int(2, 2);
[BoxGroup("Rooms (Phase 2)")]
[ShowIf(nameof(generateRooms))]
public Vector2Int maxRoomSize = new Vector2Int(4, 4);
[BoxGroup("References")]
[Required]
[SerializeField] private Transform mazeContainer;
@@ -165,6 +177,8 @@ namespace Hallucinate.GameSetup.Maze
mazes[i] = new MazeGrid(width, depth);
mazes[i].Level = i;
CarveRooms(mazes[i]);
IMazeAlgorithm algorithmForFloor = GetAlgorithm(selectedAlgorithm);
algorithmForFloor.Generate(mazes[i]);
}
@@ -203,6 +217,7 @@ namespace Hallucinate.GameSetup.Maze
}
};
CarveRooms(mazes[i]);
mazeRenderer.Initialize(mazes[i], mazeContainer, i == 0);
IMazeAlgorithm algorithmForFloor = GetAlgorithm(selectedAlgorithm);
@@ -262,6 +277,42 @@ namespace Hallucinate.GameSetup.Maze
}
}
private void CarveRooms(MazeGrid grid)
{
if (!generateRooms) return;
for (int i = 0; i < numberOfRooms; i++)
{
int w = Random.Range(minRoomSize.x, maxRoomSize.x + 1);
int d = Random.Range(minRoomSize.y, maxRoomSize.y + 1);
int startX = Random.Range(1, width - w - 1);
int startZ = Random.Range(1, depth - d - 1);
for (int x = startX; x < startX + w; x++)
{
for (int z = startZ; z < startZ + d; z++)
{
grid.SetCell(x, z, MazeCellType.Room);
}
}
// Carve guaranteed door to seed pathfinding
if (Random.value > 0.5f)
{
int doorX = Random.Range(startX, startX + w);
int doorZ = Random.value > 0.5f ? startZ + d : startZ - 1;
grid.SetCell(doorX, doorZ, MazeCellType.Corridor);
}
else
{
int doorX = Random.value > 0.5f ? startX + w : startX - 1;
int doorZ = Random.Range(startZ, startZ + d);
grid.SetCell(doorX, doorZ, MazeCellType.Corridor);
}
}
}
private void ShuffleList<T>(List<T> list)
{
for (int i = 0; i < list.Count; i++)

View File

@@ -139,48 +139,143 @@ namespace Hallucinate.GameSetup.Maze
_spawnedCells.Remove(posKey);
}
GameObject prefab = null;
Quaternion rotation = Quaternion.identity;
if (type == MazeCellType.Wall) return;
if (type == MazeCellType.Corridor || type == MazeCellType.Processing)
float logicalSpacing = visualProfile.nodeSpacing; // Distances between Nodes
float halfSpacing = logicalSpacing / 2f;
float safeScale = Mathf.Max(0.001f, visualProfile.scale);
float spacingScale = logicalSpacing * safeScale;
float yOffset = grid.Level * floorHeight;
Vector3 localPos = new Vector3(x * spacingScale, yOffset, z * spacingScale);
GameObject cellParent = new GameObject($"Cell_{x}_{grid.Level}_{z}");
cellParent.transform.SetParent(_container);
cellParent.transform.localPosition = localPos;
bool spawnedAnything = false;
if (type == MazeCellType.Corridor || type == MazeCellType.Processing || type == MazeCellType.StairsUp || type == MazeCellType.StairsDown)
{
(prefab, rotation) = GetCorridorPrefabAndRotation(grid, x, z);
// 1. Spawn Node (Intersection, Corner, T, DeadEnd, or Stairs)
GameObject nodePrefab;
Quaternion nodeRot;
Vector3 nodeOffset = Vector3.zero;
if (type == MazeCellType.StairsUp || type == MazeCellType.StairsDown)
{
nodePrefab = visualProfile.GetPrefab(type);
nodeRot = Quaternion.Euler(0, visualProfile.stairsOffset, 0);
}
else
{
(nodePrefab, nodeRot, nodeOffset) = GetNodePrefabAndRotation(grid, x, z);
}
if (nodePrefab != null)
{
GameObject node = Instantiate(nodePrefab, cellParent.transform);
node.transform.localPosition = nodeOffset * safeScale;
node.transform.localRotation = nodeRot;
node.transform.localScale = Vector3.one * safeScale;
spawnedAnything = true;
}
// 2. Spawn Edge X (Right path)
if (IsPath(grid, x + 1, z))
{
GameObject edgePrefab = visualProfile.corridorStraight;
if (edgePrefab != null)
{
GameObject edgeX = Instantiate(edgePrefab, cellParent.transform);
edgeX.transform.localPosition = new Vector3(halfSpacing * safeScale, 0, 0); // half units offset right
edgeX.transform.localRotation = Quaternion.Euler(0, 90f, 0); // pointing along X
edgeX.transform.localScale = Vector3.one * safeScale;
spawnedAnything = true;
}
}
// 3. Spawn Edge Z (Top path)
if (IsPath(grid, x, z + 1))
{
GameObject edgePrefab = visualProfile.corridorStraight;
if (edgePrefab != null)
{
GameObject edgeZ = Instantiate(edgePrefab, cellParent.transform);
edgeZ.transform.localPosition = new Vector3(0, 0, halfSpacing * safeScale); // half units offset forward
edgeZ.transform.localRotation = Quaternion.identity; // pointing along Z
edgeZ.transform.localScale = Vector3.one * safeScale;
spawnedAnything = true;
}
}
}
else if (type == MazeCellType.Room)
{
// Spawn Floor
if (visualProfile.roomFloorPrefab != null)
{
GameObject floor = Instantiate(visualProfile.roomFloorPrefab, cellParent.transform);
floor.transform.localPosition = Vector3.zero;
floor.transform.localScale = Vector3.one * safeScale;
spawnedAnything = true;
}
// Spawn Ceiling
if (visualProfile.roomCeilingPrefab != null)
{
GameObject ceiling = Instantiate(visualProfile.roomCeilingPrefab, cellParent.transform);
ceiling.transform.localPosition = new Vector3(0, floorHeight, 0);
ceiling.transform.localScale = Vector3.one * safeScale;
spawnedAnything = true;
}
// Spawn Room Edges (Walls or Doors)
MazeCellType top = grid.IsInBounds(x, z + 1) ? grid.GetCell(x, z + 1) : MazeCellType.Wall;
SpawnRoomEdge(cellParent, top, new Vector3(0, 0, halfSpacing * safeScale), 0f, safeScale);
MazeCellType right = grid.IsInBounds(x + 1, z) ? grid.GetCell(x + 1, z) : MazeCellType.Wall;
SpawnRoomEdge(cellParent, right, new Vector3(halfSpacing * safeScale, 0, 0), 90f, safeScale);
MazeCellType bottom = grid.IsInBounds(x, z - 1) ? grid.GetCell(x, z - 1) : MazeCellType.Wall;
SpawnRoomEdge(cellParent, bottom, new Vector3(0, 0, -halfSpacing * safeScale), 180f, safeScale);
MazeCellType left = grid.IsInBounds(x - 1, z) ? grid.GetCell(x - 1, z) : MazeCellType.Wall;
SpawnRoomEdge(cellParent, left, new Vector3(-halfSpacing * safeScale, 0, 0), 270f, safeScale);
spawnedAnything = true; // Always true if it reaches here
}
else
{
prefab = visualProfile.GetPrefab(type);
if (type == MazeCellType.StairsUp || type == MazeCellType.StairsDown)
// Non-corridor logic (Start, End, etc)
GameObject prefab = visualProfile.GetPrefab(type);
if (prefab != null)
{
rotation = Quaternion.Euler(0, visualProfile.stairsOffset, 0);
GameObject obj = Instantiate(prefab, cellParent.transform);
obj.transform.localPosition = Vector3.zero;
obj.transform.localRotation = Quaternion.identity;
obj.transform.localScale = Vector3.one * safeScale;
spawnedAnything = true;
}
}
if (prefab == null) return;
if (!spawnedAnything)
{
DestroyImmediate(cellParent);
return;
}
float safeScale = Mathf.Max(0.001f, visualProfile.scale);
float modelScaleMultiplier = 1f;
float yOffset = grid.Level * floorHeight;
Vector3 localPos = new Vector3(x * safeScale, yOffset, z * safeScale);
GameObject newObj = Instantiate(prefab, _container);
newObj.transform.localPosition = localPos;
newObj.transform.localRotation = rotation;
newObj.transform.localScale = Vector3.one * safeScale * modelScaleMultiplier;
_spawnedCells[posKey] = newObj;
_spawnedCells[posKey] = cellParent;
if (animate && visualProfile.animationDuration > 0)
{
StartCoroutine(AnimateCell(newObj.transform));
StartCoroutine(AnimateCell(cellParent.transform));
}
}
// =================================================================================
// THUẬT TOÁN BITMASK AUTO-TILING
// =================================================================================
private (GameObject, Quaternion) GetCorridorPrefabAndRotation(MazeGrid grid, int x, int z)
private (GameObject, Quaternion, Vector3) GetNodePrefabAndRotation(MazeGrid grid, int x, int z)
{
bool top = IsPath(grid, x, z + 1);
bool right = IsPath(grid, x + 1, z);
@@ -195,24 +290,32 @@ namespace Hallucinate.GameSetup.Maze
GameObject prefabToSpawn = null;
float yRotation = 0f;
Vector3 offset = Vector3.zero;
// Push dead ends to the boundary where edges end
float endOffset = visualProfile.deadEndShift;
switch (mask)
{
case 1:
prefabToSpawn = visualProfile.corridorDeadEnd;
yRotation = 180f;
yRotation = 0f;
offset = new Vector3(0, 0, endOffset);
break;
case 2:
prefabToSpawn = visualProfile.corridorDeadEnd;
yRotation = 270f;
yRotation = 90f;
offset = new Vector3(endOffset, 0, 0);
break;
case 4:
prefabToSpawn = visualProfile.corridorDeadEnd;
yRotation = 0f;
yRotation = 180f;
offset = new Vector3(0, 0, -endOffset);
break;
case 8:
prefabToSpawn = visualProfile.corridorDeadEnd;
yRotation = 90f;
yRotation = 270f;
offset = new Vector3(-endOffset, 0, 0);
break;
case 5:
@@ -243,19 +346,19 @@ namespace Hallucinate.GameSetup.Maze
case 11:
prefabToSpawn = visualProfile.corridorTJunction;
yRotation = 180f;
yRotation = 0f;
break;
case 7:
prefabToSpawn = visualProfile.corridorTJunction;
yRotation = 270f;
yRotation = 90f;
break;
case 14:
prefabToSpawn = visualProfile.corridorTJunction;
yRotation = 0f;
yRotation = 180f;
break;
case 13:
prefabToSpawn = visualProfile.corridorTJunction;
yRotation = 90f;
yRotation = 270f;
break;
case 15:
@@ -276,7 +379,32 @@ namespace Hallucinate.GameSetup.Maze
if (prefabToSpawn == null) prefabToSpawn = visualProfile.corridorPrefab;
return (prefabToSpawn, Quaternion.Euler(0, finalRotation, 0));
return (prefabToSpawn, Quaternion.Euler(0, finalRotation, 0), offset);
}
private void SpawnRoomEdge(GameObject parent, MazeCellType neighborType, Vector3 offset, float yRot, float safeScale)
{
if (neighborType == MazeCellType.Room)
return; // Open space to another room cell
GameObject prefabToSpawn = null;
if (neighborType == MazeCellType.Corridor || neighborType == MazeCellType.Processing || neighborType == MazeCellType.Start || neighborType == MazeCellType.End)
{
prefabToSpawn = visualProfile.roomDoorwayPrefab;
}
else
{
prefabToSpawn = visualProfile.roomWallPrefab;
}
if (prefabToSpawn != null)
{
GameObject edge = Instantiate(prefabToSpawn, parent.transform);
edge.transform.localPosition = offset;
edge.transform.localRotation = Quaternion.Euler(0, yRot, 0);
edge.transform.localScale = Vector3.one * safeScale;
}
}
private bool IsPath(MazeGrid grid, int x, int z)

View File

@@ -66,10 +66,28 @@ namespace Hallucinate.GameSetup.Maze
[Required]
public GameObject corridorDeadEnd;
[BoxGroup("Room Pieces (Phase 2)")]
public GameObject roomFloorPrefab;
[BoxGroup("Room Pieces (Phase 2)")]
public GameObject roomWallPrefab;
[BoxGroup("Room Pieces (Phase 2)")]
public GameObject roomCeilingPrefab;
[BoxGroup("Room Pieces (Phase 2)")]
public GameObject roomDoorwayPrefab;
[BoxGroup("Visualization")]
[MinValue(0.001f)]
public float scale = 0.167f;
[BoxGroup("Visualization")]
[MinValue(1f)]
[InfoBox("The physical distance between each grid cell. Default is 6 based on 3x3 intersections and 3x2 halls.")]
public float nodeSpacing = 6f;
[BoxGroup("Visualization")]
[InfoBox("How far to push dead-end caps from the center so they touch the hallway edge. Default is 1.0.")]
public float deadEndShift = 1.0f;
[BoxGroup("Visualization")]
[MinValue(0f)]
public float animationDuration = 0.25f;

View File

@@ -109,8 +109,8 @@ namespace Hallucinate.GameSetup.Maze
private void GenerateRecursive(MazeGrid grid, int x, int z)
{
// Boundary and Noise check
if (!grid.IsInBounds(x, z)) return;
if (grid.GetCell(x, z) != MazeCellType.Wall) return;
if (GetNoiseAt(x, z, grid.Width) < CorridorThreshold) return;
if (grid.GetCell(x, z) == MazeCellType.Corridor) return;
@@ -130,6 +130,7 @@ namespace Hallucinate.GameSetup.Maze
private IEnumerator GenerateRecursiveStepByStep(MazeGrid grid, int x, int z, int cellsPerFrame)
{
if (!grid.IsInBounds(x, z)) yield break;
if (grid.GetCell(x, z) != MazeCellType.Wall) yield break;
if (GetNoiseAt(x, z, grid.Width) < CorridorThreshold) yield break;
if (grid.GetCell(x, z) == MazeCellType.Corridor) yield break;

View File

@@ -25,6 +25,7 @@ namespace Hallucinate.GameSetup.Maze
private void GenerateRecursive(MazeGrid grid, int x, int z)
{
if (grid.GetCell(x, z) != MazeCellType.Wall) return;
if (grid.CountSquareNeighbours(x, z, MazeCellType.Corridor) >= DeadEndNeighbourThreshold) return;
grid.SetCell(x, z, MazeCellType.Corridor);
@@ -45,6 +46,7 @@ namespace Hallucinate.GameSetup.Maze
private IEnumerator GenerateRecursiveStepByStep(MazeGrid grid, int x, int z, int cellsPerFrame)
{
if (grid.GetCell(x, z) != MazeCellType.Wall) yield break;
if (grid.CountSquareNeighbours(x, z, MazeCellType.Corridor) >= DeadEndNeighbourThreshold) yield break;
grid.SetCell(x, z, MazeCellType.Processing);