From b54e0162836afe48b02b2d3afcae193376b52a4b Mon Sep 17 00:00:00 2001 From: dal4segno Date: Sat, 31 Jan 2026 21:36:56 +0900 Subject: [PATCH] =?UTF-8?q?=ED=8F=AC=ED=83=88=EC=9D=B4=20=EA=B8=80?= =?UTF-8?q?=EB=A1=9C=EB=B2=8C=20=ED=83=80=EC=9D=B4=EB=A8=B8=20=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=ED=81=B4=EC=97=90=20=EB=A7=9E=EC=B6=B0=20=EC=9B=A8?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=A5=BC=20=EC=86=8C=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 시작 코스트 4, 웨이브당 증가량 10% --- .gitignore | 5 +- Assembly-CSharp-Editor.csproj | 18 +-- Assembly-CSharp.csproj | 23 ++-- .../Monster/Monster101.asset | 2 +- .../Monster/Monster102.asset | 2 +- Assets/Scenes/GameMain.unity | 44 +++++- Assets/Scripts/Editor/EnemyPortalEditor.cs | 77 +++++++++++ .../Scripts/Editor/EnemyPortalEditor.cs.meta | 2 + Assets/Scripts/EnemyPortal.cs | 125 ++++++++++++++---- ExternAttributes.Editor.csproj | 1 - FlatKit.Utils.Editor.csproj | 1 - ...y.RenderPipelines.Universal.Runtime.csproj | 7 +- 12 files changed, 252 insertions(+), 55 deletions(-) create mode 100644 Assets/Scripts/Editor/EnemyPortalEditor.cs create mode 100644 Assets/Scripts/Editor/EnemyPortalEditor.cs.meta diff --git a/.gitignore b/.gitignore index e23a945..0ef1b51 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,7 @@ [Uu]ser[Ss]ettings/ .vs -.vs/* \ No newline at end of file +.vs/* +.vscode +Assets/_Recovery +Assets/_Recovery.meta diff --git a/Assembly-CSharp-Editor.csproj b/Assembly-CSharp-Editor.csproj index 9241097..304cdde 100644 --- a/Assembly-CSharp-Editor.csproj +++ b/Assembly-CSharp-Editor.csproj @@ -43,13 +43,13 @@ 6000.3.5f2 - + @@ -1245,14 +1245,14 @@ Library\ScriptAssemblies\PPv2URPConverters.dll False - - Library\ScriptAssemblies\Unity.2D.Common.Editor.dll - False - Library\ScriptAssemblies\Unity.AI.Navigation.Updater.dll False + + Library\ScriptAssemblies\Unity.2D.Common.Editor.dll + False + Library\ScriptAssemblies\Unity.AI.Navigation.Editor.dll False @@ -1289,10 +1289,6 @@ Library\ScriptAssemblies\Unity.2D.Aseprite.Common.dll False - - Library\ScriptAssemblies\Unity.Rider.Editor.dll - False - Library\ScriptAssemblies\Unity.AI.Navigation.Editor.ConversionSystem.dll False @@ -1301,6 +1297,10 @@ Library\ScriptAssemblies\Unity.2D.Aseprite.Editor.dll False + + Library\ScriptAssemblies\Unity.Rider.Editor.dll + False + Library\ScriptAssemblies\Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary.dll False diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index 3ee2004..d30ecb8 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -43,14 +43,12 @@ 6000.3.5f2 - - @@ -69,6 +67,7 @@ + @@ -83,7 +82,6 @@ - @@ -99,10 +97,13 @@ + + + @@ -1263,14 +1264,14 @@ Library\ScriptAssemblies\PPv2URPConverters.dll False - - Library\ScriptAssemblies\Unity.2D.Common.Editor.dll - False - Library\ScriptAssemblies\Unity.AI.Navigation.Updater.dll False + + Library\ScriptAssemblies\Unity.2D.Common.Editor.dll + False + Library\ScriptAssemblies\Unity.AI.Navigation.Editor.dll False @@ -1307,10 +1308,6 @@ Library\ScriptAssemblies\Unity.2D.Aseprite.Common.dll False - - Library\ScriptAssemblies\Unity.Rider.Editor.dll - False - Library\ScriptAssemblies\Unity.AI.Navigation.Editor.ConversionSystem.dll False @@ -1319,6 +1316,10 @@ Library\ScriptAssemblies\Unity.2D.Aseprite.Editor.dll False + + Library\ScriptAssemblies\Unity.Rider.Editor.dll + False + Library\ScriptAssemblies\Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary.dll False diff --git a/Assets/Data/ScriptableObjects/Monster/Monster101.asset b/Assets/Data/ScriptableObjects/Monster/Monster101.asset index e152544..d2f0668 100644 --- a/Assets/Data/ScriptableObjects/Monster/Monster101.asset +++ b/Assets/Data/ScriptableObjects/Monster/Monster101.asset @@ -19,6 +19,6 @@ MonoBehaviour: atkRange: 1 atkDamage: 3 atkIntervalSec: 1.2 - prefabPath: Assets/Prefabs/EnemyTest + prefabPath: Assets/Prefabs/EnemyTest.prefab cost: 1 weight: 1 diff --git a/Assets/Data/ScriptableObjects/Monster/Monster102.asset b/Assets/Data/ScriptableObjects/Monster/Monster102.asset index eca53ca..3eb164b 100644 --- a/Assets/Data/ScriptableObjects/Monster/Monster102.asset +++ b/Assets/Data/ScriptableObjects/Monster/Monster102.asset @@ -19,6 +19,6 @@ MonoBehaviour: atkRange: 1 atkDamage: 2 atkIntervalSec: 1 - prefabPath: Assets/Prefabs/MonsterTest + prefabPath: Assets/Prefabs/MonsterTest.prefab cost: 2 weight: 0.5 diff --git a/Assets/Scenes/GameMain.unity b/Assets/Scenes/GameMain.unity index e3b310a..d83b389 100644 --- a/Assets/Scenes/GameMain.unity +++ b/Assets/Scenes/GameMain.unity @@ -1891,6 +1891,26 @@ PrefabInstance: propertyPath: m_Name value: EnemyPortal (1) objectReference: {fileID: 0} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.size + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.data[0].prefab + value: + objectReference: {fileID: 8774623643640324048, guid: c92c9f1bf0ae6364f85409ecdc4aeaf3, type: 3} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.data[1].prefab + value: + objectReference: {fileID: 5176576196123937037, guid: 951b69041a2ace947afd721fefb3eaba, type: 3} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.data[0].monsterData + value: + objectReference: {fileID: 11400000, guid: cec2336a0be4b6c4eb954ac3d08aa8d9, type: 2} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.data[1].monsterData + value: + objectReference: {fileID: 11400000, guid: fde07a19ade09f044aca9151f407d073, type: 2} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] @@ -2341,10 +2361,10 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: Assembly-CSharp::Northbound.GlobalTimer ShowTopMostFoldoutHeaderGroup: 1 - cycleLength: 90 + cycleLength: 5 autoStart: 1 pauseOnZero: 0 - exceptionalFirstCycleLength: 10 + exceptionalFirstCycleLength: 1 showDebugLogs: 1 --- !u!4 &1442785555 Transform: @@ -3224,6 +3244,26 @@ PrefabInstance: propertyPath: m_Name value: EnemyPortal objectReference: {fileID: 0} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.size + value: 2 + objectReference: {fileID: 0} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.data[0].prefab + value: + objectReference: {fileID: 8774623643640324048, guid: c92c9f1bf0ae6364f85409ecdc4aeaf3, type: 3} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.data[1].prefab + value: + objectReference: {fileID: 5176576196123937037, guid: 951b69041a2ace947afd721fefb3eaba, type: 3} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.data[0].monsterData + value: + objectReference: {fileID: 11400000, guid: cec2336a0be4b6c4eb954ac3d08aa8d9, type: 2} + - target: {fileID: 6859825394817103090, guid: 11e3760dda2c0164abf759c18d918893, type: 3} + propertyPath: monsterEntries.Array.data[1].monsterData + value: + objectReference: {fileID: 11400000, guid: fde07a19ade09f044aca9151f407d073, type: 2} m_RemovedComponents: [] m_RemovedGameObjects: [] m_AddedGameObjects: [] diff --git a/Assets/Scripts/Editor/EnemyPortalEditor.cs b/Assets/Scripts/Editor/EnemyPortalEditor.cs new file mode 100644 index 0000000..5ccfe5e --- /dev/null +++ b/Assets/Scripts/Editor/EnemyPortalEditor.cs @@ -0,0 +1,77 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; +using System.Linq; + +[CustomEditor(typeof(EnemyPortal))] +public class EnemyPortalEditor : Editor +{ + private const string MONSTER_DATA_FOLDER = "Assets/Data/ScriptableObjects/Monster"; + + public override void OnInspectorGUI() + { + DrawDefaultInspector(); + + EnemyPortal portal = (EnemyPortal)target; + + EditorGUILayout.Space(); + EditorGUILayout.LabelField("Monster Data Loader", EditorStyles.boldLabel); + + if (GUILayout.Button("Load Monster Data")) + { + LoadMonsterData(portal); + } + + EditorGUILayout.HelpBox("Click 'Load Monster Data' to automatically load all monsters from " + MONSTER_DATA_FOLDER, MessageType.Info); + } + + private void LoadMonsterData(EnemyPortal portal) + { + string[] guids = AssetDatabase.FindAssets("t:MonsterData", new[] { MONSTER_DATA_FOLDER }); + + List entries = new List(); + int loadedCount = 0; + + foreach (string guid in guids) + { + string assetPath = AssetDatabase.GUIDToAssetPath(guid); + Northbound.Data.MonsterData monsterData = AssetDatabase.LoadAssetAtPath(assetPath); + + if (monsterData != null) + { + GameObject prefab = AssetDatabase.LoadAssetAtPath(monsterData.prefabPath); + + if (prefab != null) + { + entries.Add(new EnemyPortal.MonsterEntry + { + monsterData = monsterData, + prefab = prefab + }); + loadedCount++; + } + else + { + Debug.LogWarning($"[EnemyPortal] Could not load prefab at path: {monsterData.prefabPath} for monster {monsterData.id}"); + } + } + } + + serializedObject.Update(); + SerializedProperty entriesProperty = serializedObject.FindProperty("monsterEntries"); + entriesProperty.ClearArray(); + entriesProperty.arraySize = entries.Count; + + for (int i = 0; i < entries.Count; i++) + { + SerializedProperty element = entriesProperty.GetArrayElementAtIndex(i); + element.FindPropertyRelative("monsterData").objectReferenceValue = entries[i].monsterData; + element.FindPropertyRelative("prefab").objectReferenceValue = entries[i].prefab; + } + + serializedObject.ApplyModifiedProperties(); + AssetDatabase.SaveAssets(); + + Debug.Log($"[EnemyPortal] Loaded {loadedCount} monsters from {MONSTER_DATA_FOLDER}"); + } +} diff --git a/Assets/Scripts/Editor/EnemyPortalEditor.cs.meta b/Assets/Scripts/Editor/EnemyPortalEditor.cs.meta new file mode 100644 index 0000000..939be54 --- /dev/null +++ b/Assets/Scripts/Editor/EnemyPortalEditor.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 70cde0c89ff88c149b6535cc2e9903b3 \ No newline at end of file diff --git a/Assets/Scripts/EnemyPortal.cs b/Assets/Scripts/EnemyPortal.cs index acf6d70..e1a77ba 100644 --- a/Assets/Scripts/EnemyPortal.cs +++ b/Assets/Scripts/EnemyPortal.cs @@ -2,43 +2,120 @@ using Northbound; using System.Collections.Generic; using Unity.Netcode; using UnityEngine; -using static Northbound.ObstacleSpawner; -using static UnityEditor.FilePathAttribute; public class EnemyPortal : MonoBehaviour { - [Header("Spawn Settings")] - [Tooltip("소환할 몬스터 목록")] - [SerializeField] private List Enemies = new(); - - // Start is called once before the first execution of Update after the MonoBehaviour is created - void Start() + [System.Serializable] + public class MonsterEntry { - GlobalTimer.Instance.OnCycleComplete += SpawnEnemy; + public Northbound.Data.MonsterData monsterData; + public GameObject prefab; } - private void SpawnEnemy() - { - foreach (GameObject obj in Enemies) - { - GameObject enemy = Instantiate(obj, transform); + [Header("Spawn Settings")] + [Tooltip("몬스터 데이터 목록 (Editor에서 자동 로드 가능)")] + [SerializeField] private List monsterEntries = new(); - // Add FogOfWarVisibility component to hide enemies in unexplored areas - if (enemy.GetComponent() == null) + [Header("Cost Settings")] + [Tooltip("시간당 코스트 시작 값")] + [SerializeField] private float initialCost = 4f; + [Tooltip("사이클마다 코스트 증가율 (%)")] + [SerializeField] private float costIncreaseRate = 10f; + + private float currentCost; + + void Start() + { + currentCost = initialCost; + GlobalTimer.Instance.OnCycleStart += OnCycleStart; + } + + private void OnCycleStart(int cycleNumber) + { + SpawnMonsters(); + IncreaseCost(); + } + + private void SpawnMonsters() + { + float remainingCost = currentCost; + int spawnedCount = 0; + + while (remainingCost > 0 && monsterEntries.Count > 0) + { + MonsterEntry selectedEntry = SelectMonsterByWeight(); + + if (selectedEntry.monsterData.cost > remainingCost) { - var visibility = enemy.AddComponent(); - visibility.showInExploredAreas = false; // Enemies hidden when not visible - visibility.updateInterval = 0.2f; + if (!CanSpawnAnyMonster(remainingCost)) + { + break; + } + continue; } - enemy.GetComponent().Spawn(); - Debug.Log(enemy); + SpawnEnemy(selectedEntry.prefab); + remainingCost -= selectedEntry.monsterData.cost; + spawnedCount++; + } + + if (spawnedCount > 0) + { + Debug.Log($"[EnemyPortal] Spawned {spawnedCount} monsters (Cost used: {currentCost - remainingCost:F2})"); } } - // Update is called once per frame - void Update() + private bool CanSpawnAnyMonster(float remainingCost) { - + foreach (var entry in monsterEntries) + { + if (entry.monsterData.cost <= remainingCost) + { + return true; + } + } + return false; + } + + private MonsterEntry SelectMonsterByWeight() + { + float totalWeight = 0f; + foreach (var entry in monsterEntries) + { + totalWeight += entry.monsterData.weight; + } + + float randomValue = Random.Range(0f, totalWeight); + float cumulativeWeight = 0f; + + foreach (var entry in monsterEntries) + { + cumulativeWeight += entry.monsterData.weight; + if (randomValue <= cumulativeWeight) + { + return entry; + } + } + + return monsterEntries[0]; + } + + private void SpawnEnemy(GameObject prefab) + { + GameObject enemy = Instantiate(prefab, transform); + + if (enemy.GetComponent() == null) + { + var visibility = enemy.AddComponent(); + visibility.showInExploredAreas = false; + visibility.updateInterval = 0.2f; + } + + enemy.GetComponent().Spawn(); + } + + private void IncreaseCost() + { + currentCost *= (1f + costIncreaseRate / 100f); } } diff --git a/ExternAttributes.Editor.csproj b/ExternAttributes.Editor.csproj index d74c257..35f03b0 100644 --- a/ExternAttributes.Editor.csproj +++ b/ExternAttributes.Editor.csproj @@ -43,7 +43,6 @@ 6000.3.5f2 - diff --git a/FlatKit.Utils.Editor.csproj b/FlatKit.Utils.Editor.csproj index 598b48b..9988b14 100644 --- a/FlatKit.Utils.Editor.csproj +++ b/FlatKit.Utils.Editor.csproj @@ -43,7 +43,6 @@ 6000.3.5f2 - diff --git a/Unity.RenderPipelines.Universal.Runtime.csproj b/Unity.RenderPipelines.Universal.Runtime.csproj index 00a650f..c30acff 100644 --- a/Unity.RenderPipelines.Universal.Runtime.csproj +++ b/Unity.RenderPipelines.Universal.Runtime.csproj @@ -43,15 +43,14 @@ 6000.3.5f2 - - + @@ -143,8 +142,8 @@ - + @@ -247,8 +246,8 @@ - +