강화 스테이터스 증가에 대한 부분은 이와 같이 처리했다.
private void StatusUpgradeUIUpdate()
{
for(int i = 0; i < _characterUpgradeLevelText.Length; i++)
{
_characterUpgradeLevelText[i].text = $"LV.{2 * (i + 1)}";
List<StatusGrowth> statusGrowths = _currentCharUnit.Status.Data.UpgradeStatData.GetCurrentStatusData(_currentCharUnit.Status.Data.Grade, 2 * (i + 1));
StringBuilder sb = new StringBuilder();
for(int j = 0; j < statusGrowths.Count; j++)
{
sb.Append($"{StatTypeTranslate(statusGrowths[j].Type)} {statusGrowths[j].Value} ");
if (j != statusGrowths.Count - 1 && j % 2 == 1) sb.Append("\n");
}
sb.Append("증가");
_characterUpgradeDescriptionText[i].text = sb.ToString();
}
ActiveUpgradeStatusInfo();
}
private void ActiveUpgradeStatusInfo()
{
int currentUpgradeLevel = _currentCharUnit.Status.Data.UpgradeData.CurrentUpgradeData.UpgradeLevel / 2;
for(int i = 0; i < currentUpgradeLevel; i++)
{
_upgradeStatusDisablePanel[i].SetActive(false);
}
for(int i = currentUpgradeLevel; i < _upgradeStatusDisablePanel.Length; i++)
{
_upgradeStatusDisablePanel[i].SetActive(true);
}
}
private string StatTypeTranslate(StatType type)
{
string text = "";
switch(type)
{
case StatType.MaxHealth: text = "최대체력"; break;
case StatType.MaxMana: text = "최대마나"; break;
case StatType.ManaGain: text = "마나 회복속도"; break;
case StatType.AttackSpeed: text = "공격속도"; break;
case StatType.MoveSpeed: text = "공격속도"; break;
case StatType.PhysicalDamage: text = "물리공격력"; break;
case StatType.MagicDamage: text = "마법공격력"; break;
case StatType.CritChance: text = "크리티컬확률"; break;
case StatType.CritDamage: text = "크리티컬 데미지"; break;
case StatType.PhysicalDefense: text = "물리방어력"; break;
case StatType.MagicDefense: text = "마법방어력"; break;
case StatType.Shield: text = "쉴드"; break;
case StatType.AttackRange: text = "공격범위"; break;
case StatType.AttackCount: text = "공격횟수"; break;
case StatType.CurHp: text = "현재체력"; break;
case StatType.CurMana: text = "현재마나"; break;
}
return text;
}
using System;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "UpgradeStatData", menuName = "Data/Upgrade/UpgradeStatData")]
public class UpgradeStatData : ScriptableObject
{
public List<GradeGrowth> StatData;
public List<StatusGrowth> GetCurrentStatusData(Grade grade, int level)
{
GradeGrowth gradeGrowth = StatData.Find(g => g.CharGrade == grade);
if (gradeGrowth.Equals(default(GradeGrowth)))
{
Debug.LogWarning($"[UpgradeStatData] 해당 Grade({grade}) 데이터가 없음");
return null;
}
LevelGrowth levelGrowth = gradeGrowth.Stats.Find(l => l.Level == level);
if (levelGrowth.Equals(default(LevelGrowth)))
{
Debug.LogWarning($"[UpgradeStatData] Grade({grade}) 내 Level({level}) 데이터가 없음");
return null;
}
return levelGrowth.Stats; // 해당 레벨의 StatusGrowth 리스트 반환
}
}
[Serializable]
public struct GradeGrowth
{
public Grade CharGrade;
public List<LevelGrowth> Stats;
}
[Serializable]
public struct LevelGrowth
{
public int Level;
public List<StatusGrowth> Stats;
}
[Serializable]
public struct StatusGrowth
{
public StatType Type;
public float Value;
}
여기서 유의점으로는, StatType를 다시 맞는 텍스트로 변경하는 작업과 스테이터스가 자연스럽게 표시될 수 있도록 스테이터스 두 개 표시 후 엔터를 하는 방식의 추가가 필요했다.
출력에는 문제가 없으나, 미관상 보기가 안 좋다.
using Firebase.Database;
using System;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Unit_UpgradeUnitData", menuName = "Data/Upgrade/Unit_UpgradeUnitData")]
public class UpgradeUnitData : ScriptableObject
{
// 캐릭터의 업그레이드 레벨 - 레벨이 0일 때는 획득하지 않은 상태
private Grade _grade;
private LevelUpData _levelUpData;
public CurrentUpgradeData CurrentUpgradeData;
public event Action OnLevelUp;
public void Init(Grade grade, LevelUpData data)
{
_grade = grade;
_levelUpData = data;
}
public int GetRequiredPiece()
{
if (CurrentUpgradeData.UpgradeLevel >= 10 ||
CurrentUpgradeData.UpgradeLevel <= 0) return 0;
if (_levelUpData == null)
{
Debug.LogError($"[{name}] LevelUpData가 설정되지 않았습니다.");
return 0;
}
RequirePiece requirePiece = _levelUpData.RequirePieceData.Find(r=>r.Grade == _grade);
if (requirePiece == null)
{
Debug.LogError($"[{name}] {_grade} 등급에 맞는 RequirePiece 데이터가 없습니다.");
return 0;
}
PieceLevelRatio pieceLevelRatio = requirePiece.LevelRatio.Find(l => l.Level == CurrentUpgradeData.UpgradeLevel + 1);
if (pieceLevelRatio == null)
{
Debug.LogError($"[{name}] {_grade} / {CurrentUpgradeData.UpgradeLevel}에 맞는 PieceLevelRatio 데이터가 없습니다.");
return 0;
}
return pieceLevelRatio.RequirePiece;
}
public int GetRequiredGold()
{
if (CurrentUpgradeData.UpgradeLevel >= 10 ||
CurrentUpgradeData.UpgradeLevel <= 0) return 0;
if (_levelUpData == null)
{
Debug.LogError($"[{name}] LevelUpData가 설정되지 않았습니다.");
return 0;
}
RequirePiece requirePiece = _levelUpData.RequirePieceData.Find(r => r.Grade == _grade);
if (requirePiece == null)
{
Debug.LogError($"[{name}] {_grade} 등급에 맞는 RequirePiece 데이터가 없습니다.");
return 0;
}
PieceLevelRatio pieceLevelRatio = requirePiece.LevelRatio.Find(l => l.Level == CurrentUpgradeData.UpgradeLevel + 1);
if (pieceLevelRatio == null)
{
Debug.LogError($"[{name}] {_grade} / {CurrentUpgradeData.UpgradeLevel}에 맞는 PieceLevelRatio 데이터가 없습니다.");
return 0;
}
return pieceLevelRatio.RequireGold;
}
public void AddPiece(int piece)
{
CurrentUpgradeData.CurrentPieces += piece;
}
public async void LevelUp()
{
// 최대레벨 변수 추가?
if (CurrentUpgradeData.UpgradeLevel >= 10) return;
if (CurrentUpgradeData.UpgradeLevel == 0)
{
if(CurrentUpgradeData.CurrentPieces >= 10)
{
CurrentUpgradeData.CurrentPieces -= 10;
CurrentUpgradeData.UpgradeLevel += 1;
OnLevelUp?.Invoke();
}
}
else
{
int requiredPiece = GetRequiredPiece();
int requiredGold = GetRequiredGold();
string uid = FirebaseManager.Auth.CurrentUser.UserId;
var diaRef = FirebaseManager.DataReference.Child("UserData").Child(uid).Child("Gold");
DataSnapshot snapshot = await diaRef.GetValueAsync();
int currentGold = 0;
if (snapshot.Exists && snapshot.Value != null)
{
currentGold = Convert.ToInt32(snapshot.Value);
}
if (CurrentUpgradeData.CurrentPieces >= requiredPiece && currentGold >= requiredGold)
{
CurrentUpgradeData.CurrentPieces -= requiredPiece;
CurrentUpgradeData.UpgradeLevel += 1;
await DBManager.Instance.SubtractGoldAsync(requiredGold);
OnLevelUp?.Invoke();
}
}
}
}
[CreateAssetMenu(fileName = "Unit_LevelUpData", menuName = "Data/Temp/Unit_LevelUpData")]
public class LevelUpData : ScriptableObject
{
public List<RequirePiece> RequirePieceData = new();
}
[Serializable]
public class RequirePiece
{
public Grade Grade;
public List<PieceLevelRatio> LevelRatio = new List<PieceLevelRatio>();
}
/// <summary>
/// 에디터상 입력을 위해 임시로 List 로 처리함. 추후에 Dictionary로 전환할 필요성 있음
/// </summary>
[Serializable]
public class PieceLevelRatio
{
public int RequireGold;
public int RequirePiece;
public int Level;
}
[Serializable]
public class CurrentUpgradeData
{
// 현재 보유 캐릭터 조각 수
public int CurrentPieces;
public int UpgradeLevel;
public void SetData(int currentPieces, int upgradeLevel)
{
CurrentPieces = currentPieces;
UpgradeLevel = upgradeLevel;
}
}