WitchMendokusai DevLog 01
๐ _
์ ๋ฒ ์ผ์ง์ ๋ง์ฐฌ๊ฐ์ง๋ก,
์ด๋ฒ ์ผ์ง์์๋ ๋ง์ ์๋ขฐ๋ฅผ ๋ง๋ค๊ธฐ ์ํด ๊ตฌํํ ๊ธฐ๋ฅ๋ค์ ๊ธฐ๋กํด๋ณธ๋ค.
๐ ๋ฐ์ดํฐ ์ ์ฅ
์ ๋ฒ ์ผ์ง์์ ํ์คํธ์ ์ผ์ด ๊ธฐ๋ฅ์ ์ผ๋ก ๋์ํ๋ ๊ฒ๊น์ง ๋ง๋ค์๋ค.
์ด์ ํ์คํธ์ ์ผ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ณ ๋ถ๋ฌ์ค๋ ๊ฑธ ๊ตฌํํด๋ณธ๋ค.
์ ๋ง ๋ง์ ์ผ์ด ์์๋ค.
๐ฟ 1. ์ผ๋จ ์ ์ฅํด๋ด !
1
2
3
4
5
6
7
8
9
10
11
12
[Serializable]
public struct QuestData
{
public int QuestID;
public QuestState State;
public QuestData(int questID, QuestState state)
{
QuestID = questID;
State = state;
}
}
1
2
3
4
5
6
7
[Serializable]
public class GameData
{
public Dictionary<int, List<Work>> works = new();
public List<QuestData> questDatas = new();
// ...
}
๋จ์ํ QuestData
๋ฅผ ์๋ก ์ ์ํ๊ณ GameData
์ ์ถ๊ฐํ๋ค.
๊ฐ๋จํ๊ฒ ํ์คํธ ์ ๋ณด์ ์ผ ์ ๋ณด๋ฅผ ์ ์ฅํ ์ ์๊ฒ ๋๋ค.
๐ฟ 2. ์กฐ๊ฑด ์ ๋ณด ์ ์ฅ (Criteria, RuntimeCriteria)
ํ์ง๋ง ๋ฌธ์ ๊ฐ ์๋ค.
ํ์คํธ๋ฅผ ์๋ฃํ๊ธฐ ์ํ ์๋ธ ํ์คํธ๋ฅผ Criteria
, ์กฐ๊ฑด
์ผ๋ก ์นญํ๊ฒ ๋ค.
ํ์คํธ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ๋ก ์กด์ฌํ๋ค.
๋ฐํ์์์ ๊ณ์ ์งํ์ํฉ์ ์ฒดํฌํ ์ ์๋ ์กฐ๊ฑด๋ค๋ ์์ง๋ง,
๋ฑ ํ ๋ฒ๋ง ๋ฌ์ฑํด๋ ๋๊ฑฐ๋, ๋๋คํ ์์๋ฅผ ๊ฐ์ง๋ ๋ฑ์ ํน์ง์ ๊ฐ์ง ์กฐ๊ฑด๋ค๋ ์๋ค.
์ด๋ฐ ์กฐ๊ฑด๋ค์ ๊ฒ์์ด ๊ป๋ค์ผฐ์ ๋ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ฌ ์ ์์ด์ผ ํ๋ค.
๋๋ฌธ์ ์ด๋ฐ ์กฐ๊ฑด๋ค์ ์ ๋ณด๋ ์งํ ์ํฉ์ ์ ์ฅํด์ผ ํ๋ค.
์ฒ์์ QuestData
์ ๋ง์ฐฌ๊ฐ์ง๋ก CriteriaData
๋ฅผ ๋ง๋ค์ด CriteriaID
, IsCompleted
, Value
๋ฑ์ ์ ์ฅํด๋ณด๋ ค ํ๋ค.
Quest
์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ์ ๊ธฐ์กด State
์ ๋ง์ฐฌ๊ฐ์ง๋ก [NonSerialized]
์ธ List<bool> IsCompleted
์ List<SomeValue> CriteriaValue
๋ฅผ ์ถ๊ฐํ ๋ค์,
CriteriaData
๋ฅผ ์ฝ์ด๋ณผ ๋ ๊ฐ ์กฐ๊ฑด์ ID์ ๋ง์ถฐ ์๋ฃ ์ฌ๋ถ๋ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ๋ฐฉ์์ด๋ค.
..๋์ถฉ๋ด๋ ์๋ฆ๋ต์ง๋ ์์ ๋ฐฉ์์ด๋ค. ์ค์ ๋ก ์๋์ ๊ฐ์ ๋ฌธ์ ๋ค์ด ์๋ค.
- ์์๊ฐ ์กด์ฌํ๊ธด ํ์ง๋ง, ID๊ฐ ๋๊ฐ์ ์กฐ๊ฑด์ด ์๋ค๋ฉด ๋ชจํธํด์ง๋ค.
CriteriaValue
๋ฅผ ์ด๋ค ํ์ ์ผ๋ก ๋ง๋ค์ด ์ ์ฅํ ์ง๊ฐ ๊ณ ๋ฏผ์ค๋ฝ๋ค. ์กฐ๊ฑด๋ง๋ค ํ์ํ ๋ถ๊ฐ ์ ๋ณด๊ฐ ๋ค๋ฅผ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ด๋ค.- ์กฐ๊ฑด๊ณผ ๊ด๋ จ๋ ๋ณ์๊ฐ
Criterias
,IsCompleted
,Value
๋ ์๊ธด๋ค. ํ๋๋ก ํฉ์น๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค. - ์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ์ ๋๋ฌด ๋ง์ ์ ๋ณด๊ฐ ๋ค์ด๊ฐ๋ค. ํนํ
[NonSerialized]
ํ ์ ๋ณด๋ค์ด ๋ง์์ง๋ค. ๋ถ๋ฆฌํ ํ์๊ฐ ์๋ค.
์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด ์๋์ฒ๋ผ ๊ตฌ์กฐ๋ฅผ ๋ฐ๊พธ๊ณ ๊ตฌํํ๋ค.
Criteria
- ๊ธฐ์กด
Criteria
๋CriteriaSO
๋ก ๋ณ๊ฒฝ - ์๋ก
Criteria
ํด๋์ค๋ฅผ ๋ง๋ค์ด์, ๋์ ์ผ๋ก๋Criteria
๋ฅผ ์์ฑํ ์ ์๋๋ก ๋ณ๊ฒฝ - ์๋ก
RuntimeCriteria
ํด๋์ค๋ฅผ ๋ง๋ค์ด์,Criteria
,IsCompleted
๋ฑ์ ์ ์ฅ
- ๊ธฐ์กด
Quest
๋ถ๋ฆฌ- ๊ธฐ์กด
Quest
๋ ์๋ํฐ ํ์์์ ์ ์ ์ธ ๋ฐ์ดํฐ๋ง์ ์ ์ฅํ๋๋กQuestData
๋ก ๋ณ๊ฒฝ - ๊ธฐ์กด
QuestData
๋QuestDataSave
๋ก ๋ณ๊ฒฝ - ์๋ก
Quest
ํด๋์ค๋ฅผ ๋ง๋ค์ด์,QuestData
์RuntimeCriteria
๋ฅผ ์ ์ฅ GameData
์List<Quest>
๋ฅผ ์ถ๊ฐํด์ ๋ฐ๋ก ์ง๋ ฌํ
- ๊ธฐ์กด
์ด๋ ๊ฒ ์์ ๋ฒํ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ณ ์ ํ๋ค.
CriteriaValue
์ ํ์
๊ฒฐ์ ๋ฌธ์ ๋, JSON ๋ฐ์ดํฐ ์ ์ฅ ์ TypeNameHandling = TypeNameHandling.Auto
์ต์
์ ์ผ์, Criteria
ํ์
์ผ๋ก ์ ์ฅํ๋๋ผ๋ ํ์ ํด๋์ค์ ํ๋ ์ญ์ ์ ์ฅํ ์ ์๋๋กํ์ฌ ํด๊ฒฐํ๋ค.
๊ทธ๋ ๊ฒ ๋ง๋ค์ด์ง ํด๋์ค๋ค์ ์๋ ๊ฐ์ ๋ชจ์์ ๊ฐ์ง๊ฒ ๋๋ค.
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
public class RuntimeCriteria : ICriteria
{
public Criteria Criteria { get; private set; }
// ํ ๋ฒ๋ง ๋ฌ์ฑํ๋ฉด ๋๋์ง
public bool JustOnce { get; private set; }
public bool IsCompleted { get; private set; }
public bool Evaluate()
{
if (JustOnce && IsCompleted)
return true;
return IsCompleted = Criteria.Evaluate();
}
public float GetProgress()
{
return Criteria.GetProgress();
}
[JsonConstructor]
public RuntimeCriteria(Criteria criteria, bool justOnce = false)
{
Criteria = criteria;
JustOnce = justOnce;
}
public RuntimeCriteria(CriteriaInfo criteriaInfo)
{
Criteria = criteriaInfo.CriteriaSO.Data;
JustOnce = criteriaInfo.JustOnce;
}
}
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
public class Quest
{
public Guid? Guid { get; private set; }
public int DataID { get; private set; }
public QuestState State { get; private set; }
public List<RuntimeCriteria> Criterias { get; private set; }
public QuestData GetData()
{
return DataManager.Instance.QuestDic[DataID];
}
[JsonConstructor]
public Quest(Guid? guid, int dataID, QuestState state, List<RuntimeCriteria> criterias)
{
Guid = guid;
DataID = dataID;
State = state;
Criterias = criterias;
StartQuest();
}
public Quest(QuestData questData)
{
Guid = System.Guid.NewGuid();
DataID = questData.ID;
Criterias = Data.Criterias.ConvertAll(criteriaData => new RuntimeCriteria(criteriaData));
StartQuest();
}
// ...
}
๐ฟ 3. ํต๊ณ์ ์คํฏ ์ ์ฅ
์กฐ๊ฑด์ ์ธ๋ถ ์ ๋ณด๋ Criteria
๊ฐ ์ง์ ๋ค๊ณ ์๋ค.
์๋ฅผ ๋ค์ด, โ๋ชน์ 10๋ง๋ฆฌ ์ก์ผ์์คโ ๊ฐ์ ์กฐ๊ฑด์ด ์๋ค๊ณ ํ๋ค๋ฉด,
MonsterKill
๊ฐ์ ์ง์ผ๋ณด๋ฉด์, ๊ฐ์ด 10 ์ด์์ผ ๋ Criteria.Evaluate()
ํจ์์์ true
๋ฅผ ๋ฐํํ๋ค.
๊ธฐ์กด์๋ MonsterKill
๊ฐ์ ํต๊ณ ๊ฐ์ด๋ ์คํฏ๋ค์ ์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ๋ก ๋ง๋ค์ด ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์,
Criteria
์์๋ ์ด๋ฐ ์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ๋ฅผ ํ๋๋ก ๊ฐ์ง๊ณ ์์๋ค.
ํ์ง๋ง ์์์ ๋ฐ์ดํฐ ์ ์ฅ ๊ตฌ์กฐ๋ฅผ ๋ฐ๊พธ๋ฉด์ ์ด๋ฐ ๋ฐฉ์์ ๋ฌธ์ ๊ฐ ์๊ฒผ๋ค.
Criteria
๋ ์ด์ RuntimeCriteria
์ ํ๋๋ก์ ๋ฐ์ดํฐ๋ก ์ ์ฅ์ด ๋๋๋ฐ, ์ด๋ฌ๋ฉด Criteria
๋ฅผ ์ง๋ ฌํ/์ญ์ง๋ ฌํ ํ ๋ ๊ฐ์ ์ ์ฅ๋ผ๋ ๋ ํผ๋ฐ์ค๊ฐ ์ฌ๋ผ์ ธ์ ๋ฒ๊ฑฐ๋กญ๊ฒ ์ง์ ๋ ํผ๋ฐ์ค๋ฅผ ์ฐ๊ฒฐํด์ฃผ๋ ์์
์ด ํ์ํ๊ฒ ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํต๊ณ ๊ฐ์ ์ ์ฅํ๋ ๋ฐฉ์์ ์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ์์ Enum
์ผ๋ก ๋ณ๊ฒฝํ๊ณ ,
๋ณ๋๋ก Statistics
SO๋ฅผ ๋ง๋ค์ด์ Dictionaty<StatisticsType, int>
๋ก ๊ด๋ฆฌํ๊ธฐ ์์ํ๋ค.
์ด๋ฌ๋ฉด Enum
์ ์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋๊ณ , Evaluate()
๋ฑ์์ ํต๊ณ ๊ฐ์ ์๊ณ ์ ํ ๋๋ Statistics
์์ ๊ฐ์ ธ์ค๋ฉด ๋๋ค.
์ ์ฒด์ ์ผ๋ก ์๋์ ๊ฐ์ ๋ชจ์์ด ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class Criteria : ICriteria
{
public abstract int GetCurValue();
public abstract int GetTargetValue();
public abstract bool Evaluate();
// NewtonSoft๋ก Json ์ง๋ ฌํ/์ญ์ง๋ ฌํ๋ฅผ ์ํค๊ณ ์๋๋ฐ,
// ํ์ดํ ํจ์๋ฅผ ์ง๋ ฌํํ๋ ๊ฒ ๊ฐ์์ ์ผ๋ฐ์ ์ธ ํจ์ ๋ชจ์์ผ๋ก ๋ง๋ค์๋ค.
// ์ข ๋ ์์๋ด์ผ ํ ๋ฏ
public virtual float GetProgress()
{
return (float)GetCurValue() / GetTargetValue();
}
}
1
2
3
4
5
6
7
public abstract class NumCriteria : Criteria
{
public ComparisonOperator ComparisonOperator { get; private set; }
public int TargetValue { get; private set; }
// ...
}
1
2
3
4
5
6
7
8
9
10
11
public class StatisticsCriteria : NumCriteria
{
public StatisticsType Type { get; private set; }
public override int GetCurValue()
{
return SOManager.Instance.Statistics[Type];
}
// ...
}
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
public class Statistics : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField] private List<StatisticsInfo> initStatistics = new();
[NonSerialized] private Dictionary<StatisticsType, int> statistics = new();
public int this[StatisticsType type]
{
get
{
if (!statistics.ContainsKey(type))
statistics[type] = 0;
return statistics[type];
}
set
{
if (!statistics.ContainsKey(type))
statistics[type] = 0;
statistics[type] = value;
}
}
// ...
}
์ ์์์ ์ฐธ๊ณ ํ๋ค.
์์์์ ์๊ฐํ๋ ๊ฒ์ฒ๋ผ, ์คํฏ๋ ์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ์์ Enum
์ผ๋ก ๋ฐ๊พธ๊ณ ,
๋ณ๋๋ก Dictionaty<StatType, int>
๋ฅผ ๊ฐ์ง๋ Stat
ํด๋์ค๋ก ๊ด๋ฆฌํ๊ธฐ ์์ํ๋ค.
์ด๋ฐ ๋ฐฉ์์ด ์ธ ๋๋ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ ๋๋ ํธํ๊ธดํ๋ฐ,
ํ ๊ฐ์ง ๋ฌธ์ ์ ์ด๋ผ ํ๋ค๋ฉด Enum
๊ฐ์ ์์๋ฅผ ๋ฐ๊พธ๊ฑฐ๋ ํ๋ค๋ฉด ๋ฐ์ดํฐ๊ฐ ๊ผฌ์ธ๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋์ ์ต๋ํ ๋ณ๊ฒฝ์ ํผํ๋๋ก ์๋์ ๊ฐ์ด ์์ง์ฑ์ด ์๋ ๊ฒ๋ค์ 100 ๋จ์๋ก ๋ถ๋ฅํ๋ค.
์ด๋ค ์คํฏ์ ์ด๋ค ๋ถ๋ฅ์ ๋ฐฐ์นํด์ผ ํ๋์ง ๋ฑ์ ๊ฒฝ๊ณ์ ๋ฌธ์ ๋ ์์ ๊ฒ์ด๊ณ , ์ธ์ ๊ฐ ๋ถ๊ฐํผํ๊ฒ ๋ณ๊ฒฝ์ด ํ์ํ ๋ ์ด ์์ํ ์ง๋ง.. ์ผ๋จ ๊ณ์ ๊ตฌํํด๋ณด๋๋ก ํ๋ค.
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
public enum StatType
{
// ์ฒด๋ ฅ
HP_CUR = 0,
HP_MAX = 1,
// ๊ฒฝํ์น, ๋ ๋ฒจ
EXP_CUR = 100,
EXP_MAX = 101,
LEVEL_CUR = 102,
// ๋ง๋
MANA_CUR = 200,
MANA_MAX = 201,
// ์ด๋
MOVEMENT_SPEED = 300,
MOVEMENT_SPEED_BONUS = 301,
// ์คํฌ
COOLTIME_BONUS = 400,
// ๋ฐ๋ฏธ์ง
DAMAGE_BONUS = 500,
// ํค์๋
PLAYER_EXP_COLLIDER_SCALE = 10000,
SATELLITE_COUNT = 100001,
}
๐ฟ 4. Reward
์กฐ๊ฑด๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณด์๋ ์ ์ฅํด์ผํ๋ค. (๋ณด์๋ ๋๋ค์ผ ์ ์๊ณ , ํฌ๊ฒ๋ ํ์คํธ๋ฅผ ๋์ ์ผ๋ก ์์ฑํ๊ธฐ ์ํด)
์ด๋ฅผ ์ํ ๊ตฌ์กฐ์ฒด, ํด๋์ค๋ค์ ์ ์ํ๋ค.
1
2
3
4
5
6
public enum RewardType
{
Item,
Gold,
Exp,
}
1
2
3
4
5
6
7
[Serializable]
public struct RewardInfo
{
public RewardType Type;
public Artifact Artifact;
public int Amount;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Serializable]
public struct RewardData
{
public RewardType Type;
public int ArtifactID;
public int Amount;
public RewardData(RewardInfo rewardInfo)
{
Type = rewardInfo.Type;
ArtifactID = rewardInfo.Artifact ? rewardInfo.Artifact.ID : Artifact.NONE_ID;
Amount = rewardInfo.Amount;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Reward
{
public static void GetReward(RewardData reward)
{
switch (reward.Type)
{
case RewardType.Item:
ItemData itemData = DataManager.Instance.ItemDic[reward.ArtifactID];
SOManager.Instance.ItemInventory.Add(itemData, reward.Amount);
break;
case RewardType.Gold:
SOManager.Instance.Nyang.RuntimeValue += reward.Amount;
break;
case RewardType.Exp:
SOManager.Instance.VQExp.RuntimeValue += reward.Amount;
break;
}
}
}
์ด๋ ๊ฒ ๊ตฌํํ ๊ตฌ์กฐ์ฒด, ํด๋์ค๋ค์ QuestData
์ Quest
์์ ์ ์ฅํ์ฌ ์ฌ์ฉํ๋ค.
๐ ๊ทธ ์ธ
ํ์คํธ UI๋ฅผ ๊ฐ์ ํ๋ฉด์, ํ์คํธ์ ํดํ์ ์กฐ๊ฑด๊ณผ ๋ณด์ ์ ๋ณด๋ฅผ ํ์ํ๊ธฐ ์์ํ๋ค.
- ์ธํ๊ณผ ์นด๋ฉ๋ผ ์ฌ์ด์ ์๋ ์ค๋ธ์ ํธ๋ค์ ํฌ๋ช
ํ๊ฒ ์ฒ๋ฆฌํ๊ธฐ ์์ํ๋ค.
- ์ฌ์ค ๊ธฐ๋ฅ์ ๊ธฐ์กด์๋ ์์๋๋ฐ, ์ ๋๋ก ์๋ํ์ง ์๋ ๋ฌธ์ ๋ฅผ ์์ ํ๋ฉด์ ๋ฆฌํฉํ ๋ง์ ์งํํ๋ค.
- ๋ฐ์ดํฐ๋ฅผ ๋ก์ปฌ JSON ํ์ผ๋ก ์ ์ฅํ๊ธฐ ์์ํ๋ค.
- ๊ธฐ์กด์๋ PlayFab์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋๋ฐ, ๋น์ฅ ์ ์ฅ ๋ฐ์ดํฐ ๊ตฌ์กฐ๊ฐ ๊ณ์ ๋ฐ๋๋ ์ํฉ์์ PlayFab ํ์ด์ง๊น์ง ๋ค์ด๊ฐ ์์ ํ๊ณ ์ง์ฐ๋ ๊ณผ์ ์ด ๋ฒ๊ฑฐ๋ก์ ๊ธฐ์..
๐ฟ ISavable
1
2
3
4
5
public interface ISavable<T>
{
void Load(T saveData);
T Save();
}
๊ฐ๋จํ ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค์๋ค.
๐ ํ์ฌ๊น์ง์ ์งํ ์ํฉ
๐ ๋ค์ ๋ชฉํ
์ผ์ถ ๋ง์ ์๋ขฐ๊ฐ ๋ง๋ค์ด์ก๋ค.
๋ง์ ์๋ขฐ๋ฅผ ๋ง๋ค๋ฉด์ ์ฌ๋ฌ ์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ๋ค์ ๊ด๋ฆฌํ๊ฒ ๋๋๋ฐ,
๋งค๋ฒ ๋๊ผ๋ ๊ฒ์ด ๋ฒ๊ฑฐ๋ก์์ด์๋ค.
ํ๋ก์ ํธ์์ ์ฌ์ฉํ๋ ๋ชจ๋ ์คํฌ๋ฆฝํฐ๋ธ ์ค๋ธ์ ํธ๋, ๋ด๊ฐ ๋ง๋ ํด๋์ค์ธ Artifact
๋ฅผ ์์๋ฐ๋๋ค.
Artifact
์๋ ๊ณ ์ ํ ์ซ์์ธ ID
๊ฐ ์์ฑ์ผ๋ก ์๊ณ , ์ด ID
๋ฅผ ํตํด Artifact
๋ฅผ ๊ตฌ๋ณํ๋ค.
ํ์ง๋ง ์ด๋ฅผ ์ค์ ํ๋ ๊ฑด ์จ์ ํ ๋ด ๋ชซ์ด๊ธฐ ๋๋ฌธ์,
์ด๊ฒ์ ๊ฒ ๊ด๋ฆฌํ๋ฉด์ Artifact
๋ฅผ ์๋ก ๋ง๋ค๊ฑฐ๋ ์์ ํ ๋ ๋งค๋ฒ ์ ์ ํ ID
๋ฅผ ์ฐพ์ ์ค์ ํด์ค์ผํ๋ค.
์ฌ๊ฐ ๋ฒ๊ฑฐ๋ก์ด ๊ฒ์ด ์๋๋ค.
๋, ์ด๋ฐ Artifact
๋ค์ ๋ถ๋ฅ์ ๋ง๊ฒ ์ ์ฅํด์ผ ํ ๋๊ฐ ์๋ค.
๋จ์ํ ํน์ ๋ถ๋ฅ์ ๋ชจ๋ Artifact
๋ฅผ ๋ชจ๋ ๋ชจ์์ผ ํ๋ ๊ฒฝ์ฐ๋ ์๊ณ , (๋ฐ์ดํฐ ์ ๊ทผ์ ์ํ ๋์
๋๋ฆฌ๋ค)
๋ชฉ์ ์ ๋ง๊ฒ ๋ชจ์์ผ ํ๋ ๊ฒฝ์ฐ๋ ์๋ค. (ํน์ ๋ฑ์ ๋ค์ด๊ฐ ์นด๋๋ค)
์ด๋ฅผ ํ๋ํ๋ ๋๋๊ทธ/๋๋กญํ๋๊ฒ๋ ์ฐธ ๊ท์ฐฎ์ ์์ ์ด๋ค.
์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด, UI ToolKit์ ์ด์ฉํ ์์ ๊ด๋ฆฌ ํด์ ๋ง๋ค์ด๋ณผ ๊ฒ์ด๋ค.