From 4ee2c5a2c2ad4b79c68eab018898c863ccaee14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20P=C4=9Bnkava?= Date: Wed, 25 Jun 2025 23:54:00 +0200 Subject: [PATCH 1/3] Level Generator --- 3D blobici/Assets/Levels.meta | 8 + 3D blobici/Assets/Levels/MapLayout1.asset | 19 ++ .../Assets/Levels/MapLayout1.asset.meta | 8 + 3D blobici/Assets/Prefabs/Levels.meta | 8 + .../Assets/Prefabs/Scripts/MapLayout.cs | 14 + .../Assets/Prefabs/Scripts/MapLayout.cs.meta | 2 + .../{CreateEntrances.cs => RoomHandler.cs} | 14 +- ...eEntrances.cs.meta => RoomHandler.cs.meta} | 0 3D blobici/Assets/Scenes/GenTest.unity | 6 +- .../Assets/Scripts/MapGen/MapGenManager.cs | 289 ++++++++++-------- .../ProjectSettings/ProjectSettings.asset | 164 ++++++++-- 11 files changed, 373 insertions(+), 159 deletions(-) create mode 100644 3D blobici/Assets/Levels.meta create mode 100644 3D blobici/Assets/Levels/MapLayout1.asset create mode 100644 3D blobici/Assets/Levels/MapLayout1.asset.meta create mode 100644 3D blobici/Assets/Prefabs/Levels.meta create mode 100644 3D blobici/Assets/Prefabs/Scripts/MapLayout.cs create mode 100644 3D blobici/Assets/Prefabs/Scripts/MapLayout.cs.meta rename 3D blobici/Assets/Prefabs/Scripts/{CreateEntrances.cs => RoomHandler.cs} (57%) rename 3D blobici/Assets/Prefabs/Scripts/{CreateEntrances.cs.meta => RoomHandler.cs.meta} (100%) diff --git a/3D blobici/Assets/Levels.meta b/3D blobici/Assets/Levels.meta new file mode 100644 index 0000000..e60f0a5 --- /dev/null +++ b/3D blobici/Assets/Levels.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a08c64b8785870549887368e2a81e2db +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/3D blobici/Assets/Levels/MapLayout1.asset b/3D blobici/Assets/Levels/MapLayout1.asset new file mode 100644 index 0000000..420c377 --- /dev/null +++ b/3D blobici/Assets/Levels/MapLayout1.asset @@ -0,0 +1,19 @@ +%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: 990d24eb53743184e9b379e68eec63e1, type: 3} + m_Name: MapLayout1 + m_EditorClassIdentifier: + grid: '123-2235454121 + + 412123 + + 11---4' diff --git a/3D blobici/Assets/Levels/MapLayout1.asset.meta b/3D blobici/Assets/Levels/MapLayout1.asset.meta new file mode 100644 index 0000000..d37e1e6 --- /dev/null +++ b/3D blobici/Assets/Levels/MapLayout1.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0c4ecdc10844c394b92ccd08ee36d635 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/3D blobici/Assets/Prefabs/Levels.meta b/3D blobici/Assets/Prefabs/Levels.meta new file mode 100644 index 0000000..d1e2543 --- /dev/null +++ b/3D blobici/Assets/Prefabs/Levels.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 78cd8de59ec022844907c273b05c0395 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/3D blobici/Assets/Prefabs/Scripts/MapLayout.cs b/3D blobici/Assets/Prefabs/Scripts/MapLayout.cs new file mode 100644 index 0000000..f6b7eb5 --- /dev/null +++ b/3D blobici/Assets/Prefabs/Scripts/MapLayout.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +[CreateAssetMenu(fileName = "MapLayout", menuName = "Scriptable Objects/MapLayout")] +public class MapLayout : ScriptableObject +{ + /// + /// 2D grid. Kad dek je jeden dek mapy, nahoe = vy Z. + /// slice = index prefab-u v MapGenManager.mapPrefab, + /// '-' = przdn msto, + /// 'S' = startovn mstnost. + /// + [TextArea(5, 20)] + public string grid; +} diff --git a/3D blobici/Assets/Prefabs/Scripts/MapLayout.cs.meta b/3D blobici/Assets/Prefabs/Scripts/MapLayout.cs.meta new file mode 100644 index 0000000..ea44525 --- /dev/null +++ b/3D blobici/Assets/Prefabs/Scripts/MapLayout.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 990d24eb53743184e9b379e68eec63e1 \ No newline at end of file diff --git a/3D blobici/Assets/Prefabs/Scripts/CreateEntrances.cs b/3D blobici/Assets/Prefabs/Scripts/RoomHandler.cs similarity index 57% rename from 3D blobici/Assets/Prefabs/Scripts/CreateEntrances.cs rename to 3D blobici/Assets/Prefabs/Scripts/RoomHandler.cs index 7731484..e44ef56 100644 --- a/3D blobici/Assets/Prefabs/Scripts/CreateEntrances.cs +++ b/3D blobici/Assets/Prefabs/Scripts/RoomHandler.cs @@ -1,11 +1,23 @@ using UnityEngine; -public class CreateEntrances : MonoBehaviour +/// +/// Object handling Room logic +/// +/// +public class RoomHandler : MonoBehaviour { [SerializeField] private GameObject wallNorth; [SerializeField] private GameObject wallSouth; [SerializeField] private GameObject wallEast; [SerializeField] private GameObject wallWest; + + /// + /// Creates entrances to corridors leading to other rooms + /// + /// + /// + /// + /// public void SetEntrances(bool northOpen, bool southOpen, bool eastOpen, bool westOpen) { wallNorth.SetActive(!northOpen); diff --git a/3D blobici/Assets/Prefabs/Scripts/CreateEntrances.cs.meta b/3D blobici/Assets/Prefabs/Scripts/RoomHandler.cs.meta similarity index 100% rename from 3D blobici/Assets/Prefabs/Scripts/CreateEntrances.cs.meta rename to 3D blobici/Assets/Prefabs/Scripts/RoomHandler.cs.meta diff --git a/3D blobici/Assets/Scenes/GenTest.unity b/3D blobici/Assets/Scenes/GenTest.unity index 307bf6f..cc48c48 100644 --- a/3D blobici/Assets/Scenes/GenTest.unity +++ b/3D blobici/Assets/Scenes/GenTest.unity @@ -149,20 +149,18 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: mapPrefab: + - {fileID: 819094401162878122, guid: 03f2147e5a186fc408b959faa2f97e86, type: 3} - {fileID: 2783560673348224804, guid: b7111ccd107e56741a9790a50ab8e190, type: 3} - {fileID: 7069902989848030098, guid: e8e0ba1faefe88f47b927a477b87ed22, type: 3} - {fileID: 8524395191423973796, guid: 37b1623de3a4b8140bc4fd60f59c6329, type: 3} - {fileID: 4362243528253867212, guid: 04cd18e800b8e854491a95529a91b3a1, type: 3} - {fileID: 5061069654894918266, guid: 6ac586441811a834fbf148a96b779734, type: 3} - StartPoint: {fileID: 819094401162878122, guid: 03f2147e5a186fc408b959faa2f97e86, type: 3} - EndPoint: {fileID: 819094401162878122, guid: 03f2147e5a186fc408b959faa2f97e86, type: 3} Player: {fileID: 6983871523237736218, guid: f0df263e5be65a041848d5a8bab85af1, type: 3} CorridorStraight: {fileID: 8047827979703692770, guid: 1a5d554c0c76caf4195cae47e098b79d, type: 3} CorridorStraightUnlit: {fileID: 2016417306107577256, guid: 92d9025262a022a499862d352c2724ee, type: 3} DoorCorridor: {fileID: 5603417387143431118, guid: 9eccbf5a500a0d2429e6008a713a49fd, type: 3} + layout: {fileID: 11400000, guid: 0c4ecdc10844c394b92ccd08ee36d635, type: 2} RoomDistance: 40 - minRoomsNumber: 3 - maxRoomsNumber: 7 --- !u!4 &23489964 Transform: m_ObjectHideFlags: 0 diff --git a/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs b/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs index 135f213..b153193 100644 --- a/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs +++ b/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using UnityEngine; using System.Linq; @@ -6,8 +6,6 @@ public class MapGenManager : MonoBehaviour { [Header("Room Prefabs")] [SerializeField] private List mapPrefab = new List(); - [SerializeField] private GameObject StartPoint; - [SerializeField] private GameObject EndPoint; [Header("Player")] [SerializeField] private GameObject Player; @@ -16,149 +14,190 @@ public class MapGenManager : MonoBehaviour [SerializeField] private GameObject CorridorStraight; [SerializeField] private GameObject CorridorStraightUnlit; [SerializeField] private GameObject DoorCorridor; - /*[SerializeField] private GameObject CorridorL; - [SerializeField] private GameObject CorridorT; - [SerializeField] private GameObject CorridorCross; - [SerializeField] private GameObject CorridorEnd;*/ + + [Header("Layout")] + [SerializeField] private MapLayout layout; [Header("Generation Settings")] [SerializeField] private int RoomDistance = 3; - [SerializeField] private int minRoomsNumber = 3; - [SerializeField] private int maxRoomsNumber = 7; - private List roomPositions = new List(); - private List placedRooms = new List(); + private Dictionary gridToRoom = new(); - void Start() + private readonly Vector3 roomOriginOffset = Vector3.zero; + + void Start() => GenerateFromLayout(); + + private void GenerateFromLayout() { - MapGen(); - } - - private void MapGen() - { - // Clear previous rooms and positions - roomPositions.Clear(); - placedRooms.Clear(); - - // Add Start Point - Vector3 startPos = new Vector3(0, 0, 0); - GameObject startPoint = Instantiate(StartPoint, startPos, Quaternion.identity, transform); - roomPositions.Add(startPos); - placedRooms.Add(startPoint); - startPoint.GetComponent().SetEntrances(false, false, true, false); - - // Instantiate the player at the starting position - GameObject player = Instantiate(Player, new Vector3(startPos.x, 1, startPos.z - 5), Quaternion.identity, transform); - - // Generate a random number of rooms - int roomCount = Random.Range(minRoomsNumber, maxRoomsNumber); - - // Place Generate Rooms - for (int i = 0; i < roomCount; i++) + if (layout == null || string.IsNullOrWhiteSpace(layout.grid)) { - GameObject roomPrefab = mapPrefab[Random.Range(0, mapPrefab.Count)]; - Vector3 roomPos = GetGridPosition(roomPrefab); - GameObject room = Instantiate(roomPrefab, roomPos, Quaternion.identity, transform); - placedRooms.Add(room); - roomPositions.Add(roomPos); - room.GetComponent().SetEntrances(false, false, true, true); + Debug.LogError("Layout asset není přiřazený nebo je prázdný!"); + return; } - // Add End Point - GameObject endPoint = Instantiate(EndPoint, GetGridPosition(EndPoint), Quaternion.identity, transform); - roomPositions.Add(endPoint.transform.position); - placedRooms.Add(endPoint); - endPoint.GetComponent().SetEntrances(false, false, false, false); + gridToRoom.Clear(); - // Create corridors between rooms - for (int i = 0; i < roomPositions.Count - 1; i++) + /* ---------- 0) VYTVOŘÍME SPAWN-ROOM ---------- */ + GameObject spawnPrefab = mapPrefab[0]; + PrefabSize spawnSizeComp = spawnPrefab.GetComponent(); + Vector3 cellSize = spawnSizeComp != null + ? new Vector3(spawnSizeComp.prefabSize.x, 0, spawnSizeComp.prefabSize.y) + : new Vector3(10, 0, 10); // fallback + + Vector3 spawnPos = roomOriginOffset; + GameObject spawnRoom = Instantiate(spawnPrefab, spawnPos, Quaternion.identity, transform); + gridToRoom[new Vector2Int(0, 0)] = spawnRoom; + + // hráče necháme na spawnu + if (Player != null) { - Vector3 startRoomPos = roomPositions[i]; - PrefabSize startRoom = placedRooms[i].GetComponent(); - Vector3 endRoomPos = roomPositions[i + 1]; - PrefabSize endRoom = placedRooms[i + 1].GetComponent(); - Vector3 firstCorridorPos = new Vector3( - startRoomPos.x, - startRoomPos.y, - startRoomPos.z + startRoom.prefabSize.y / 2 - ); - Vector3 lastCorridorPos = new Vector3( - endRoomPos.x, - endRoomPos.y, - endRoomPos.z - endRoom.prefabSize.y / 2 - ); - CreateCorridor(firstCorridorPos, lastCorridorPos); + Vector3 playerPos = spawnPos + new Vector3(0, 1, 3); + Instantiate(Player, playerPos, Quaternion.identity, transform); } - } - private Vector3 GetGridPosition(GameObject roomPrefab) - { - Vector3 lastRoomPos = roomPositions[roomPositions.Count - 1]; - PrefabSize lastRoom = placedRooms[placedRooms.Count - 1].GetComponent(); - PrefabSize roomSize = roomPrefab.GetComponent(); + /* ---------- 1) PARSOVÁNÍ LAYOUTU ---------- */ + string[] lines = layout.grid + .Split('\n') + .Select(l => l.TrimEnd('\r')) + .Where(l => !string.IsNullOrEmpty(l)) + .ToArray(); - Vector3 roomPos = new Vector3( - lastRoomPos.x, - lastRoomPos.y - 0.01f, - lastRoomPos.z + lastRoom.prefabSize.y / 2f + roomSize.prefabSize.y / 2f + RoomDistance - ); + int rows = lines.Length; - return roomPos; - } - - private void CreateCorridor(Vector3 start, Vector3 end) - { - // Calculate the distance - float distance = Vector3.Distance(start, end); - PrefabSize corridorSize = CorridorStraight.GetComponent(); - PrefabSize corridorUnlitSize = CorridorStraightUnlit.GetComponent(); - PrefabSize doorSize = DoorCorridor.GetComponent(); - - // Calculate the number of corridors needed - int corridorCount = Mathf.FloorToInt(distance / corridorSize.prefabSize.y); - Debug.Log($"Creating {corridorCount} corridors from {start} to {end}"); - - // Create corridors - //Start with door - if (corridorCount > 0) + /* ---------- 2) SMYČKA PŘES GRID ------------- */ + for (int z = 0; z < rows; z++) { - Vector3 doorPos = new Vector3( - start.x, - start.y, - start.z + doorSize.prefabSize.y * 0.5f - ); - Quaternion doorRotation = Quaternion.Euler(0, 0, 0); - GameObject doorCorridor = Instantiate(DoorCorridor, doorPos, doorRotation, transform); - doorCorridor.GetComponent().OpenDoor(); - - - for (int i = 1; i < corridorCount; i++) + string line = lines[rows - 1 - z]; // dolní řádek layoutu = nejnižší Z v textu + for (int x = 0; x < line.Length; x++) { - if (i % 2 != 0) + char c = line[x]; + if (c == '-') continue; // prázdné místo + + if (!char.IsDigit(c)) { - // Create straight corridor - Vector3 pos = new Vector3( - start.x, - start.y, - start.z + i * corridorSize.prefabSize.y + corridorSize.prefabSize.y * 0.5f - ); - Quaternion rotation = Quaternion.Euler(0, 0, 0); - GameObject corridor = Instantiate(CorridorStraight, pos, rotation, transform); + Debug.LogWarning($"Neznámý znak {c} v layoutu – ignorováno."); + continue; } - else + + int index = c - '0'; + if (index >= mapPrefab.Count) { - // Create unlit corridor - Vector3 pos = new Vector3( - start.x, - start.y, - start.z + i * corridorUnlitSize.prefabSize.y + corridorUnlitSize.prefabSize.y * 0.5f - ); - Quaternion rotation = Quaternion.Euler(0, 0, 0); - GameObject corridorUnlit = Instantiate(CorridorStraightUnlit, pos, rotation, transform); + Debug.LogWarning($"Index {index} mimo rozsah mapPrefab!"); + continue; } - } + + GameObject prefab = mapPrefab[index]; + + PrefabSize roomSize = prefab.GetComponent(); + Vector3 rCell = roomSize != null + ? new Vector3(roomSize.prefabSize.x, 0, roomSize.prefabSize.y) + : cellSize; // použij spawn-size jako fallback + + Vector3 worldPos = roomOriginOffset + new Vector3( + x * (cellSize.x + RoomDistance), + 0, + (z + 1) * (cellSize.z + RoomDistance)); + + GameObject room = Instantiate(prefab, worldPos, Quaternion.identity, transform); + gridToRoom[new Vector2Int(x, z + 1)] = room; + } + } + + /* ---------- 3) OTEVŘEME ZDI VŠEM MÍSTNOSTEM ---------- */ + foreach (var kvp in gridToRoom) + { + Vector2Int g = kvp.Key; + RoomHandler rh = kvp.Value.GetComponent(); + + bool north = gridToRoom.ContainsKey(g + Vector2Int.left); + bool south = gridToRoom.ContainsKey(g + Vector2Int.right); + bool east = gridToRoom.ContainsKey(g + Vector2Int.up); + bool west = gridToRoom.ContainsKey(g + Vector2Int.down); + + rh.SetEntrances(northOpen: north, + southOpen: south, + eastOpen: east, + westOpen: west); + } + + BuildCorridors(); + } + + private void BuildCorridors() + { + // velikosti přímých dílů + float straightLengthZ = CorridorStraight.GetComponent().prefabSize.y; + float straightLengthX = CorridorStraight.GetComponent().prefabSize.x; + + // Abychom každý pár řešili jen jednou, projdeme jen Right a Up souseda + Vector2Int[] stepDirs = { Vector2Int.right, Vector2Int.up }; + + foreach (var kvp in gridToRoom) + { + Vector2Int cell = kvp.Key; + GameObject roomA = kvp.Value; + + foreach (Vector2Int dir in stepDirs) + { + Vector2Int neighKey = cell + dir; + if (!gridToRoom.TryGetValue(neighKey, out GameObject roomB)) + continue; // není soused – žádná chodba + + // 1) Urči směr v prostoru + Vector3 axis, axisNeg; // +směr a −směr podél stejné osy + float halfA, halfB; // půl šířky/hloubky pro start/end bod + Quaternion corridorRot; // natočení pro koridor + + if (dir == Vector2Int.right) // grid +X (svět +X) + { + axis = Vector3.right; + axisNeg = Vector3.left; + halfA = roomA.GetComponent().prefabSize.x * 0.5f; + halfB = roomB.GetComponent().prefabSize.x * 0.5f; + corridorRot = Quaternion.Euler(0, 90, 0); // koridor leží po X + } + else // dir == Vector2Int.up → svět +Z + { + axis = Vector3.forward; + axisNeg = Vector3.back; + halfA = roomA.GetComponent().prefabSize.y * 0.5f; + halfB = roomB.GetComponent().prefabSize.y * 0.5f; + corridorRot = Quaternion.identity; // prefab míří po +Z + } + + // 2) Vypočti start a end body (středy zdí) + Vector3 startPos = roomA.transform.position + axis * halfA; + Vector3 endPos = roomB.transform.position + axisNeg * halfB; + + // 3) Vytvoř sekvenci dílů + CreateStraightCorridor(startPos, endPos, axis, corridorRot, + straightLengthZ, straightLengthX); + } + } + } + + /// Vytvoří přímý koridor od startu k endu podél 'axis'. + private void CreateStraightCorridor( + Vector3 start, Vector3 end, Vector3 axis, Quaternion rot, + float stepLenZ, float stepLenX) + { + float fullDist = Vector3.Distance(start, end); + float stepLen = Mathf.Approximately(Mathf.Abs(axis.z), 1f) ? stepLenZ : stepLenX; + + int segmentCount = Mathf.Max(1, Mathf.FloorToInt(fullDist / stepLen)); + + // 0) dveřní díl + Vector3 segPos = start + axis * (stepLen * 0.5f); + GameObject door = Instantiate(DoorCorridor, segPos, rot, transform); + door.GetComponent()?.OpenDoor(); // pokud existuje + + // 1) zbytek – střídavě osvětlené / neosvětlené + for (int i = 1; i < segmentCount; i++) + { + GameObject prefab = (i % 2 == 0) ? CorridorStraight : CorridorStraightUnlit; + + segPos = start + axis * (i * stepLen + stepLen * 0.5f); + Instantiate(prefab, segPos, rot, transform); } - // If there is not enough space to create corridors, throw an exception - else throw new System.Exception("Not enough space to create corridors"); } } \ No newline at end of file diff --git a/3D blobici/ProjectSettings/ProjectSettings.asset b/3D blobici/ProjectSettings/ProjectSettings.asset index 37ed0d9..9adc1a6 100644 --- a/3D blobici/ProjectSettings/ProjectSettings.asset +++ b/3D blobici/ProjectSettings/ProjectSettings.asset @@ -3,7 +3,7 @@ --- !u!129 &1 PlayerSettings: m_ObjectHideFlags: 0 - serializedVersion: 26 + serializedVersion: 28 productGUID: 2a70d1bb4d031b249adebc15318b6bd4 AndroidProfiler: 0 AndroidFilterTouchesWhenObscured: 0 @@ -49,6 +49,7 @@ PlayerSettings: m_StereoRenderingPath: 0 m_ActiveColorSpace: 1 unsupportedMSAAFallback: 0 + m_SpriteBatchMaxVertexCount: 65535 m_SpriteBatchVertexThreshold: 300 m_MTRendering: 1 mipStripping: 0 @@ -70,17 +71,18 @@ PlayerSettings: androidRenderOutsideSafeArea: 1 androidUseSwappy: 1 androidBlitType: 0 - androidResizableWindow: 0 + androidResizeableActivity: 0 androidDefaultWindowWidth: 1920 androidDefaultWindowHeight: 1080 androidMinimumWindowWidth: 400 androidMinimumWindowHeight: 300 androidFullscreenMode: 1 androidAutoRotationBehavior: 1 + androidPredictiveBackSupport: 0 + androidApplicationEntry: 1 defaultIsNativeResolution: 1 macRetinaSupport: 1 runInBackground: 1 - captureSingleScreen: 0 muteOtherAudioSources: 0 Prepare IOS For Recording: 0 Force IOS Speakers When Recording: 0 @@ -96,6 +98,7 @@ PlayerSettings: useMacAppStoreValidation: 0 macAppStoreCategory: public.app-category.games gpuSkinning: 1 + meshDeformation: 2 xboxPIXTextureCapture: 0 xboxEnableAvatar: 0 xboxEnableKinect: 0 @@ -127,10 +130,8 @@ PlayerSettings: switchAllowGpuScratchShrinking: 0 switchNVNMaxPublicTextureIDCount: 0 switchNVNMaxPublicSamplerIDCount: 0 - switchNVNGraphicsFirmwareMemory: 32 switchMaxWorkerMultiple: 8 - stadiaPresentMode: 0 - stadiaTargetFramerate: 0 + switchNVNGraphicsFirmwareMemory: 32 vulkanNumSwapchainBuffers: 3 vulkanEnableSetSRGBWrite: 0 vulkanEnablePreTransform: 1 @@ -160,6 +161,7 @@ PlayerSettings: resetResolutionOnWindowResize: 0 androidSupportedAspectRatio: 1 androidMaxAspectRatio: 2.1 + androidMinAspectRatio: 1 applicationIdentifier: {} buildNumber: Standalone: 0 @@ -168,7 +170,7 @@ PlayerSettings: tvOS: 0 overrideDefaultApplicationIdentifier: 0 AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 22 + AndroidMinSdkVersion: 23 AndroidTargetSdkVersion: 0 AndroidPreferredInstallLocation: 1 aotOptions: @@ -178,16 +180,18 @@ PlayerSettings: ForceInternetPermission: 0 ForceSDCardPermission: 0 CreateWallpaper: 0 - APKExpansionFiles: 0 + androidSplitApplicationBinary: 0 keepLoadedShadersAlive: 0 StripUnusedMeshComponents: 1 strictShaderVariantMatching: 0 VertexChannelCompressionMask: 4054 iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 12.0 + iOSSimulatorArchitecture: 0 + iOSTargetOSVersionString: 13.0 tvOSSdkVersion: 0 + tvOSSimulatorArchitecture: 0 tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: 12.0 + tvOSTargetOSVersionString: 13.0 VisionOSSdkVersion: 0 VisionOSTargetOSVersionString: 1.0 uIPrerenderedIcon: 0 @@ -214,7 +218,6 @@ PlayerSettings: rgba: 0 iOSLaunchScreenFillPct: 100 iOSLaunchScreenSize: 100 - iOSLaunchScreenCustomXibPath: iOSLaunchScreeniPadType: 0 iOSLaunchScreeniPadImage: {fileID: 0} iOSLaunchScreeniPadBackgroundColor: @@ -222,7 +225,6 @@ PlayerSettings: rgba: 0 iOSLaunchScreeniPadFillPct: 100 iOSLaunchScreeniPadSize: 100 - iOSLaunchScreeniPadCustomXibPath: iOSLaunchScreenCustomStoryboardPath: iOSLaunchScreeniPadCustomStoryboardPath: iOSDeviceRequirements: [] @@ -259,12 +261,12 @@ PlayerSettings: useCustomGradleSettingsTemplate: 0 useCustomProguardFile: 0 AndroidTargetArchitectures: 1 - AndroidTargetDevices: 0 AndroidSplashScreenScale: 0 androidSplashScreen: {fileID: 0} AndroidKeystoreName: AndroidKeyaliasName: AndroidEnableArmv9SecurityFeatures: 0 + AndroidEnableArm64MTE: 0 AndroidBuildApkPerCpuArchitecture: 0 AndroidTVCompatibility: 0 AndroidIsGame: 1 @@ -277,13 +279,106 @@ PlayerSettings: height: 180 banner: {fileID: 0} androidGamepadSupportLevel: 0 - chromeosInputEmulation: 1 AndroidMinifyRelease: 0 AndroidMinifyDebug: 0 AndroidValidateAppBundleSize: 1 AndroidAppBundleSizeToValidate: 150 + AndroidReportGooglePlayAppDependencies: 1 + androidSymbolsSizeThreshold: 800 m_BuildTargetIcons: [] - m_BuildTargetPlatformIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: Android + m_Icons: + - m_Textures: [] + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 0 + m_SubKind: m_BuildTargetBatching: - m_BuildTarget: Standalone m_StaticBatching: 1 @@ -363,18 +458,14 @@ PlayerSettings: iPhone: 1 tvOS: 1 m_BuildTargetGroupLightmapEncodingQuality: - - m_BuildTarget: Android + - serializedVersion: 2 + m_BuildTarget: Android m_EncodingQuality: 1 - - m_BuildTarget: iPhone + - serializedVersion: 2 + m_BuildTarget: iOS m_EncodingQuality: 1 - - m_BuildTarget: tvOS - m_EncodingQuality: 1 - m_BuildTargetGroupHDRCubemapEncodingQuality: - - m_BuildTarget: Android - m_EncodingQuality: 1 - - m_BuildTarget: iPhone - m_EncodingQuality: 1 - - m_BuildTarget: tvOS + - serializedVersion: 2 + m_BuildTarget: tvOS m_EncodingQuality: 1 m_BuildTargetGroupLightmapSettings: [] m_BuildTargetGroupLoadStoreDebugModeSettings: [] @@ -386,11 +477,13 @@ PlayerSettings: - m_BuildTarget: tvOS m_Encoding: 1 m_BuildTargetDefaultTextureCompressionFormat: - - m_BuildTarget: Android - m_Format: 3 + - serializedVersion: 3 + m_BuildTarget: Android + m_Formats: 03000000 playModeTestRunnerEnabled: 0 runPlayModeTestAsEditModeTest: 0 actionOnDotNetUnhandledException: 1 + editorGfxJobOverride: 1 enableInternalProfiler: 0 logObjCUncaughtExceptions: 1 enableCrashReportAPI: 0 @@ -398,7 +491,7 @@ PlayerSettings: locationUsageDescription: microphoneUsageDescription: bluetoothUsageDescription: - macOSTargetOSVersion: 10.13.0 + macOSTargetOSVersion: 11.0 switchNMETAOverride: switchNetLibKey: switchSocketMemoryPoolSize: 6144 @@ -536,12 +629,14 @@ PlayerSettings: switchSocketBufferEfficiency: 4 switchSocketInitializeEnabled: 1 switchNetworkInterfaceManagerInitializeEnabled: 1 + switchDisableHTCSPlayerConnection: 0 switchUseNewStyleFilepaths: 1 switchUseLegacyFmodPriorities: 0 switchUseMicroSleepForYield: 1 switchEnableRamDiskSupport: 0 switchMicroSleepForYieldTime: 25 switchRamDiskSpaceSize: 12 + switchUpgradedPlayerSettingsToNMETA: 0 ps4NPAgeRating: 12 ps4NPTitleSecret: ps4NPTrophyPackPath: @@ -644,13 +739,19 @@ PlayerSettings: webGLMemoryLinearGrowthStep: 16 webGLMemoryGeometricGrowthStep: 0.2 webGLMemoryGeometricGrowthCap: 96 + webGLEnableWebGPU: 0 webGLPowerPreference: 2 + webGLWebAssemblyTable: 0 + webGLWebAssemblyBigInt: 0 + webGLCloseOnQuit: 0 + webWasm2023: 0 scriptingDefineSymbols: {} additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: {} il2cppCompilerConfiguration: {} il2cppCodeGeneration: {} + il2cppStacktraceInformation: {} managedStrippingLevel: EmbeddedLinux: 1 GameCoreScarlett: 1 @@ -675,6 +776,7 @@ PlayerSettings: gcIncremental: 1 gcWBarrierValidation: 0 apiCompatibilityLevelPerPlatform: {} + editorAssembliesCompatibilityLevel: 1 m_RenderingPath: 1 m_MobileRenderingPath: 1 metroPackageName: 3D blobici @@ -749,9 +851,11 @@ PlayerSettings: hmiPlayerDataPath: hmiForceSRGBBlit: 1 embeddedLinuxEnableGamepadInput: 1 - hmiLogStartupTiming: 0 hmiCpuConfiguration: + hmiLogStartupTiming: 0 + qnxGraphicConfPath: apiCompatibilityLevel: 6 + captureStartupLogs: {} activeInputHandler: 0 windowsGamepadBackendHint: 0 cloudProjectId: @@ -765,3 +869,5 @@ PlayerSettings: platformRequiresReadableAssets: 0 virtualTexturingSupportEnabled: 0 insecureHttpOption: 0 + androidVulkanDenyFilterList: [] + androidVulkanAllowFilterList: [] From 4684d7f64fd57275589b1af2bbb3a36427e503d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20P=C4=9Bnkava?= Date: Fri, 27 Jun 2025 07:13:19 +0200 Subject: [PATCH 2/3] Downscale player (for now) --- 3D blobici/Assets/Prefabs/PlayerContainer.prefab | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/3D blobici/Assets/Prefabs/PlayerContainer.prefab b/3D blobici/Assets/Prefabs/PlayerContainer.prefab index 408d10e..84e6d98 100644 --- a/3D blobici/Assets/Prefabs/PlayerContainer.prefab +++ b/3D blobici/Assets/Prefabs/PlayerContainer.prefab @@ -187,8 +187,8 @@ Transform: serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1.8, y: 1.8, z: 1.8} - m_ConstrainProportionsScale: 0 + m_LocalScale: {x: 1.5, y: 1.5, z: 1.5} + m_ConstrainProportionsScale: 1 m_Children: - {fileID: 1872598832695960773} - {fileID: 1302341320372733696} From 0cc8c76a48789c8df1d047f3564276db5bdd7cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20P=C4=9Bnkava?= Date: Fri, 27 Jun 2025 07:13:39 +0200 Subject: [PATCH 3/3] Map gen changes --- .../Assets/Scripts/MapGen/MapGenManager.cs | 278 +++++++++++------- 1 file changed, 165 insertions(+), 113 deletions(-) diff --git a/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs b/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs index b153193..3906ed1 100644 --- a/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs +++ b/3D blobici/Assets/Scripts/MapGen/MapGenManager.cs @@ -1,11 +1,13 @@ using System.Collections.Generic; using UnityEngine; using System.Linq; +using System.Runtime.CompilerServices; public class MapGenManager : MonoBehaviour { + /* ------------------ INSPECTOR FIELDS ------------------ */ [Header("Room Prefabs")] - [SerializeField] private List mapPrefab = new List(); + [SerializeField] private List mapPrefab = new(); [Header("Player")] [SerializeField] private GameObject Player; @@ -21,12 +23,13 @@ public class MapGenManager : MonoBehaviour [Header("Generation Settings")] [SerializeField] private int RoomDistance = 3; - private Dictionary gridToRoom = new(); - + private readonly Dictionary gridToRoom = new(); private readonly Vector3 roomOriginOffset = Vector3.zero; + void Start() => GenerateFromLayout(); + private void GenerateFromLayout() { if (layout == null || string.IsNullOrWhiteSpace(layout.grid)) @@ -37,167 +40,216 @@ public class MapGenManager : MonoBehaviour gridToRoom.Clear(); - /* ---------- 0) VYTVOŘÍME SPAWN-ROOM ---------- */ + /* ----------- Create a spawn room ----------- */ GameObject spawnPrefab = mapPrefab[0]; - PrefabSize spawnSizeComp = spawnPrefab.GetComponent(); - Vector3 cellSize = spawnSizeComp != null - ? new Vector3(spawnSizeComp.prefabSize.x, 0, spawnSizeComp.prefabSize.y) - : new Vector3(10, 0, 10); // fallback + Vector3 cellSize = GetPrefabXZ(spawnPrefab); + + /* ---------- Text layout to grid ---------- */ + string[] lines = layout.grid + .Split('\n') + .Select(line => line.TrimEnd('\r')) + .Where(line => !string.IsNullOrWhiteSpace(line)) + .ToArray(); + + + Vector2 firstRoomPos = GetFirstOrLastRoom(lines); + int bottomRowIdx = (int)firstRoomPos.y; + int spawnGridX = (int)firstRoomPos.x; + + /* ---------- Create spawn room properly ---------- */ + Vector3 spawnPos = roomOriginOffset + new Vector3( + spawnGridX * (cellSize.x + RoomDistance), // X + 0, + 0); - Vector3 spawnPos = roomOriginOffset; GameObject spawnRoom = Instantiate(spawnPrefab, spawnPos, Quaternion.identity, transform); - gridToRoom[new Vector2Int(0, 0)] = spawnRoom; + gridToRoom[new Vector2Int(spawnGridX, 0)] = spawnRoom; - // hráče necháme na spawnu - if (Player != null) + /* ---------- Instantiate player ---------- */ + if (Player) { Vector3 playerPos = spawnPos + new Vector3(0, 1, 3); Instantiate(Player, playerPos, Quaternion.identity, transform); } - /* ---------- 1) PARSOVÁNÍ LAYOUTU ---------- */ - string[] lines = layout.grid - .Split('\n') - .Select(l => l.TrimEnd('\r')) - .Where(l => !string.IsNullOrEmpty(l)) - .ToArray(); + /* ---------- Build the rest of rooms ---------- */ - int rows = lines.Length; + BuildRooms(lines, bottomRowIdx, cellSize); - /* ---------- 2) SMYČKA PŘES GRID ------------- */ - for (int z = 0; z < rows; z++) + /* ---------- Open walls based on aproximity to other rooms ---------- */ + foreach (var keyValuePair in gridToRoom) { - string line = lines[rows - 1 - z]; // dolní řádek layoutu = nejnižší Z v textu - for (int x = 0; x < line.Length; x++) - { - char c = line[x]; - if (c == '-') continue; // prázdné místo - - if (!char.IsDigit(c)) - { - Debug.LogWarning($"Neznámý znak {c} v layoutu – ignorováno."); - continue; - } - - int index = c - '0'; - if (index >= mapPrefab.Count) - { - Debug.LogWarning($"Index {index} mimo rozsah mapPrefab!"); - continue; - } - - GameObject prefab = mapPrefab[index]; - - PrefabSize roomSize = prefab.GetComponent(); - Vector3 rCell = roomSize != null - ? new Vector3(roomSize.prefabSize.x, 0, roomSize.prefabSize.y) - : cellSize; // použij spawn-size jako fallback - - Vector3 worldPos = roomOriginOffset + new Vector3( - x * (cellSize.x + RoomDistance), - 0, - (z + 1) * (cellSize.z + RoomDistance)); - - GameObject room = Instantiate(prefab, worldPos, Quaternion.identity, transform); - gridToRoom[new Vector2Int(x, z + 1)] = room; - } - } - - /* ---------- 3) OTEVŘEME ZDI VŠEM MÍSTNOSTEM ---------- */ - foreach (var kvp in gridToRoom) - { - Vector2Int g = kvp.Key; - RoomHandler rh = kvp.Value.GetComponent(); + Vector2Int g = keyValuePair.Key; + RoomHandler rh = keyValuePair.Value.GetComponent(); bool north = gridToRoom.ContainsKey(g + Vector2Int.left); bool south = gridToRoom.ContainsKey(g + Vector2Int.right); bool east = gridToRoom.ContainsKey(g + Vector2Int.up); bool west = gridToRoom.ContainsKey(g + Vector2Int.down); - rh.SetEntrances(northOpen: north, - southOpen: south, - eastOpen: east, - westOpen: west); + rh.SetEntrances(northOpen: north, southOpen: south, eastOpen: east, westOpen: west); } + /* ---------- 5) CHODBY ---------- */ BuildCorridors(); } + /// + /// Build corridors between rooms + /// + /// private void BuildCorridors() { - // velikosti přímých dílů - float straightLengthZ = CorridorStraight.GetComponent().prefabSize.y; - float straightLengthX = CorridorStraight.GetComponent().prefabSize.x; - - // Abychom každý pár řešili jen jednou, projdeme jen Right a Up souseda + float straightZ = CorridorStraight.GetComponent().prefabSize.y; + float straightX = CorridorStraight.GetComponent().prefabSize.x; Vector2Int[] stepDirs = { Vector2Int.right, Vector2Int.up }; - foreach (var kvp in gridToRoom) + foreach (var kv in gridToRoom) { - Vector2Int cell = kvp.Key; - GameObject roomA = kvp.Value; + Vector2Int cell = kv.Key; + GameObject roomA = kv.Value; foreach (Vector2Int dir in stepDirs) { - Vector2Int neighKey = cell + dir; - if (!gridToRoom.TryGetValue(neighKey, out GameObject roomB)) - continue; // není soused – žádná chodba + Vector2Int nKey = cell + dir; + if (!gridToRoom.TryGetValue(nKey, out GameObject roomB)) continue; - // 1) Urči směr v prostoru - Vector3 axis, axisNeg; // +směr a −směr podél stejné osy - float halfA, halfB; // půl šířky/hloubky pro start/end bod - Quaternion corridorRot; // natočení pro koridor + Vector3 axis, axisNeg; + float halfA, halfB; + Quaternion rot; - if (dir == Vector2Int.right) // grid +X (svět +X) + if (dir == Vector2Int.right) { - axis = Vector3.right; - axisNeg = Vector3.left; - halfA = roomA.GetComponent().prefabSize.x * 0.5f; - halfB = roomB.GetComponent().prefabSize.x * 0.5f; - corridorRot = Quaternion.Euler(0, 90, 0); // koridor leží po X + axis = Vector3.right; axisNeg = Vector3.left; + halfA = GetPrefabXZ(roomA).x * 0.5f; + halfB = GetPrefabXZ(roomB).x * 0.5f; + rot = Quaternion.Euler(0, 90, 0); } - else // dir == Vector2Int.up → svět +Z + else { - axis = Vector3.forward; - axisNeg = Vector3.back; - halfA = roomA.GetComponent().prefabSize.y * 0.5f; - halfB = roomB.GetComponent().prefabSize.y * 0.5f; - corridorRot = Quaternion.identity; // prefab míří po +Z + axis = Vector3.forward; axisNeg = Vector3.back; + halfA = GetPrefabXZ(roomA).z * 0.5f; + halfB = GetPrefabXZ(roomB).z * 0.5f; + rot = Quaternion.identity; } - // 2) Vypočti start a end body (středy zdí) - Vector3 startPos = roomA.transform.position + axis * halfA; - Vector3 endPos = roomB.transform.position + axisNeg * halfB; + Vector3 start = roomA.transform.position + axis * halfA; + Vector3 end = roomB.transform.position + axisNeg * halfB; - // 3) Vytvoř sekvenci dílů - CreateStraightCorridor(startPos, endPos, axis, corridorRot, - straightLengthZ, straightLengthX); + CreateStraightCorridor(start, end, axis, rot, straightZ, straightX); } } } - /// Vytvoří přímý koridor od startu k endu podél 'axis'. + + /// + /// Build all rooms based on the layout grid + /// + /// + /// + /// + private void BuildRooms(string[] lines, int bottomRowIdx, Vector3 cellSize) + { + int rows = lines.Length; + + for (int rowsIter = 0; rowsIter < rows; rowsIter++) + { + string line = lines[rowsIter]; + int gridZ = bottomRowIdx - rowsIter + 1; + + for (int x = 0; x < line.Length; x++) + { + char ch = line[x]; + if (ch == '-') continue; + if (!char.IsDigit(ch)) + { + Debug.LogWarning($"Neznámý znak '{ch}' v layoutu – ignoruji."); + continue; + } + + int idx = ch - '0'; + if (idx >= mapPrefab.Count) + { + Debug.LogWarning($"Index {idx} mimo rozsah mapPrefab!"); + continue; + } + + GameObject prefab = mapPrefab[idx]; + Vector3 worldPos = roomOriginOffset + new Vector3( + x * (cellSize.x + RoomDistance), + 0, + gridZ * (cellSize.z + RoomDistance)); + + GameObject room = Instantiate(prefab, worldPos, Quaternion.identity, transform); + gridToRoom[new Vector2Int(x, gridZ)] = room; + } + } + } + + /// + /// Returns the (x, y) coordinates of the room with closest aproximity to spawn or the furthest aproximity to spawn + /// + /// + /// + /// Vector2(x, y) where x is the line index and y is the column index + private Vector2 GetFirstOrLastRoom(string[] lines, bool last = false) + { + int colIdx = -1; + int spawnGridX = 0; + + int rows = lines.Length; + + for (int rowsIter = rows - 1; rowsIter >= 0; rowsIter--) + { + string line = lines[rowsIter]; + for (int c = 0; c < line.Length; c++) + { + if (char.IsDigit(line[c])) + { + colIdx = rowsIter; + spawnGridX = c; + break; + } + } + if (colIdx != -1) break; + } + if (colIdx == -1) + { + Debug.LogError("Layout neobsahuje žádnou číslici (místnost)!"); + return Vector2.zero; + } + + return new Vector2(spawnGridX, colIdx); + } + private void CreateStraightCorridor( Vector3 start, Vector3 end, Vector3 axis, Quaternion rot, float stepLenZ, float stepLenX) { - float fullDist = Vector3.Distance(start, end); - float stepLen = Mathf.Approximately(Mathf.Abs(axis.z), 1f) ? stepLenZ : stepLenX; + float dist = Vector3.Distance(start, end); + float step = Mathf.Approximately(Mathf.Abs(axis.z), 1f) ? stepLenZ : stepLenX; + int count = Mathf.Max(1, Mathf.FloorToInt(dist / step)); - int segmentCount = Mathf.Max(1, Mathf.FloorToInt(fullDist / stepLen)); + Vector3 segPos = start + axis * (step * 0.5f); + var door = Instantiate(DoorCorridor, segPos, rot, transform); + door.GetComponent()?.OpenDoor(); - // 0) dveřní díl - Vector3 segPos = start + axis * (stepLen * 0.5f); - GameObject door = Instantiate(DoorCorridor, segPos, rot, transform); - door.GetComponent()?.OpenDoor(); // pokud existuje - - // 1) zbytek – střídavě osvětlené / neosvětlené - for (int i = 1; i < segmentCount; i++) + for (int i = 1; i < count; i++) { GameObject prefab = (i % 2 == 0) ? CorridorStraight : CorridorStraightUnlit; - - segPos = start + axis * (i * stepLen + stepLen * 0.5f); + segPos = start + axis * (i * step + step * 0.5f); Instantiate(prefab, segPos, rot, transform); } } -} \ No newline at end of file + + /// + /// Returns the size of a prefab room + /// + /// Choose a prefab from available ones + /// Size of the prefab as Vector3 + private static Vector3 GetPrefabXZ(GameObject prefab) + { + var ps = prefab.GetComponent(); + return ps ? new Vector3(ps.prefabSize.x, 0, ps.prefabSize.y) : new Vector3(10, 0, 10); + } +}