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 @@
-
+