1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.Events;
using UnityEngine.UI;
public class ExperienceManager : Singleton<ExperienceManager>
{
#region
[Tooltip("ํ˜„์žฌ ๋ ˆ๋ฒจ์„ ํ‘œ์‹œํ•  UI ์ปดํฌ๋„ŒํŠธ")]
#endregion
[SerializeField]
TextMeshProUGUI CurrentLevelText;
#region
[Tooltip("ํ˜„์žฌ XP๋ฅผ ํ‘œ์‹œํ•  UI ์ปดํฌ๋„ŒํŠธ")]
#endregion
[SerializeField]
TextMeshProUGUI CurrentXPText;
#region
[Tooltip("๋‹ค์Œ ๋ ˆ๋ฒจ๊นŒ์ง€ ํ•„์š”ํ•œ XP๋ฅผ ํ‘œ์‹œํ•  UI ์ปดํฌ๋„ŒํŠธ")]
#endregion
[SerializeField]
TextMeshProUGUI XPToNextLevelText;
#region
[Tooltip("XP ๊ณ„์‚ฐ ๋ฐฉ์‹์„ ๊ฒฐ์ •ํ•  ScriptableObject")]
#endregion
[SerializeField]
BaseXPTranslation XPTranslationType;
// C# ์ด๋ฒคํŠธ ์„ ์–ธ
public event Action<int, int> OnXpChanged;
public Slider expBarSlider;
// ๋Ÿฐํƒ€์ž„์— ์‚ฌ์šฉ๋  XP ๊ณ„์‚ฐ ์ธ์Šคํ„ด์Šค
BaseXPTranslation XPTranslation;
private void Awake()
{
//Debug.Log(XPTranslationType);
XPTranslation = ScriptableObject.Instantiate(XPTranslationType);
}
// ๊ฒฝํ—˜์น˜ ์ถ”๊ฐ€ ๋ฐ UI ์—…๋ฐ์ดํŠธ ๋ฉ”์„œ๋“œ, EXP ๋งค๋‹ˆ์ €๋ฅผ ํ†ตํ•ด์„œ XP Translation์„ ์ฐธ์กฐํ•จ
public void AddXP(int amount)
{
int previousLevel = XPTranslation.CurrentLevel;
if (XPTranslation.AddXP(amount))
{
OnXpChanged?.Invoke(previousLevel, XPTranslation.CurrentLevel);
}
RefreshDisplays();
}
// ๋ ˆ๋ฒจ ์„ค์ • ๋ฐ UI ์—…๋ฐ์ดํŠธ ๋ฉ”์„œ๋“œ
public void SetLevel(int level)
{
int previousLevel = XPTranslation.CurrentLevel;
XPTranslation.SetLevel(level);
if (previousLevel != XPTranslation.CurrentLevel)
{
OnXpChanged?.Invoke(previousLevel, XPTranslation.CurrentLevel);
}
RefreshDisplays();
}
// Start is called before the first frame update
void Start()
{
RefreshDisplays();
//Debug.Log("์Šคํƒ€ํŠธ!");
//Debug.Log($"Start: OnXpChanged = {OnXpChanged}");
OnXpChanged?.Invoke(0, XPTranslation.CurrentLevel);
}
// Update is called once per frame
void Update()
{
}
// UI๋ฅผ ์ตœ์‹  ์ƒํƒœ๋กœ ๊ฐฑ์‹ ํ•˜๋Š” ๋ฉ”์„œ๋“œ
void RefreshDisplays()
{
#region ํ…์ŠคํŠธ ํŒŒํŠธ
CurrentLevelText.text = $"{XPTranslation.CurrentLevel}";
CurrentXPText.text = $"{XPTranslation.CurrentXP}";
if (!XPTranslation.AtLevelCap)
{
XPToNextLevelText.text = $"{XPTranslation.XPRequiredForNextLevel}";
}
else
{
CurrentXPText.text = $"Max";
XPToNextLevelText.text = $"Max";
}
#endregion ํ…์ŠคํŠธ ํŒŒํŠธ
//์Šฌ๋ผ์ด๋” UI
if (expBarSlider != null)
{
//๋งŒ๋ ™์ด ์•„๋‹๋•Œ
if(!XPTranslation.AtLevelCap)
{
//ํ˜„์žฌ ์บ๋ฆญํ„ฐ์˜ ๋Šฅ๋ ฅ์น˜๋กœ ๋ฐ›๊ธฐ๋กœ ๊ณง ๊ต์ฒดํ•˜๊ธฐ
expBarSlider.maxValue = XPTranslation.XPRequiredForNextLevel;
expBarSlider.value = XPTranslation.CurrentXP;
}
//๋งŒ๋ ™์ผ๋•Œ
else
{
expBarSlider.maxValue = XPTranslation.XPRequiredForNextLevel;
expBarSlider.value = XPTranslation.XPRequiredForNextLevel;
}
}
}
}
cs





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class XPTranslationTableEntry
{
public int Level; //ํ•ด๋‹น ์—”ํŠธ๋ฆฌ์˜ ๋ ˆ๋ฒจ
public int XPRequired;//ํ•ด๋‹น ๋ ˆ๋ฒจ์— ๋„๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒฝํ—˜์น˜์˜ ์–‘
}
[CreateAssetMenu(fileName = "XPTranslation_Table" , menuName = "Scriptable Objects/Exp/XPTable")]
public class XPTranslation_Table : BaseXPTranslation
{
//SO๋ฐ์ดํ„ฐ
[SerializeField]
List<XPTranslationTableEntry> Table; // ๋ ˆ๋ฒจ๊ณผ ํ•„์š”ํ•œ XP๋ฅผ ๋งคํ•‘ํ•œ ํ…Œ์ด๋ธ”
// ๊ฒฝํ—˜์น˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ๋ ˆ๋ฒจ ์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฉ”์„œ๋“œ
public override bool AddXP(int amount)
{
if (AtLevelCap)
{
return false;
}
CurrentXP += amount;
bool levelChanged = false;
// ํ˜„์žฌ XP๊ฐ€ ๋‹ค์Œ ๋ ˆ๋ฒจ์— ํ•„์š”ํ•œ XP๋ฅผ ์ดˆ๊ณผํ•  ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต
while (!AtLevelCap && CurrentXP >= Table[CurrentLevel].XPRequired)
{
// ๋‹ค์Œ ๋ ˆ๋ฒจ๋กœ ์—…๋ฐ์ดํŠธ
CurrentXP -= Table[CurrentLevel].XPRequired; // ๋‹ค์Œ ๋ ˆ๋ฒจ๋กœ ๊ฐ€๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ XP๋ฅผ ํ˜„์žฌ XP์—์„œ ๋นผ๊ธฐ
CurrentLevel++;
levelChanged = true;
// ๋ ˆ๋ฒจ ์—… ํ›„ ์ตœ์ข… ๋ ˆ๋ฒจ์— ๋„๋‹ฌํ–ˆ๋Š”์ง€ ํ™•์ธ
AtLevelCap = CurrentLevel >= Table.Count;
if (AtLevelCap)
{
CurrentXP = 0; // ์ตœ์ข… ๋ ˆ๋ฒจ์—์„œ๋Š” XP๋ฅผ 0์œผ๋กœ ์„ค์ •
break; // ๋ฐ˜๋ณต ์ข…๋ฃŒ
}
}
return levelChanged;
}
// ํŠน์ • ๋ ˆ๋ฒจ๋กœ ์„ค์ •ํ•˜๋Š” ๋ฉ”์„œ๋“œ
public override void SetLevel(int level)
{
CurrentXP = 0;
CurrentLevel = 1;
AtLevelCap = false;
foreach (var entry in Table)
{
if (entry.Level == level)
{
AddXP(entry.XPRequired);
return;
}
}
throw new System.ArgumentOutOfRangeException($"๋ ˆ๋ฒจ์— ๋Œ€ํ•œ ํ•ญ๋ชฉ ์ฐพ์„ ์ˆ˜ ์—†์Œ {level}");
}
// ๋‹ค์Œ ๋ ˆ๋ฒจ์— ํ•„์š”ํ•œXP๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ
protected override int GetXPRequiredForNextLevel()
{
if (AtLevelCap)
{
return int.MaxValue;
}
for (int index = 0; index < Table.Count; ++index)
{
var entry = Table[index];
if (entry.Level == CurrentLevel)
{
return Table[index + 1].XPRequired;
}
}
throw new System.ArgumentOutOfRangeException($"ํ˜„์žฌ ๋ ˆ๋ฒจ์— ๋Œ€ํ•œ ํ•ญ๋ชฉ ์ฐพ์„ ์ˆ˜ ์—†์Œ {CurrentLevel}");
}
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using UnityEngine;
public abstract class BaseXPTranslation : ScriptableObject
{
// ํ˜„์žฌ ์บ๋ฆญํ„ฐ์˜ XP
public int CurrentXP { get; protected set; } = 0;
// ํ˜„์žฌ ์บ๋ฆญํ„ฐ์˜ ๋ ˆ๋ฒจ
public int CurrentLevel { get; protected set; } = 1;
// ๋‹ค์Œ ๋ ˆ๋ฒจ์— ํ•„์š”ํ•œ XP
public int XPRequiredForNextLevel => GetXPRequiredForNextLevel();
// ๋ ˆ๋ฒจ ์ƒํ•œ์— ๋„๋‹ฌํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€
public bool AtLevelCap { get; protected set; } = false;
// ๊ฒฝํ—˜์น˜ ์ถ”๊ฐ€ ์ถ”์ƒ ๋ฉ”์„œ๋“œ
public abstract bool AddXP(int amount);
// ๋ ˆ๋ฒจ ์„ค์ • ์ถ”์ƒ ๋ฉ”์„œ๋“œ
public abstract void SetLevel(int level);
// ๋‹ค์Œ ๋ ˆ๋ฒจ์— ํ•„์š”ํ•œ XP ๊ณ„์‚ฐ ์ถ”์ƒ ๋ฉ”์„œ๋“œ
protected abstract int GetXPRequiredForNextLevel();
}
cs

ํ˜„์žฌ๋Š” SO์—์„œ ๋ฐ์ดํ„ฐ ๋งคํ•‘ํ•ด์„œ ๊ตฌํ˜„ํ–ˆ๋Š”๋ฐ

๋‚ด๊ฐ€ ์ƒ๊ฐํ•ด๋„ ์ฝ”๋“œ๋ฅผ ๊ทธ๋ ‡๊ฒŒ ์ž˜ ์งœ์ง€ ์•Š์•„์„œ, ์ข€ ๊ณ ๋ฏผ ์ค‘์ด๋‹ค.

์ฝ”๋“œ๊ฐ€ ์ด์˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋Š”๋ฐ,



25ee9e36ebd518986abce89544847d6948


์ด๋ ‡๊ฒŒ ๋…ธ๋“œ ๊ทธ๋ž˜ํ”„๋ฅผ ๋งŒ๋“œ๋Š” ์ค‘์ธ๋ฐ, SO์˜ ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋…ธ๋“œ๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ.


์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‚˜์ค‘์— ํ˜‘์—…ํ• ๋•Œ ๊ธฐํšํ•˜๋ฉด ์ˆœ์‹๊ฐ„์— ๊ธˆ๋ฐฉ ๊ณ ์ณ๋„ ๋ ๊ฒƒ๊ฐ™์•„์„œ ํŽธํ• ๊ฑฐ๊ฐ™์€๋ฐ


๊ทธ๋ž˜์„œ ๋‚ด ๋ชฉํ‘œ๊ฐ€ ์ € ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”์„ ๋…ธ๋“œ๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ์€๋ฐ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?

์ฆ‰ ๋ ˆ๋ฒจ์—…-๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ” ๋…ธ๋“œ ์ง€๋‚˜๊ฐ->๊ฒฐ๊ณผ๊ฐ’


์ด๋ ‡๊ฒŒ ๋˜์•ผํ•˜๋Š”๋ฐ, ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ” ๋…ธ๋“œ์—์„œ ๋‹ค์Œ ๋ ˆ๋ฒจ์—… ์ •๋ณด๋ฅผ ๋ฐ›์œผ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ์งœ์•ผํ•˜์ง€.


์ฝ”๋“œ ์ˆ˜์ค€์ด ๋‚ฎ์€๊ฑด ์ดํ•ดํ•ด์ฃผ์…ˆ. ๊ทธ๋‹ค์ง€ ์ฝ”๋“œ๋ฅผ ์ž˜ ์งœ์ง€ ๋ชปํ•ด์„œ