diff --git a/.idea/.idea.BABA_YAGA/.idea/workspace.xml b/.idea/.idea.BABA_YAGA/.idea/workspace.xml
index 24fd8087..88bfb4db 100644
--- a/.idea/.idea.BABA_YAGA/.idea/workspace.xml
+++ b/.idea/.idea.BABA_YAGA/.idea/workspace.xml
@@ -12,19 +12,17 @@
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
@@ -48,6 +46,10 @@
+
+
diff --git a/Assets/Materials/Transparency.mat b/Assets/Materials/Red 1.mat
similarity index 87%
rename from Assets/Materials/Transparency.mat
rename to Assets/Materials/Red 1.mat
index 0e5f621d..5b8fdeb0 100644
--- a/Assets/Materials/Transparency.mat
+++ b/Assets/Materials/Red 1.mat
@@ -7,22 +7,27 @@ Material:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_Name: Transparency
+ m_Name: Red 1
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
+ - _ALPHAPREMULTIPLY_ON
+ - _EMISSION
- _ENVIRONMENTREFLECTIONS_OFF
+ - _SURFACE_TYPE_TRANSPARENT
m_InvalidKeywords:
- _GLOSSYREFLECTIONS_OFF
- m_LightmapFlags: 4
+ m_LightmapFlags: 1
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
- m_CustomRenderQueue: 2000
+ m_CustomRenderQueue: 3000
stringTagMap:
- RenderType: Opaque
+ RenderType: Transparent
disabledShaderPasses:
- MOTIONVECTORS
+ - DepthOnly
+ - SHADOWCASTER
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
@@ -97,36 +102,36 @@ Material:
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _DstBlendAlpha: 0
+ - _DstBlend: 10
+ - _DstBlendAlpha: 10
- _EnvironmentReflections: 0
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- - _Metallic: 0
+ - _Metallic: 1
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- - _Smoothness: 0
+ - _Smoothness: 0.485
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- - _Surface: 0
+ - _Surface: 1
- _UVSec: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- - _ZWrite: 1
+ - _ZWrite: 0
m_Colors:
- - _BaseColor: {r: 0.6462264, g: 1, b: 0.90943396, a: 1}
- - _Color: {r: 0.6462264, g: 1, b: 0.90943396, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
+ - _BaseColor: {r: 1, g: 0, b: 0, a: 0.54509807}
+ - _Color: {r: 1, g: 0, b: 0, a: 0.54509807}
+ - _EmissionColor: {r: 0.4433962, g: 0, b: 0.035386458, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
---- !u!114 &7323331776208790253
+--- !u!114 &4579113440628220621
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
diff --git a/Assets/Materials/Separator.mat.meta b/Assets/Materials/Red 1.mat.meta
similarity index 79%
rename from Assets/Materials/Separator.mat.meta
rename to Assets/Materials/Red 1.mat.meta
index b5a9ba1b..f192ad39 100644
--- a/Assets/Materials/Separator.mat.meta
+++ b/Assets/Materials/Red 1.mat.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: b0a84576fc378a24cbb3bfc7be45a02e
+guid: 4e2761c702df38044a3b33cb36bdabf4
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
diff --git a/Assets/Materials/Separator.mat b/Assets/Materials/Red 2.mat
similarity index 86%
rename from Assets/Materials/Separator.mat
rename to Assets/Materials/Red 2.mat
index 68711ec5..97ed2e35 100644
--- a/Assets/Materials/Separator.mat
+++ b/Assets/Materials/Red 2.mat
@@ -7,21 +7,26 @@ Material:
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
- m_Name: Separator
+ m_Name: Red 2
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
- m_ValidKeywords: []
+ m_ValidKeywords:
+ - _ALPHAPREMULTIPLY_ON
+ - _EMISSION
+ - _ENVIRONMENTREFLECTIONS_OFF
+ - _SURFACE_TYPE_TRANSPARENT
m_InvalidKeywords:
- _GLOSSYREFLECTIONS_OFF
- m_LightmapFlags: 4
+ m_LightmapFlags: 1
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
- m_CustomRenderQueue: 2000
+ m_CustomRenderQueue: 3000
stringTagMap:
- RenderType: Opaque
+ RenderType: Transparent
disabledShaderPasses:
- MOTIONVECTORS
+ - DepthOnly
- SHADOWCASTER
m_LockedProperties:
m_SavedProperties:
@@ -97,36 +102,36 @@ Material:
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _DstBlendAlpha: 0
+ - _DstBlend: 10
+ - _DstBlendAlpha: 10
- _EnvironmentReflections: 0
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- - _Metallic: 0
+ - _Metallic: 1
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- - _Smoothness: 0
+ - _Smoothness: 0.485
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- - _Surface: 0
+ - _Surface: 1
- _UVSec: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- - _ZWrite: 1
+ - _ZWrite: 0
m_Colors:
- - _BaseColor: {r: 1, g: 0, b: 0, a: 0.5686275}
- - _Color: {r: 1, g: 0, b: 0, a: 0.5686275}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
+ - _BaseColor: {r: 1, g: 0, b: 0, a: 0.54509807}
+ - _Color: {r: 1, g: 0, b: 0, a: 0.54509807}
+ - _EmissionColor: {r: 0.4433962, g: 0, b: 0.035386458, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
---- !u!114 &9152226916650191239
+--- !u!114 &4579113440628220621
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
diff --git a/Assets/Materials/Transparency.mat.meta b/Assets/Materials/Red 2.mat.meta
similarity index 79%
rename from Assets/Materials/Transparency.mat.meta
rename to Assets/Materials/Red 2.mat.meta
index 3b3b2510..90dcc5fb 100644
--- a/Assets/Materials/Transparency.mat.meta
+++ b/Assets/Materials/Red 2.mat.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: d7e691e02b41b9a47b417cc138d6f1bc
+guid: c2de57284d214404394d08e4b5f50372
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
diff --git a/Assets/Materials/Red.mat b/Assets/Materials/Red.mat
index 9650f183..a9d7cec1 100644
--- a/Assets/Materials/Red.mat
+++ b/Assets/Materials/Red.mat
@@ -11,17 +11,23 @@ Material:
m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
- m_ValidKeywords: []
+ m_ValidKeywords:
+ - _ALPHAPREMULTIPLY_ON
+ - _EMISSION
+ - _ENVIRONMENTREFLECTIONS_OFF
+ - _SURFACE_TYPE_TRANSPARENT
m_InvalidKeywords:
- _GLOSSYREFLECTIONS_OFF
- m_LightmapFlags: 4
+ m_LightmapFlags: 1
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
- m_CustomRenderQueue: -1
+ m_CustomRenderQueue: 3000
stringTagMap:
- RenderType: Opaque
+ RenderType: Transparent
disabledShaderPasses:
- MOTIONVECTORS
+ - DepthOnly
+ - SHADOWCASTER
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
@@ -96,32 +102,32 @@ Material:
- _Cutoff: 0.5
- _DetailAlbedoMapScale: 1
- _DetailNormalMapScale: 1
- - _DstBlend: 0
- - _DstBlendAlpha: 0
+ - _DstBlend: 10
+ - _DstBlendAlpha: 10
- _EnvironmentReflections: 0
- _GlossMapScale: 0
- _Glossiness: 0
- _GlossyReflections: 0
- - _Metallic: 0
+ - _Metallic: 1
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.005
- _QueueOffset: 0
- _ReceiveShadows: 1
- - _Smoothness: 0
+ - _Smoothness: 0.485
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SrcBlendAlpha: 1
- - _Surface: 0
+ - _Surface: 1
- _UVSec: 0
- _WorkflowMode: 1
- _XRMotionVectorsPass: 1
- - _ZWrite: 1
+ - _ZWrite: 0
m_Colors:
- - _BaseColor: {r: 1, g: 0, b: 0, a: 1}
- - _Color: {r: 1, g: 0, b: 0, a: 1}
- - _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
+ - _BaseColor: {r: 1, g: 0, b: 0, a: 0.54509807}
+ - _Color: {r: 1, g: 0, b: 0, a: 0.54509807}
+ - _EmissionColor: {r: 0.4433962, g: 0, b: 0.035386458, a: 1}
- _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1
diff --git a/Assets/Prefabs/Environment/Hall/MazeVisualize 1 1.prefab b/Assets/Prefabs/Environment/Hall/MazeVisualize 1 1.prefab
new file mode 100644
index 00000000..365d68d9
--- /dev/null
+++ b/Assets/Prefabs/Environment/Hall/MazeVisualize 1 1.prefab
@@ -0,0 +1,63 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &8524974212353532561
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ serializedVersion: 3
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3172752473709046689, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 3276807805808399797, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: 'm_Materials.Array.data[0]'
+ value:
+ objectReference: {fileID: 2100000, guid: c2de57284d214404394d08e4b5f50372, type: 2}
+ - target: {fileID: 7410088413158269499, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
+ propertyPath: m_Name
+ value: MazeVisualize 1 1
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_RemovedGameObjects: []
+ m_AddedGameObjects: []
+ m_AddedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: 17f01b6b44475394da68b1ca1d8d7eb4, type: 3}
diff --git a/Assets/Prefabs/Environment/Hall/MazeVisualize 1 1.prefab.meta b/Assets/Prefabs/Environment/Hall/MazeVisualize 1 1.prefab.meta
new file mode 100644
index 00000000..695a3c49
--- /dev/null
+++ b/Assets/Prefabs/Environment/Hall/MazeVisualize 1 1.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: c39adeeb3a17d824392cc018d65aedc4
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Prefabs/Environment/Hall/MazeVisualize 1.prefab b/Assets/Prefabs/Environment/Hall/MazeVisualize 1.prefab
new file mode 100644
index 00000000..c80ddca8
--- /dev/null
+++ b/Assets/Prefabs/Environment/Hall/MazeVisualize 1.prefab
@@ -0,0 +1,63 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1001 &4042319629769208918
+PrefabInstance:
+ m_ObjectHideFlags: 0
+ serializedVersion: 2
+ m_Modification:
+ serializedVersion: 3
+ m_TransformParent: {fileID: 0}
+ m_Modifications:
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalPosition.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalPosition.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalPosition.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalRotation.w
+ value: 1
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalRotation.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalRotation.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalRotation.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.x
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.y
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1449831261723959287, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_LocalEulerAnglesHint.z
+ value: 0
+ objectReference: {fileID: 0}
+ - target: {fileID: 1540436817844937187, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: 'm_Materials.Array.data[0]'
+ value:
+ objectReference: {fileID: 2100000, guid: 4e2761c702df38044a3b33cb36bdabf4, type: 2}
+ - target: {fileID: 6831072708289238637, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
+ propertyPath: m_Name
+ value: MazeVisualize 1
+ objectReference: {fileID: 0}
+ m_RemovedComponents: []
+ m_RemovedGameObjects: []
+ m_AddedGameObjects: []
+ m_AddedComponents: []
+ m_SourcePrefab: {fileID: 100100000, guid: 085ffdfee17437a4f8e0d3c365edcc24, type: 3}
diff --git a/Assets/Prefabs/Environment/Hall/MazeVisualize 1.prefab.meta b/Assets/Prefabs/Environment/Hall/MazeVisualize 1.prefab.meta
new file mode 100644
index 00000000..7f7865ec
--- /dev/null
+++ b/Assets/Prefabs/Environment/Hall/MazeVisualize 1.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 17f01b6b44475394da68b1ca1d8d7eb4
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Prefabs/Environment/Hall/MazeVisualize.prefab b/Assets/Prefabs/Environment/Hall/MazeVisualize.prefab
new file mode 100644
index 00000000..35a5965f
--- /dev/null
+++ b/Assets/Prefabs/Environment/Hall/MazeVisualize.prefab
@@ -0,0 +1,114 @@
+%YAML 1.1
+%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &6831072708289238637
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1449831261723959287}
+ - component: {fileID: 7162882105187371053}
+ - component: {fileID: 1540436817844937187}
+ - component: {fileID: 1186626314013191963}
+ m_Layer: 0
+ m_Name: MazeVisualize
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1449831261723959287
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6831072708289238637}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 111.06352, y: 0.99998, z: 75.67667}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 0}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!33 &7162882105187371053
+MeshFilter:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6831072708289238637}
+ m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
+--- !u!23 &1540436817844937187
+MeshRenderer:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6831072708289238637}
+ m_Enabled: 1
+ m_CastShadows: 1
+ m_ReceiveShadows: 1
+ m_DynamicOccludee: 1
+ m_StaticShadowCaster: 0
+ m_MotionVectors: 1
+ m_LightProbeUsage: 1
+ m_ReflectionProbeUsage: 1
+ m_RayTracingMode: 2
+ m_RayTraceProcedural: 0
+ m_RayTracingAccelStructBuildFlagsOverride: 0
+ m_RayTracingAccelStructBuildFlags: 1
+ m_SmallMeshCulling: 1
+ m_ForceMeshLod: -1
+ m_MeshLodSelectionBias: 0
+ m_RenderingLayerMask: 1
+ m_RendererPriority: 0
+ m_Materials:
+ - {fileID: 2100000, guid: 9193f4635bbf98d46be9a6357461aa10, type: 2}
+ m_StaticBatchInfo:
+ firstSubMesh: 0
+ subMeshCount: 0
+ m_StaticBatchRoot: {fileID: 0}
+ m_ProbeAnchor: {fileID: 0}
+ m_LightProbeVolumeOverride: {fileID: 0}
+ m_ScaleInLightmap: 1
+ m_ReceiveGI: 1
+ m_PreserveUVs: 0
+ m_IgnoreNormalsForChartDetection: 0
+ m_ImportantGI: 0
+ m_StitchLightmapSeams: 1
+ m_SelectedEditorRenderState: 3
+ m_MinimumChartSize: 4
+ m_AutoUVMaxDistance: 0.5
+ m_AutoUVMaxAngle: 89
+ m_LightmapParameters: {fileID: 0}
+ m_GlobalIlluminationMeshLod: 0
+ m_SortingLayerID: 0
+ m_SortingLayer: 0
+ m_SortingOrder: 0
+ m_MaskInteraction: 0
+ m_AdditionalVertexStreams: {fileID: 0}
+--- !u!65 &1186626314013191963
+BoxCollider:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 6831072708289238637}
+ m_Material: {fileID: 0}
+ m_IncludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_ExcludeLayers:
+ serializedVersion: 2
+ m_Bits: 0
+ m_LayerOverridePriority: 0
+ m_IsTrigger: 0
+ m_ProvidesContacts: 0
+ m_Enabled: 0
+ serializedVersion: 3
+ m_Size: {x: 1, y: 1, z: 1}
+ m_Center: {x: 0, y: 0, z: 0}
diff --git a/Assets/Prefabs/Environment/Hall/MazeVisualize.prefab.meta b/Assets/Prefabs/Environment/Hall/MazeVisualize.prefab.meta
new file mode 100644
index 00000000..c6ca0466
--- /dev/null
+++ b/Assets/Prefabs/Environment/Hall/MazeVisualize.prefab.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 085ffdfee17437a4f8e0d3c365edcc24
+PrefabImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Prefabs/Environment/Hall/MazeRework.asset b/Assets/Presets/MazeRework.asset
similarity index 92%
rename from Assets/Prefabs/Environment/Hall/MazeRework.asset
rename to Assets/Presets/MazeRework.asset
index 16242fe9..037da5e4 100644
--- a/Assets/Prefabs/Environment/Hall/MazeRework.asset
+++ b/Assets/Presets/MazeRework.asset
@@ -12,13 +12,14 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 30892b1102feb6841a9288ddb11ef50d, type: 3}
m_Name: MazeRework
m_EditorClassIdentifier: Assembly-CSharp::Baba_yaga.GameSetup.MazeRework.MazeReworkConfig
- width: 15
- depth: 15
+ algorithm: 3
+ width: 21
+ depth: 21
useRandomSeed: 1
seed: 1337
startLocation: {x: 1, y: 1}
generateRooms: 0
- roomCount: 207
+ roomCount: 378
minRoomSize: {x: 3, y: 3}
maxRoomSize: {x: 5, y: 5}
extraRoomDoorChance: 0.3
diff --git a/Assets/Prefabs/Environment/Hall/MazeRework.asset.meta b/Assets/Presets/MazeRework.asset.meta
similarity index 100%
rename from Assets/Prefabs/Environment/Hall/MazeRework.asset.meta
rename to Assets/Presets/MazeRework.asset.meta
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms.meta
new file mode 100644
index 00000000..8c068543
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 1207eeec52bcfcf4a9a97e054680d844
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSIterative.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSIterative.cs
new file mode 100644
index 00000000..9d08961f
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSIterative.cs
@@ -0,0 +1,76 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Baba_yaga.GameSetup.MazeRework.Algorithms
+{
+ public class DFSIterative : IMazeReworkAlgorithm
+ {
+ public void Carve(
+ MazeReworkCellType[,] grid,
+ bool[,] visited,
+ int startX, int startZ,
+ int width, int depth,
+ System.Random rng,
+ System.Action onCellChanged = null)
+ {
+ Stack stack = new Stack();
+ stack.Push(new Vector2Int(startX, startZ));
+ onCellChanged?.Invoke(startX, startZ, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+
+ int[] dx = { 2, -2, 0, 0 };
+ int[] dz = { 0, 0, 2, -2 };
+
+ while (stack.Count > 0)
+ {
+ Vector2Int current = stack.Peek();
+
+ List candidates = new List(4);
+ for (int i = 0; i < 4; i++)
+ {
+ int nx = current.x + dx[i];
+ int nz = current.y + dz[i];
+ if (nx > 0 && nx < width - 1 && nz > 0 && nz < depth - 1 && !visited[nx, nz])
+ candidates.Add(i);
+ }
+
+ if (candidates.Count > 0)
+ {
+ int pick = candidates[rng.Next(candidates.Count)];
+ int nx2 = current.x + dx[pick];
+ int nz2 = current.y + dz[pick];
+ int wx = current.x + dx[pick] / 2;
+ int wz = current.y + dz[pick] / 2;
+
+ grid[wx, wz] = MazeReworkCellType.Corridor;
+ grid[nx2, nz2] = MazeReworkCellType.Corridor;
+ visited[wx, wz] = true;
+ visited[nx2, nz2] = true;
+
+ // Move head off current cell
+ onCellChanged?.Invoke(current.x, current.y, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+
+ // Show breaking intermediate wall with head
+ onCellChanged?.Invoke(wx, wz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+ onCellChanged?.Invoke(wx, wz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+
+ // Move head to new cell
+ onCellChanged?.Invoke(nx2, nz2, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+
+ stack.Push(new Vector2Int(nx2, nz2));
+ }
+ else
+ {
+ stack.Pop();
+ // Clear head from popped cell
+ onCellChanged?.Invoke(current.x, current.y, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+ // Restore head to new top of stack
+ if (stack.Count > 0)
+ {
+ var nextCurrent = stack.Peek();
+ onCellChanged?.Invoke(nextCurrent.x, nextCurrent.y, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSIterative.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSIterative.cs.meta
new file mode 100644
index 00000000..f76ed1d2
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSIterative.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: cdda5d3deb881154481ad5f60c4bdc0a
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSRecursive.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSRecursive.cs
new file mode 100644
index 00000000..960ff74d
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSRecursive.cs
@@ -0,0 +1,64 @@
+namespace Baba_yaga.GameSetup.MazeRework.Algorithms
+{
+ public class DFSRecursive : IMazeReworkAlgorithm
+ {
+ public void Carve(
+ MazeReworkCellType[,] grid,
+ bool[,] visited,
+ int startX, int startZ,
+ int width, int depth,
+ System.Random rng,
+ System.Action onCellChanged = null)
+ {
+ CarveFrom(startX, startZ, grid, visited, rng, width, depth, onCellChanged);
+ // Clear final head position when completely done
+ onCellChanged?.Invoke(startX, startZ, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+ }
+
+ private void CarveFrom(int cx, int cz, MazeReworkCellType[,] grid, bool[,] visited,
+ System.Random rng, int width, int depth,
+ System.Action onCellChanged)
+ {
+ onCellChanged?.Invoke(cx, cz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+
+ int[] dx = { 2, -2, 0, 0 };
+ int[] dz = { 0, 0, 2, -2 };
+
+ int[] order = { 0, 1, 2, 3 };
+ for (int i = 3; i > 0; i--)
+ {
+ int j = rng.Next(i + 1);
+ int tmp = order[i]; order[i] = order[j]; order[j] = tmp;
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ int nx = cx + dx[order[i]];
+ int nz = cz + dz[order[i]];
+ int wx = cx + dx[order[i]] / 2;
+ int wz = cz + dz[order[i]] / 2;
+
+ if (nx > 0 && nx < width - 1 && nz > 0 && nz < depth - 1 && !visited[nx, nz])
+ {
+ grid[wx, wz] = MazeReworkCellType.Corridor;
+ grid[nx, nz] = MazeReworkCellType.Corridor;
+ visited[wx, wz] = true;
+ visited[nx, nz] = true;
+
+ // Move head off current cell
+ onCellChanged?.Invoke(cx, cz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+
+ // Show intermediate wall breaking with head
+ onCellChanged?.Invoke(wx, wz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+ onCellChanged?.Invoke(wx, wz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+
+ CarveFrom(nx, nz, grid, visited, rng, width, depth, onCellChanged);
+
+ // Clear head from the child cell and restore it here
+ onCellChanged?.Invoke(nx, nz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+ onCellChanged?.Invoke(cx, cz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+ }
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSRecursive.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSRecursive.cs.meta
new file mode 100644
index 00000000..9b97cb23
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/DFSRecursive.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: f20ddc35c8bf6604b84a0102bdad1821
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/IMazeReworkAlgorithm.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/IMazeReworkAlgorithm.cs
new file mode 100644
index 00000000..1bad3b82
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/IMazeReworkAlgorithm.cs
@@ -0,0 +1,36 @@
+namespace Baba_yaga.GameSetup.MazeRework.Algorithms
+{
+ ///
+ /// Contract that all maze carving algorithms must fulfill.
+ /// The algorithm is only responsible for carving corridors.
+ /// Rooms, loops, Start/End placement, and connectivity repair are handled externally.
+ ///
+ public interface IMazeReworkAlgorithm
+ {
+ ///
+ /// Carves corridors into the grid starting from (startX, startZ).
+ /// All cells begin as Wall. The algorithm sets reachable cells to Corridor.
+ ///
+ /// The 2D cell array to carve into.
+ /// Shared visited map. Pre-marked cells (e.g. rooms) are already true.
+ /// X coordinate of the first cell to carve (must be odd).
+ /// Z coordinate of the first cell to carve (must be odd).
+ /// Grid width.
+ /// Grid depth.
+ /// Seeded random number generator.
+ ///
+ /// Optional callback fired every time a cell is carved or evaluated.
+ /// Signature: (x, z, newType, highlight). Pass null in non-animated mode.
+ ///
+ void Carve(
+ MazeReworkCellType[,] grid,
+ bool[,] visited,
+ int startX,
+ int startZ,
+ int width,
+ int depth,
+ System.Random rng,
+ System.Action onCellChanged = null
+ );
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/IMazeReworkAlgorithm.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/IMazeReworkAlgorithm.cs.meta
new file mode 100644
index 00000000..70f1b7fb
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/IMazeReworkAlgorithm.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: f8ba54b75b8f8344aa7ccb03b8779c03
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Kruskals.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Kruskals.cs
new file mode 100644
index 00000000..084d7533
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Kruskals.cs
@@ -0,0 +1,82 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Baba_yaga.GameSetup.MazeRework.Algorithms
+{
+ public class Kruskals : IMazeReworkAlgorithm
+ {
+ public void Carve(
+ MazeReworkCellType[,] grid,
+ bool[,] visited,
+ int startX, int startZ,
+ int width, int depth,
+ System.Random rng,
+ System.Action onCellChanged = null)
+ {
+ // Assign unique ID to every odd-coordinate (node) cell
+ int[,] cellId = new int[width, depth];
+ int idCounter = 0;
+ for (int z = 1; z < depth - 1; z += 2)
+ for (int x = 1; x < width - 1; x += 2)
+ cellId[x, z] = idCounter++;
+
+ UnionFind uf = new UnionFind(idCounter);
+
+ // Collect all internal walls
+ List walls = new List();
+ for (int z = 1; z < depth - 1; z++)
+ for (int x = 1; x < width - 1; x++)
+ if ((x % 2 == 0 && z % 2 == 1) || (x % 2 == 1 && z % 2 == 0))
+ walls.Add(new Vector2Int(x, z));
+
+ // Shuffle walls
+ for (int i = walls.Count - 1; i > 0; i--)
+ {
+ int j = rng.Next(i + 1);
+ var tmp = walls[i]; walls[i] = walls[j]; walls[j] = tmp;
+ }
+
+ foreach (var wall in walls)
+ {
+ int wx = wall.x, wz = wall.y;
+ int ax, az, bx, bz;
+
+ if (wx % 2 == 0) { ax = wx - 1; az = wz; bx = wx + 1; bz = wz; }
+ else { ax = wx; az = wz - 1; bx = wx; bz = wz + 1; }
+
+ if (ax < 1 || ax >= width - 1 || az < 1 || az >= depth - 1) continue;
+ if (bx < 1 || bx >= width - 1 || bz < 1 || bz >= depth - 1) continue;
+
+ // Show evaluating highlight
+ onCellChanged?.Invoke(wx, wz, grid[wx, wz], Animation.MazeCellHighlight.Evaluating);
+
+ if (uf.Find(cellId[ax, az]) != uf.Find(cellId[bx, bz]))
+ {
+ grid[wx, wz] = MazeReworkCellType.Corridor;
+ grid[ax, az] = MazeReworkCellType.Corridor;
+ grid[bx, bz] = MazeReworkCellType.Corridor;
+ visited[wx, wz] = visited[ax, az] = visited[bx, bz] = true;
+
+ onCellChanged?.Invoke(ax, az, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+ onCellChanged?.Invoke(wx, wz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+ onCellChanged?.Invoke(bx, bz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+
+ uf.Union(cellId[ax, az], cellId[bx, bz]);
+ }
+ else
+ {
+ // Clear evaluate highlight
+ onCellChanged?.Invoke(wx, wz, grid[wx, wz], Animation.MazeCellHighlight.None);
+ }
+ }
+ }
+
+ private class UnionFind
+ {
+ private readonly int[] _parent, _rank;
+ public UnionFind(int count) { _parent = new int[count]; _rank = new int[count]; for (int i = 0; i < count; i++) _parent[i] = i; }
+ public int Find(int x) { if (_parent[x] != x) _parent[x] = Find(_parent[x]); return _parent[x]; }
+ public void Union(int a, int b) { int ra = Find(a), rb = Find(b); if (ra == rb) return; if (_rank[ra] < _rank[rb]) _parent[ra] = rb; else if (_rank[ra] > _rank[rb]) _parent[rb] = ra; else { _parent[rb] = ra; _rank[ra]++; } }
+ }
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Kruskals.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Kruskals.cs.meta
new file mode 100644
index 00000000..d9927da2
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Kruskals.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 7574ba4325993ac46a12a7861b70031f
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Prims.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Prims.cs
new file mode 100644
index 00000000..e83ad20f
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Prims.cs
@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Baba_yaga.GameSetup.MazeRework.Algorithms
+{
+ public class Prims : IMazeReworkAlgorithm
+ {
+ public void Carve(
+ MazeReworkCellType[,] grid,
+ bool[,] visited,
+ int startX, int startZ,
+ int width, int depth,
+ System.Random rng,
+ System.Action onCellChanged = null)
+ {
+ grid[startX, startZ] = MazeReworkCellType.Corridor;
+ visited[startX, startZ] = true;
+ onCellChanged?.Invoke(startX, startZ, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+
+ List<(int nx, int nz, int wx, int wz)> frontier = new List<(int, int, int, int)>();
+ AddFrontier(startX, startZ, frontier, visited, width, depth, grid, onCellChanged);
+
+ while (frontier.Count > 0)
+ {
+ int pick = rng.Next(frontier.Count);
+ var (nx, nz, wx, wz) = frontier[pick];
+
+ // Swap-remove O(1)
+ frontier[pick] = frontier[frontier.Count - 1];
+ frontier.RemoveAt(frontier.Count - 1);
+
+ if (visited[nx, nz])
+ {
+ // Clear the frontier highlight if this cell was already visited by another path
+ onCellChanged?.Invoke(nx, nz, grid[nx, nz], Animation.MazeCellHighlight.None);
+ continue;
+ }
+
+ grid[wx, wz] = MazeReworkCellType.Corridor;
+ grid[nx, nz] = MazeReworkCellType.Corridor;
+ visited[wx, wz] = true;
+ visited[nx, nz] = true;
+
+ onCellChanged?.Invoke(wx, wz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+ onCellChanged?.Invoke(wx, wz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+
+ onCellChanged?.Invoke(nx, nz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.SearchHead);
+ onCellChanged?.Invoke(nx, nz, MazeReworkCellType.Corridor, Animation.MazeCellHighlight.None);
+
+ AddFrontier(nx, nz, frontier, visited, width, depth, grid, onCellChanged);
+ }
+ }
+
+ private void AddFrontier(int cx, int cz,
+ List<(int nx, int nz, int wx, int wz)> frontier,
+ bool[,] visited, int width, int depth, MazeReworkCellType[,] grid,
+ System.Action onCellChanged)
+ {
+ int[] dx = { 2, -2, 0, 0 };
+ int[] dz = { 0, 0, 2, -2 };
+ for (int i = 0; i < 4; i++)
+ {
+ int nx = cx + dx[i], nz = cz + dz[i];
+ int wx = cx + dx[i] / 2, wz = cz + dz[i] / 2;
+ if (nx > 0 && nx < width - 1 && nz > 0 && nz < depth - 1 && !visited[nx, nz])
+ {
+ frontier.Add((nx, nz, wx, wz));
+ onCellChanged?.Invoke(nx, nz, grid[nx, nz], Animation.MazeCellHighlight.Frontier);
+ }
+ }
+ }
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Prims.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Prims.cs.meta
new file mode 100644
index 00000000..10517b4d
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Algorithms/Prims.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 321151d3d7c655047b73b6bd981800e6
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation.meta
new file mode 100644
index 00000000..6377a6f2
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 92ea88f252068ee47ad6145db600314b
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimationPhase.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimationPhase.cs
new file mode 100644
index 00000000..23fafe32
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimationPhase.cs
@@ -0,0 +1,15 @@
+namespace Baba_yaga.GameSetup.MazeRework.Animation
+{
+ ///
+ /// Labels each recorded cell change with which generation phase produced it.
+ /// Used to color-code or group changes during animated playback.
+ ///
+ public enum MazeAnimationPhase
+ {
+ RoomPlacement, // Rooms being stamped onto the grid
+ Carving, // Algorithm carving corridors
+ Connecting, // Hunt-and-Kill fixing isolated pockets
+ Loops, // Extra walls removed to create shortcuts
+ StartEnd // Start and End cells placed
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimationPhase.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimationPhase.cs.meta
new file mode 100644
index 00000000..8bbb9ed4
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimationPhase.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 45bda90d4b2d42245a8d9f06543053ee
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimator.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimator.cs
new file mode 100644
index 00000000..d0a0a8ab
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimator.cs
@@ -0,0 +1,123 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace Baba_yaga.GameSetup.MazeRework.Animation
+{
+ public class MazeAnimator : MonoBehaviour
+ {
+ [Header("Animation Settings")]
+ [Tooltip("How many cell changes to process in a single frame. Higher = faster generation.")]
+ [Min(1)]
+ public int cellsPerFrame = 5;
+
+ [Tooltip("Extra delay (in seconds) between major generation phases (like switching from Rooms to Carving).")]
+ public float delayBetweenPhases = 0.5f;
+
+ private Coroutine _animationRoutine;
+
+ public void AnimateGeneration(
+ List history,
+ MazeReworkCellType[,] grid,
+ MazeReworkSpawner spawner,
+ float yOffset,
+ Transform container,
+ System.Action onComplete = null)
+ {
+ if (_animationRoutine != null)
+ StopCoroutine(_animationRoutine);
+
+ _animationRoutine = StartCoroutine(AnimateRoutine(history, grid, spawner, yOffset, container, onComplete));
+ }
+
+ public void StopAnimation()
+ {
+ if (_animationRoutine != null)
+ {
+ StopCoroutine(_animationRoutine);
+ _animationRoutine = null;
+ }
+ }
+
+ private IEnumerator AnimateRoutine(
+ List history,
+ MazeReworkCellType[,] finalGrid,
+ MazeReworkSpawner spawner,
+ float yOffset,
+ Transform container,
+ System.Action onComplete)
+ {
+ int width = finalGrid.GetLength(0);
+ int depth = finalGrid.GetLength(1);
+
+ // Create a working grid starting fully as walls (like the generator does)
+ MazeReworkCellType[,] workingGrid = new MazeReworkCellType[width, depth];
+ MazeCellHighlight[,] workingHighlights = new MazeCellHighlight[width, depth];
+ for (int z = 0; z < depth; z++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ workingGrid[x, z] = MazeReworkCellType.Wall;
+ workingHighlights[x, z] = MazeCellHighlight.None;
+ }
+ }
+
+ spawner.Clear();
+
+ MazeAnimationPhase currentPhase = MazeAnimationPhase.RoomPlacement;
+ int processedThisFrame = 0;
+
+ foreach (var change in history)
+ {
+ if (change.Phase != currentPhase)
+ {
+ currentPhase = change.Phase;
+ if (delayBetweenPhases > 0f)
+ {
+ yield return new WaitForSeconds(delayBetweenPhases);
+ processedThisFrame = 0;
+ }
+ }
+
+ workingGrid[change.X, change.Z] = change.Type;
+ workingHighlights[change.X, change.Z] = change.Highlight;
+
+ // Refresh the cell and its neighbors in the spawner
+ spawner.RefreshCell(workingGrid, workingHighlights, change.X, change.Z, yOffset, container);
+
+ processedThisFrame++;
+ if (processedThisFrame >= cellsPerFrame)
+ {
+ yield return null; // Wait for next frame
+ processedThisFrame = 0;
+ }
+ }
+
+ // Wait a moment at the end before finalizing
+ if (delayBetweenPhases > 0f)
+ {
+ yield return new WaitForSeconds(delayBetweenPhases);
+ }
+
+ // One final sync with finalGrid just to be absolutely safe
+ for (int z = 0; z < depth; z++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ bool gridChanged = workingGrid[x, z] != finalGrid[x, z];
+ bool highlightChanged = workingHighlights[x, z] != MazeCellHighlight.None;
+
+ if (gridChanged || highlightChanged)
+ {
+ workingGrid[x, z] = finalGrid[x, z];
+ workingHighlights[x, z] = MazeCellHighlight.None;
+ spawner.RefreshCell(workingGrid, workingHighlights, x, z, yOffset, container);
+ }
+ }
+ }
+
+ _animationRoutine = null;
+ onComplete?.Invoke();
+ }
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimator.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimator.cs.meta
new file mode 100644
index 00000000..07f9433b
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeAnimator.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 209db07e0fcae2e4e9e8b9e2fb822e31
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellChange.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellChange.cs
new file mode 100644
index 00000000..a4f5ec64
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellChange.cs
@@ -0,0 +1,24 @@
+namespace Baba_yaga.GameSetup.MazeRework.Animation
+{
+ ///
+ /// A single recorded cell change captured during maze generation.
+ /// The animator drains this list to replay generation visually.
+ ///
+ public readonly struct MazeCellChange
+ {
+ public readonly int X;
+ public readonly int Z;
+ public readonly MazeReworkCellType Type;
+ public readonly MazeCellHighlight Highlight;
+ public readonly MazeAnimationPhase Phase;
+
+ public MazeCellChange(int x, int z, MazeReworkCellType type, MazeCellHighlight highlight, MazeAnimationPhase phase)
+ {
+ X = x;
+ Z = z;
+ Type = type;
+ Highlight = highlight;
+ Phase = phase;
+ }
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellChange.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellChange.cs.meta
new file mode 100644
index 00000000..b5da66ff
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellChange.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 6f6a93f9b414a3f4a83c74ee28fb441b
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellHighlight.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellHighlight.cs
new file mode 100644
index 00000000..8af7f266
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellHighlight.cs
@@ -0,0 +1,10 @@
+namespace Baba_yaga.GameSetup.MazeRework.Animation
+{
+ public enum MazeCellHighlight
+ {
+ None,
+ SearchHead, // Current cell being evaluated (DFS, Prim's)
+ Frontier, // Known candidate cells (Prim's)
+ Evaluating // Walls currently being considered (Kruskal's)
+ }
+}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellHighlight.cs.meta b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellHighlight.cs.meta
new file mode 100644
index 00000000..89215e14
--- /dev/null
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/Animation/MazeCellHighlight.cs.meta
@@ -0,0 +1,2 @@
+fileFormatVersion: 2
+guid: 6bff934558bb70343ad947b2c9e4da45
\ No newline at end of file
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkConfig.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkConfig.cs
index eb17ce5c..8ada80ac 100644
--- a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkConfig.cs
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkConfig.cs
@@ -1,13 +1,29 @@
using UnityEngine;
+using Baba_yaga.GameSetup.MazeRework.Algorithms;
namespace Baba_yaga.GameSetup.MazeRework
{
+ ///
+ /// Defines which carving algorithm the generator will use.
+ ///
+ public enum MazeAlgorithmType
+ {
+ DFSRecursive, // Long winding corridors. May stack overflow on huge grids.
+ DFSIterative, // Same result as recursive but safe for large grids.
+ Kruskals, // Short branchy corridors, open feel, no directional bias.
+ Prims, // Organic cave-like layout, radiates outward from start.
+ }
+
///
/// Configuration asset containing parameters for the reworked maze generation.
///
- [CreateAssetMenu(fileName = "MazeReworkConfig", menuName = "BABA_YAGA/GameSetup/MazeRework")]
+ [CreateAssetMenu(fileName = "MazeReworkConfig", menuName = "BABA_YAGA/MazeRework/Config")]
public class MazeReworkConfig : ScriptableObject
{
+ [Header("Algorithm")]
+ [Tooltip("Which carving algorithm to use for generating the maze corridors.")]
+ public MazeAlgorithmType algorithm = MazeAlgorithmType.DFSRecursive;
+
[Header("Grid Dimensions")]
[Tooltip("Width of the maze grid. Best if odd to align with wall-corridor-wall patterning.")]
[Min(5)]
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkGenerator.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkGenerator.cs
index 1004efe5..c9275725 100644
--- a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkGenerator.cs
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkGenerator.cs
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using UnityEngine;
+using Baba_yaga.GameSetup.MazeRework.Algorithms;
+using Baba_yaga.GameSetup.MazeRework.Animation;
namespace Baba_yaga.GameSetup.MazeRework
{
@@ -97,10 +99,11 @@ namespace Baba_yaga.GameSetup.MazeRework
int startZ = _config.startLocation.y;
EnsureValidOddCoordinates(width, depth, ref startX, ref startZ);
- // 5. Carve Corridors recursively using Step-by-2 Recursive Backtracking
+ // 5. Carve Corridors using the selected algorithm
visited[startX, startZ] = true;
grid[startX, startZ] = MazeReworkCellType.Corridor;
- CarveFrom(startX, startZ, grid, visited, rooms, rng, width, depth);
+ IMazeReworkAlgorithm algorithm = GetAlgorithm();
+ algorithm.Carve(grid, visited, startX, startZ, width, depth, rng);
// 6. Hunt & Kill scan to connect isolated rooms/corridors
EnsureAllConnected(grid, visited, rooms, rng, width, depth);
@@ -114,9 +117,86 @@ namespace Baba_yaga.GameSetup.MazeRework
return grid;
}
+ #region Animated Generation
+
+ ///
+ /// Generates the maze and records every cell change with its phase label.
+ /// Returns the final grid AND the ordered history list for the animator to replay.
+ ///
+ public (MazeReworkCellType[,] grid, List history) GenerateAnimated()
+ {
+ if (_config == null) return (null, null);
+ int seed = _config.useRandomSeed
+ ? System.DateTime.Now.Millisecond + System.Threading.Thread.CurrentThread.ManagedThreadId
+ : _config.seed;
+ return GenerateAnimated(seed);
+ }
+
+ public (MazeReworkCellType[,] grid, List history) GenerateAnimated(int seed)
+ {
+ if (_config == null) return (null, null);
+
+ int width = _config.width;
+ int depth = _config.depth;
+ var grid = new MazeReworkCellType[width, depth];
+ var history = new List(width * depth * 2);
+
+ // Helper: record a cell change tagged with a phase
+ var currentPhase = MazeAnimationPhase.RoomPlacement;
+ Action record =
+ (x, z, t, h) => history.Add(new MazeCellChange(x, z, t, h, currentPhase));
+
+ Action recordNoHighlight =
+ (x, z, t) => record(x, z, t, MazeCellHighlight.None);
+
+ // 1. Initialize all cells as Wall (no recording — start state is all-Wall)
+ for (int z = 0; z < depth; z++)
+ for (int x = 0; x < width; x++)
+ grid[x, z] = MazeReworkCellType.Wall;
+
+ System.Random rng = new System.Random(seed);
+
+ // 2. Generate Rooms — record each Room cell
+ currentPhase = MazeAnimationPhase.RoomPlacement;
+ List rooms = GenerateRooms(grid, width, depth, rng, recordNoHighlight);
+
+ // 3. Setup visited map
+ bool[,] visited = new bool[width, depth];
+ InitializeVisitedMap(grid, visited, rooms, width, depth);
+
+ // 4. Starting coordinates
+ int startX = _config.startLocation.x;
+ int startZ = _config.startLocation.y;
+ EnsureValidOddCoordinates(width, depth, ref startX, ref startZ);
+
+ // 5. Carve Corridors — algorithm fires back through the record callback
+ currentPhase = MazeAnimationPhase.Carving;
+ visited[startX, startZ] = true;
+ grid[startX, startZ] = MazeReworkCellType.Corridor;
+ record(startX, startZ, MazeReworkCellType.Corridor, MazeCellHighlight.None); // DFS will highlight itself
+ GetAlgorithm().Carve(grid, visited, startX, startZ, width, depth, rng, record);
+
+ // 6. Hunt & Kill connecting pass
+ currentPhase = MazeAnimationPhase.Connecting;
+ EnsureAllConnected(grid, visited, rooms, rng, width, depth, recordNoHighlight);
+
+ // 7. Loop carving
+ currentPhase = MazeAnimationPhase.Loops;
+ CarveLoops(grid, rng, width, depth, recordNoHighlight);
+
+ // 8. Start & End placement
+ currentPhase = MazeAnimationPhase.StartEnd;
+ PlaceStartAndEnd(grid, rooms, width, depth, recordNoHighlight);
+
+ return (grid, history);
+ }
+
+ #endregion
+
#region Internal Generation Logic
- private List GenerateRooms(MazeReworkCellType[,] grid, int width, int depth, System.Random rng)
+ private List GenerateRooms(MazeReworkCellType[,] grid, int width, int depth, System.Random rng,
+ Action onCellChanged = null)
{
List rooms = new List();
if (!_config.generateRooms) return rooms;
@@ -144,22 +224,18 @@ namespace Baba_yaga.GameSetup.MazeRework
bool overlaps = false;
foreach (var r in rooms)
{
- if (newRoom.Overlaps(r, 1))
- {
- overlaps = true;
- break;
- }
+ if (newRoom.Overlaps(r, 1)) { overlaps = true; break; }
}
if (!overlaps)
{
rooms.Add(newRoom);
- // Carve room cells
for (int z = rz; z < rz + rh; z++)
{
for (int x = rx; x < rx + rw; x++)
{
grid[x, z] = MazeReworkCellType.Room;
+ onCellChanged?.Invoke(x, z, MazeReworkCellType.Room);
}
}
}
@@ -182,7 +258,26 @@ namespace Baba_yaga.GameSetup.MazeRework
}
}
- private void CarveFrom(int cx, int cz, MazeReworkCellType[,] grid, bool[,] visited, List rooms, System.Random rng, int width, int depth)
+ ///
+ /// Factory that returns the correct algorithm based on config selection.
+ ///
+ private IMazeReworkAlgorithm GetAlgorithm()
+ {
+ return _config.algorithm switch
+ {
+ MazeAlgorithmType.DFSRecursive => new DFSRecursive(),
+ MazeAlgorithmType.DFSIterative => new DFSIterative(),
+ MazeAlgorithmType.Kruskals => new Kruskals(),
+ MazeAlgorithmType.Prims => new Prims(),
+ _ => new DFSIterative()
+ };
+ }
+
+ ///
+ /// After corridor carving, connects room cells to the corridor network
+ /// by carving doorway walls between corridors and rooms.
+ ///
+ private void ConnectRoomsFrom(int cx, int cz, MazeReworkCellType[,] grid, bool[,] visited, List rooms, System.Random rng, int width, int depth)
{
Vector2Int[] dirs = new Vector2Int[4]
{
@@ -215,7 +310,7 @@ namespace Baba_yaga.GameSetup.MazeRework
grid[nx, nz] = MazeReworkCellType.Corridor;
visited[wx, wz] = true;
visited[nx, nz] = true;
- CarveFrom(nx, nz, grid, visited, rooms, rng, width, depth);
+ ConnectRoomsFrom(nx, nz, grid, visited, rooms, rng, width, depth);
}
else if (grid[nx, nz] == MazeReworkCellType.Room)
{
@@ -244,7 +339,9 @@ namespace Baba_yaga.GameSetup.MazeRework
}
}
- private void EnsureAllConnected(MazeReworkCellType[,] grid, bool[,] visited, List rooms, System.Random rng, int width, int depth)
+ private void EnsureAllConnected(MazeReworkCellType[,] grid, bool[,] visited, List rooms,
+ System.Random rng, int width, int depth,
+ Action onCellChanged = null)
{
for (int z = 1; z < depth - 1; z += 2)
{
@@ -254,50 +351,30 @@ namespace Baba_yaga.GameSetup.MazeRework
{
Vector2Int[] dirs = new Vector2Int[4]
{
- new Vector2Int(2, 0),
- new Vector2Int(-2, 0),
- new Vector2Int(0, 2),
- new Vector2Int(0, -2)
+ new Vector2Int(2, 0), new Vector2Int(-2, 0),
+ new Vector2Int(0, 2), new Vector2Int(0, -2)
};
-
- for (int i = 3; i > 0; i--)
- {
- int j = rng.Next(i + 1);
- var temp = dirs[i];
- dirs[i] = dirs[j];
- dirs[j] = temp;
- }
+ for (int i = 3; i > 0; i--) { int j = rng.Next(i + 1); var t = dirs[i]; dirs[i] = dirs[j]; dirs[j] = t; }
bool connected = false;
for (int i = 0; i < 4; i++)
{
- int nx = x + dirs[i].x;
- int nz = z + dirs[i].y;
- int wx = x + dirs[i].x / 2;
- int wz = z + dirs[i].y / 2;
-
- if (nx > 0 && nx < width - 1 && nz > 0 && nz < depth - 1)
+ int nx = x + dirs[i].x, nz = z + dirs[i].y;
+ int wx = x + dirs[i].x / 2, wz = z + dirs[i].y / 2;
+ if (nx > 0 && nx < width - 1 && nz > 0 && nz < depth - 1 && visited[nx, nz])
{
- if (visited[nx, nz])
- {
- grid[wx, wz] = MazeReworkCellType.Corridor;
- grid[x, z] = MazeReworkCellType.Corridor;
- visited[wx, wz] = true;
- visited[x, z] = true;
- connected = true;
- break;
- }
+ grid[wx, wz] = MazeReworkCellType.Corridor;
+ grid[x, z] = MazeReworkCellType.Corridor;
+ visited[wx, wz] = visited[x, z] = true;
+ onCellChanged?.Invoke(wx, wz, MazeReworkCellType.Corridor);
+ onCellChanged?.Invoke(x, z, MazeReworkCellType.Corridor);
+ connected = true;
+ break;
}
}
- if (connected)
- {
- CarveFrom(x, z, grid, visited, rooms, rng, width, depth);
- }
- else
- {
- CarveFrom(x, z, grid, visited, rooms, rng, width, depth);
- }
+ ConnectRoomsFrom(x, z, grid, visited, rooms, rng, width, depth);
+ _ = connected; // suppress unused warning
}
}
}
@@ -307,74 +384,31 @@ namespace Baba_yaga.GameSetup.MazeRework
var room = rooms[i];
if (!room.isConnected)
{
- ForceConnectRoom(grid, room, visited, rng, width, depth);
+ ForceConnectRoom(grid, room, visited, rng, width, depth, onCellChanged);
room.isConnected = true;
rooms[i] = room;
}
}
}
- private void ForceConnectRoom(MazeReworkCellType[,] grid, Room room, bool[,] visited, System.Random rng, int width, int depth)
+ private void ForceConnectRoom(MazeReworkCellType[,] grid, Room room, bool[,] visited,
+ System.Random rng, int width, int depth,
+ Action onCellChanged = null)
{
int[] sides = new int[] { 0, 1, 2, 3 };
- for (int i = 3; i > 0; i--)
- {
- int j = rng.Next(i + 1);
- int temp = sides[i];
- sides[i] = sides[j];
- sides[j] = temp;
- }
+ for (int i = 3; i > 0; i--) { int j = rng.Next(i + 1); int t = sides[i]; sides[i] = sides[j]; sides[j] = t; }
foreach (int side in sides)
{
- if (side == 0)
- {
- int z = room.z + room.depth - 1;
- if (z + 2 < depth - 1)
- {
- int x = room.x + 2 * rng.Next(0, room.width / 2);
- grid[x, z + 1] = MazeReworkCellType.Corridor;
- visited[x, z + 1] = true;
- return;
- }
- }
- else if (side == 1)
- {
- int z = room.z;
- if (z - 2 > 0)
- {
- int x = room.x + 2 * rng.Next(0, room.width / 2);
- grid[x, z - 1] = MazeReworkCellType.Corridor;
- visited[x, z - 1] = true;
- return;
- }
- }
- else if (side == 2)
- {
- int x = room.x;
- if (x - 2 > 0)
- {
- int z = room.z + 2 * rng.Next(0, room.depth / 2);
- grid[x - 1, z] = MazeReworkCellType.Corridor;
- visited[x - 1, z] = true;
- return;
- }
- }
- else if (side == 3)
- {
- int x = room.x + room.width - 1;
- if (x + 2 < width - 1)
- {
- int z = room.z + 2 * rng.Next(0, room.depth / 2);
- grid[x + 1, z] = MazeReworkCellType.Corridor;
- visited[x + 1, z] = true;
- return;
- }
- }
+ if (side == 0) { int z = room.z + room.depth - 1; if (z + 2 < depth - 1) { int x = room.x + 2 * rng.Next(0, room.width / 2); grid[x, z + 1] = MazeReworkCellType.Corridor; visited[x, z + 1] = true; onCellChanged?.Invoke(x, z + 1, MazeReworkCellType.Corridor); return; } }
+ else if (side == 1) { int z = room.z; if (z - 2 > 0) { int x = room.x + 2 * rng.Next(0, room.width / 2); grid[x, z - 1] = MazeReworkCellType.Corridor; visited[x, z - 1] = true; onCellChanged?.Invoke(x, z - 1, MazeReworkCellType.Corridor); return; } }
+ else if (side == 2) { int x = room.x; if (x - 2 > 0) { int z = room.z + 2 * rng.Next(0, room.depth / 2); grid[x - 1, z] = MazeReworkCellType.Corridor; visited[x - 1, z] = true; onCellChanged?.Invoke(x - 1, z, MazeReworkCellType.Corridor); return; } }
+ else if (side == 3) { int x = room.x + room.width - 1; if (x + 2 < width - 1) { int z = room.z + 2 * rng.Next(0, room.depth / 2); grid[x + 1, z] = MazeReworkCellType.Corridor; visited[x + 1, z] = true; onCellChanged?.Invoke(x + 1, z, MazeReworkCellType.Corridor); return; } }
}
}
- private void CarveLoops(MazeReworkCellType[,] grid, System.Random rng, int width, int depth)
+ private void CarveLoops(MazeReworkCellType[,] grid, System.Random rng, int width, int depth,
+ Action onCellChanged = null)
{
if (_config.loopChance <= 0f) return;
@@ -383,90 +417,66 @@ namespace Baba_yaga.GameSetup.MazeRework
for (int x = 1; x < width - 1; x++)
{
bool isHorizontalWall = (x % 2 == 0 && z % 2 != 0);
- bool isVerticalWall = (x % 2 != 0 && z % 2 == 0);
-
+ bool isVerticalWall = (x % 2 != 0 && z % 2 == 0);
if (!isHorizontalWall && !isVerticalWall) continue;
if (grid[x, z] == MazeReworkCellType.Wall)
{
- if (isHorizontalWall)
+ bool carve = isHorizontalWall
+ ? IsPathCell(grid[x - 1, z]) && IsPathCell(grid[x + 1, z])
+ : IsPathCell(grid[x, z - 1]) && IsPathCell(grid[x, z + 1]);
+
+ if (carve && rng.NextDouble() < _config.loopChance)
{
- if (IsPathCell(grid[x - 1, z]) && IsPathCell(grid[x + 1, z]))
- {
- if (rng.NextDouble() < _config.loopChance)
- {
- grid[x, z] = MazeReworkCellType.Corridor;
- }
- }
- }
- else
- {
- if (IsPathCell(grid[x, z - 1]) && IsPathCell(grid[x, z + 1]))
- {
- if (rng.NextDouble() < _config.loopChance)
- {
- grid[x, z] = MazeReworkCellType.Corridor;
- }
- }
+ grid[x, z] = MazeReworkCellType.Corridor;
+ onCellChanged?.Invoke(x, z, MazeReworkCellType.Corridor);
}
}
}
}
}
- private void PlaceStartAndEnd(MazeReworkCellType[,] grid, List rooms, int width, int depth)
+ private void PlaceStartAndEnd(MazeReworkCellType[,] grid, List rooms, int width, int depth,
+ Action onCellChanged = null)
{
if (rooms != null && rooms.Count > 0)
{
var startRoom = rooms[0];
var startPt = startRoom.GetCenter();
grid[startPt.x, startPt.y] = MazeReworkCellType.Start;
+ onCellChanged?.Invoke(startPt.x, startPt.y, MazeReworkCellType.Start);
var endRoom = rooms[rooms.Count - 1];
var endPt = endRoom.GetCenter();
- if (endPt == startPt && rooms.Count > 1)
- {
- endRoom = rooms[1];
- endPt = endRoom.GetCenter();
- }
+ if (endPt == startPt && rooms.Count > 1) { endRoom = rooms[1]; endPt = endRoom.GetCenter(); }
grid[endPt.x, endPt.y] = MazeReworkCellType.End;
+ onCellChanged?.Invoke(endPt.x, endPt.y, MazeReworkCellType.End);
}
else
{
- int sx = _config.startLocation.x;
- int sz = _config.startLocation.y;
+ int sx = _config.startLocation.x, sz = _config.startLocation.y;
EnsureValidOddCoordinates(width, depth, ref sx, ref sz);
grid[sx, sz] = MazeReworkCellType.Start;
+ onCellChanged?.Invoke(sx, sz, MazeReworkCellType.Start);
- int ex = width - 2;
- int ez = depth - 2;
+ int ex = width - 2, ez = depth - 2;
EnsureValidOddCoordinates(width, depth, ref ex, ref ez);
-
if (grid[ex, ez] == MazeReworkCellType.Wall)
{
bool found = false;
for (int r = 1; r < Mathf.Max(width, depth) && !found; r++)
- {
- for (int dx = -r; dx <= r && !found; dx++)
- {
- for (int dz = -r; dz <= r && !found; dz++)
+ for (int ddx = -r; ddx <= r && !found; ddx++)
+ for (int ddz = -r; ddz <= r && !found; ddz++)
{
- int tx = ex + dx;
- int tz = ez + dz;
+ int tx = ex + ddx, tz = ez + ddz;
if (tx >= 0 && tx < width && tz >= 0 && tz < depth && IsPathCell(grid[tx, tz]))
- {
- ex = tx;
- ez = tz;
- found = true;
- }
+ { ex = tx; ez = tz; found = true; }
}
- }
- }
}
-
if (ex != sx || ez != sz)
{
grid[ex, ez] = MazeReworkCellType.End;
+ onCellChanged?.Invoke(ex, ez, MazeReworkCellType.End);
}
}
}
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkManager.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkManager.cs
index 0acf87a9..e4152e11 100644
--- a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkManager.cs
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkManager.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using UnityEngine;
using Sirenix.OdinInspector;
+using Baba_yaga.GameSetup.MazeRework.Animation;
namespace Baba_yaga.GameSetup.MazeRework
{
@@ -16,6 +17,11 @@ namespace Baba_yaga.GameSetup.MazeRework
[Header("References")]
[SerializeField] private MazeReworkSpawner spawner;
[SerializeField] private Transform mazeContainer;
+ [SerializeField] private MazeAnimator animator;
+
+ [Header("Animation")]
+ [Tooltip("If true, visually animates the generation process step-by-step. (Best used with 1 floor)")]
+ [SerializeField] private bool animateGeneration = false;
[Header("Multi-floor Settings")]
[Tooltip("Number of floors to generate.")]
@@ -102,33 +108,51 @@ namespace Baba_yaga.GameSetup.MazeRework
// Clear any previously spawned maze objects
ClearMaze();
+ if (animator != null) animator.StopAnimation();
var generator = new MazeReworkGenerator(config);
- // Generate each floor using the configuration
- for (int i = 0; i < floorCount; i++)
+ if (animateGeneration && animator != null)
{
- int seed = config.useRandomSeed ? Random.Range(0, 1000000) : config.seed + i * 1000;
- var grid = generator.Generate(seed);
+ // Animated mode: generates floor 0 and replays the creation step-by-step
+ int seed = config.useRandomSeed ? Random.Range(0, 1000000) : config.seed;
+ var (grid, history) = generator.GenerateAnimated(seed);
_grids.Add(grid);
- }
- // Connect floors with staircases if multiple floors are present
- if (floorCount > 1)
+ BeginningWorldPosition = FindBeginningWorldPosition(grid);
+
+ animator.AnimateGeneration(history, grid, spawner, 0f, mazeContainer, () =>
+ {
+ Debug.Log($"[MazeReworkManager] Animation complete. Beginning world position: {BeginningWorldPosition}");
+ });
+ }
+ else
{
- GenerateConnections();
- }
+ // Standard instantaneous generation
+ for (int i = 0; i < floorCount; i++)
+ {
+ int seed = config.useRandomSeed ? Random.Range(0, 1000000) : config.seed + i * 1000;
+ var grid = generator.Generate(seed);
+ _grids.Add(grid);
+ }
- // Spawn prefabs for all floors
- for (int i = 0; i < floorCount; i++)
- {
- float yOffset = i * floorHeight;
- spawner.Spawn(_grids[i], yOffset, mazeContainer);
- }
+ // Connect floors with staircases if multiple floors are present
+ if (floorCount > 1)
+ {
+ GenerateConnections();
+ }
- // Compute and cache the world-space Beginning position from floor 0
- BeginningWorldPosition = FindBeginningWorldPosition(_grids[0]);
- Debug.Log($"[MazeReworkManager] Beginning world position set to: {BeginningWorldPosition}");
+ // Spawn prefabs for all floors
+ for (int i = 0; i < floorCount; i++)
+ {
+ float yOffset = i * floorHeight;
+ spawner.Spawn(_grids[i], yOffset, mazeContainer);
+ }
+
+ // Compute and cache the world-space Beginning position from floor 0
+ BeginningWorldPosition = FindBeginningWorldPosition(_grids[0]);
+ Debug.Log($"[MazeReworkManager] Beginning world position set to: {BeginningWorldPosition}");
+ }
}
private void GenerateConnections()
diff --git a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkSpawner.cs b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkSpawner.cs
index 9b200b01..ab2976ca 100644
--- a/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkSpawner.cs
+++ b/Assets/Scripts/Baba_yaga/GameSetup/MazeRework/MazeReworkSpawner.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using UnityEngine;
+using Baba_yaga.GameSetup.MazeRework.Animation;
namespace Baba_yaga.GameSetup.MazeRework
{
@@ -27,6 +28,11 @@ namespace Baba_yaga.GameSetup.MazeRework
[Tooltip("Prefab for the End cell (player exit point). Auto-rotates based on neighbors.")]
public GameObject endPrefab;
+ [Header("Highlight Prefabs (Animation Only)")]
+ public GameObject searchHeadPrefab;
+ public GameObject frontierPrefab;
+ public GameObject evaluatingPrefab;
+
[Header("Rotation Offsets (Degrees)")]
[Tooltip("Rotation offset added to Hall 'I' prefab.")]
public float hallRotationOffset = 0f;
@@ -47,7 +53,8 @@ namespace Baba_yaga.GameSetup.MazeRework
[Tooltip("Physical distance between each grid cell center.")]
public float spacing = 3.0f;
- private readonly List _spawnedObjects = new List();
+ private readonly Dictionary _spawnedObjects = new Dictionary();
+ private readonly Dictionary _spawnedHighlights = new Dictionary();
private void Start()
{
@@ -73,20 +80,21 @@ namespace Baba_yaga.GameSetup.MazeRework
///
public void Clear()
{
- foreach (var obj in _spawnedObjects)
+ foreach (var obj in _spawnedObjects.Values)
{
if (obj == null) continue;
- if (Application.isPlaying)
- Destroy(obj);
- else
- DestroyImmediate(obj);
+ if (Application.isPlaying) Destroy(obj); else DestroyImmediate(obj);
}
_spawnedObjects.Clear();
+
+ foreach (var obj in _spawnedHighlights.Values)
+ {
+ if (obj == null) continue;
+ if (Application.isPlaying) Destroy(obj); else DestroyImmediate(obj);
+ }
+ _spawnedHighlights.Clear();
}
- ///
- /// Spawns the modular prefabs based on the generated 2D grid array.
- ///
public void Spawn(MazeReworkCellType[,] grid, float yOffset, Transform container)
{
if (grid == null) return;
@@ -99,40 +107,96 @@ namespace Baba_yaga.GameSetup.MazeRework
{
for (int x = 0; x < width; x++)
{
- MazeReworkCellType type = grid[x, z];
-
- // Wall cells spawn nothing
- if (type == MazeReworkCellType.Wall)
- {
- continue;
- }
-
- // For Start and End cells, use their dedicated prefab if assigned,
- // then apply connectivity-based rotation so they face the correct open direction.
- if (type == MazeReworkCellType.Start && beginningPrefab != null)
- {
- (_, float baseRot) = GetModularPrefabAndRotation(grid, x, z, width, depth);
- SpawnPrefab(beginningPrefab, x, yOffset, z, baseRot + beginningRotationOffset, container, "Beginning");
- continue;
- }
-
- if (type == MazeReworkCellType.End && endPrefab != null)
- {
- (_, float baseRot) = GetModularPrefabAndRotation(grid, x, z, width, depth);
- SpawnPrefab(endPrefab, x, yOffset, z, baseRot + endRotationOffset, container, "End");
- continue;
- }
-
- // All other path cells: evaluate connectivity to select and rotate the modular hallway prefab
- (GameObject modularPrefab, float yRotation) = GetModularPrefabAndRotation(grid, x, z, width, depth);
- if (modularPrefab != null)
- {
- SpawnPrefab(modularPrefab, x, yOffset, z, yRotation, container, $"{type}");
- }
+ RefreshSingleCell(grid, null, x, z, width, depth, yOffset, container);
}
}
}
+ ///
+ /// Refreshes a specific cell and its neighbors based on the current grid state.
+ ///
+ public void RefreshCell(MazeReworkCellType[,] grid, MazeCellHighlight[,] highlights, int x, int z, float yOffset, Transform container)
+ {
+ if (grid == null) return;
+ int width = grid.GetLength(0);
+ int depth = grid.GetLength(1);
+
+ // Refresh the target cell
+ RefreshSingleCell(grid, highlights, x, z, width, depth, yOffset, container);
+
+ // Refresh neighbors because their connectivity might have changed
+ RefreshSingleCell(grid, highlights, x + 1, z, width, depth, yOffset, container);
+ RefreshSingleCell(grid, highlights, x - 1, z, width, depth, yOffset, container);
+ RefreshSingleCell(grid, highlights, x, z + 1, width, depth, yOffset, container);
+ RefreshSingleCell(grid, highlights, x, z - 1, width, depth, yOffset, container);
+ }
+
+ private void RefreshSingleCell(MazeReworkCellType[,] grid, MazeCellHighlight[,] highlights, int x, int z, int width, int depth, float yOffset, Transform container)
+ {
+ if (x < 0 || x >= width || z < 0 || z >= depth) return;
+
+ Vector2Int pos = new Vector2Int(x, z);
+ MazeReworkCellType type = grid[x, z];
+ MazeCellHighlight hType = highlights != null ? highlights[x, z] : MazeCellHighlight.None;
+
+ // 1. Process Highlights
+ if (_spawnedHighlights.TryGetValue(pos, out GameObject existingHighlight))
+ {
+ if (Application.isPlaying) Destroy(existingHighlight);
+ else DestroyImmediate(existingHighlight);
+ _spawnedHighlights.Remove(pos);
+ }
+
+ if (hType != MazeCellHighlight.None)
+ {
+ GameObject hPrefab = null;
+ if (hType == MazeCellHighlight.SearchHead) hPrefab = searchHeadPrefab;
+ else if (hType == MazeCellHighlight.Frontier) hPrefab = frontierPrefab;
+ else if (hType == MazeCellHighlight.Evaluating) hPrefab = evaluatingPrefab;
+
+ if (hPrefab != null)
+ {
+ Vector3 localPos = new Vector3(x * spacing, yOffset, z * spacing);
+ GameObject spawnedH = Instantiate(hPrefab, container != null ? container : transform);
+ spawnedH.transform.localPosition = localPos;
+ spawnedH.name = $"Highlight_{hType}_{x}_{z}";
+ _spawnedHighlights[pos] = spawnedH;
+ }
+ }
+
+ // 2. Process Grid Cells
+ if (type == MazeReworkCellType.Wall)
+ {
+ if (_spawnedObjects.TryGetValue(pos, out GameObject existing))
+ {
+ if (Application.isPlaying) Destroy(existing);
+ else DestroyImmediate(existing);
+ _spawnedObjects.Remove(pos);
+ }
+ return;
+ }
+
+ if (type == MazeReworkCellType.Start && beginningPrefab != null)
+ {
+ (_, float baseRot) = GetModularPrefabAndRotation(grid, x, z, width, depth);
+ SpawnPrefab(beginningPrefab, x, yOffset, z, baseRot + beginningRotationOffset, container, "Beginning");
+ return;
+ }
+
+ if (type == MazeReworkCellType.End && endPrefab != null)
+ {
+ (_, float baseRot) = GetModularPrefabAndRotation(grid, x, z, width, depth);
+ SpawnPrefab(endPrefab, x, yOffset, z, baseRot + endRotationOffset, container, "End");
+ return;
+ }
+
+ (GameObject modularPrefab, float yRotation) = GetModularPrefabAndRotation(grid, x, z, width, depth);
+ if (modularPrefab != null)
+ {
+ SpawnPrefab(modularPrefab, x, yOffset, z, yRotation, container, $"{type}");
+ }
+ }
+
private void SpawnPrefab(GameObject prefab, int x, float y, int z, float yRotation, Transform container, string namePrefix)
{
Vector3 localPosition = new Vector3(x * spacing, y, z * spacing);
@@ -140,7 +204,14 @@ namespace Baba_yaga.GameSetup.MazeRework
spawnedObj.transform.localPosition = localPosition;
spawnedObj.transform.localRotation = Quaternion.Euler(0f, yRotation, 0f);
spawnedObj.name = $"{namePrefix}_{x}_{z}";
- _spawnedObjects.Add(spawnedObj);
+
+ var pos = new Vector2Int(x, z);
+ if (_spawnedObjects.TryGetValue(pos, out GameObject existing))
+ {
+ if (Application.isPlaying) Destroy(existing);
+ else DestroyImmediate(existing);
+ }
+ _spawnedObjects[pos] = spawnedObj;
}
private (GameObject, float) GetModularPrefabAndRotation(MazeReworkCellType[,] grid, int x, int z, int width, int depth)