오늘은 자동재화 추가에 해금조건을 걸어 조건이 충족됬을 시에 업그레이드 버튼이 활성화가 되고 해금됬을시에 자동재화가 실시간에 반영되야한다.
작업 개요
오늘의 작업은 Unity 프로젝트에서 RootBase와 Root1 클래스, 그리고 UpgradeButton 클래스의 기능을 개선하고 확장하는 것이었습니다. 특히, 특정 조건이 충족되면 Root1 클래스를 해금할 수 있도록 하고, UI와 상호작용을 적절하게 처리하는 것이 목표였습니다.
RootBase 클래스의 수정
RootBase 클래스는 게임의 뿌리 시스템을 관리하는 기본 클래스입니다. 여기에 터치 레벨을 기준으로 해금 조건을 추가하고, UI 업데이트와 관련된 여러 기능을 개선했습니다.
주요 수정 사항:
해금 조건 추가: 터치 레벨이 특정 수준에 도달하면 해금할 수 있도록 조건을 추가했습니다.
UI 업데이트 개선: 해금 상태에 따라 UI에 표시되는 텍스트를 업데이트했습니다.
using TMPro;
using UnityEngine;
public interface IRoot
{
void ApplyIncreaseRate(float rate);
float GetTotalLifeGeneration();
void Unlock();
}
public class RootBase : MonoBehaviour, IRoot
{
public int rootLevel = 0; // 초기 레벨을 0으로 설정
public float baseLifeGeneration = 1;
public int lifeGenerationPerLevel = 1;
public int upgradeLifeCost = 20;
public float generationInterval = 1f;
public TextMeshProUGUI rootLevelText;
public TextMeshProUGUI rootUpgradeCostText;
public TextMeshProUGUI generationRateText; // 생산률을 나타내는 텍스트 추가
public bool isUnlocked = false; // 잠금 상태를 나타내는 변수 추가
private float timer;
public TouchData touchData; // TouchData 참조
public int unlockThreshold = 5; // 잠금 해제에 필요한 터치 레벨
public delegate void LifeGenerated(float amount);
protected event LifeGenerated OnLifeGenerated;
public event System.Action OnGenerationRateChanged;
protected virtual void Start()
{
OnLifeGenerated -= LifeManager.Instance.IncreaseWater;
OnLifeGenerated += LifeManager.Instance.IncreaseWater;
OnGenerationRateChanged?.Invoke(); // 초기화 시 이벤트 트리거
UpdateUI();
}
protected virtual void Update()
{
CheckUnlockCondition(); // 업데이트 시 잠금 해제 조건 확인
if (isUnlocked && rootLevel > 0)
{
timer += Time.deltaTime;
if (timer >= generationInterval)
{
GenerateLife();
timer = 0f;
}
}
}
protected virtual void GenerateLife()
{
if (!isUnlocked || rootLevel == 0) return; // 잠금 해제된 경우에만 생명력 생성
float generatedLife = GetTotalLifeGeneration();
InvokeLifeGenerated(generatedLife);
}
protected void InvokeLifeGenerated(float amount)
{
OnLifeGenerated?.Invoke(amount);
}
public int CalculateUpgradeCost()
{
return (rootLevel + 1) * 20; // 업그레이드 비용은 다음 레벨 기준으로 계산
}
public virtual void UpgradeLifeGeneration()
{
if (!isUnlocked) return; // 잠금 해제된 경우에만 업그레이드 가능
rootLevel++;
if (rootLevel % 25 == 0)
{
baseLifeGeneration *= 2;
}
else
{
baseLifeGeneration += lifeGenerationPerLevel;
}
upgradeLifeCost = CalculateUpgradeCost();
OnGenerationRateChanged?.Invoke();
UpdateUI();
}
public virtual void UpdateUI()
{
UpdateRootLevelUI(rootLevel, upgradeLifeCost);
UpdateGenerationRateUI(GetTotalLifeGeneration()); // 생산률 업데이트 추가
}
public virtual void ApplyIncreaseRate(float rate)
{
if (!isUnlocked) return; // 잠금 해제된 경우에만 적용 가능
baseLifeGeneration *= 1 + rate;
OnGenerationRateChanged?.Invoke();
UpdateUI();
}
public virtual void UpdateRootLevelUI(int rootLevel, int upgradeCost)
{
if (rootLevelText != null)
{
if (isUnlocked)
{
rootLevelText.text = $"뿌리 레벨: {rootLevel}";
}
else
{
rootLevelText.text = $"뿌리 레벨: 0";
}
}
if (rootUpgradeCostText != null)
{
rootUpgradeCostText.text = isUnlocked ? $"강화 비용: {upgradeCost} 물" : $"해금 비용: {upgradeCost} 물 (레벨: {unlockThreshold} 필요)";
}
}
public virtual void UpdateGenerationRateUI(float generationRate)
{
if (generationRateText != null)
{
generationRateText.text = isUnlocked ? $"생산률: {generationRate} 물/초" : $"잠금 해제 조건: 터치 레벨 {unlockThreshold}";
}
}
public virtual float GetTotalLifeGeneration()
{
return isUnlocked && rootLevel > 0 ? baseLifeGeneration : 0; // 잠금 해제되고 레벨이 1 이상인 경우에만 생산
}
public void Unlock()
{
int unlockCost = CalculateUpgradeCost(); // 해금 비용 계산 (처음 업그레이드 비용)
if (LifeManager.Instance.HasSufficientWater(unlockCost))
{
LifeManager.Instance.DecreaseWater(unlockCost);
isUnlocked = true;
rootLevel = 1; // 잠금 해제 시 레벨 1로 설정
OnGenerationRateChanged?.Invoke(); // 잠금 해제 시 이벤트 트리거
UpdateUI();
}
else
{
Debug.Log("물이 부족하여 해금할 수 없습니다.");
}
}
private void CheckUnlockCondition()
{
// 버튼 활성화 처리를 위해 조건 확인 로직을 유지
if (!isUnlocked && touchData != null && touchData.touchIncreaseLevel >= unlockThreshold)
{
UpdateUI();
}
}
}
Root1 클래스는 RootBase 클래스를 상속받아 특정 조건에서만 해금되는 뿌리를 구현합니다. 이 클래스에서는 해금 조건을 5레벨로 설정했습니다.
public class Root1 : RootBase
{
protected override void Start()
{
unlockThreshold = 5; // 5레벨이 되어야 해금
base.Start();
LifeManager.Instance.RegisterRoot(this);
UpdateUI();
}
protected override void GenerateLife()
{
float generatedLife = GetTotalLifeGeneration();
InvokeLifeGenerated(generatedLife);
}
public override void UpdateUI()
{
base.UpdateUI();
}
public override float GetTotalLifeGeneration()
{
return base.GetTotalLifeGeneration(); // 기본 클래스의 동작을 유지
}
}
UpgradeButton 클래스는 UI 버튼을 관리하며, 버튼이 클릭될 때 적절한 업그레이드 또는 해금 동작을 수행합니다. 이 클래스에서는 버튼의 Interactable 상태를 조건에 따라 업데이트하고, 해금 조건이 충족되면 버튼을 활성화합니다.
주요 수정 사항:
조건 충족 시 버튼 활성화: 해금 조건이 충족되었을 때만 버튼이 활성화되도록 수정했습니다.
버튼 클릭 시 해금/업그레이드 처리: 버튼을 클릭했을 때 해금 또는 업그레이드를 처리하도록 메서드를 추가했습니다.
using UnityEngine;
using UnityEngine.UI;
public class UpgradeButton : MonoBehaviour
{
public ResourceManager resourceManager;
public RootBase root;
public Spirit spirit;
public TouchInputManager touchInputManager;
public Touchdata touchdata;
public enum UpgradeType
{
Root,
Spirit,
Touch,
Tree,
MoveSpeed,
WaterIncrease
}
public UpgradeType upgradeType;
public int upgradeAmount = 1;
private Button upgradeButton;
private void Start()
{
upgradeButton = GetComponent<Button>();
upgradeButton.onClick.AddListener(OnUpgradeButtonClicked);
if (upgradeType == UpgradeType.Root && root != null)
{
UpdateUpgradeCostUI(root.rootLevel);
}
else if (upgradeType == UpgradeType.Spirit && spirit != null)
{
UpdateUpgradeCostUI(spirit.spiritLevel);
}
else if (upgradeType == UpgradeType.Tree && resourceManager != null)
{
UpdateUpgradeCostUI(resourceManager.lifeManager.currentLevel);
}
}
private void Update()
{
UpdateButtonInteractable();
}
private void UpdateButtonInteractable()
{
bool canUpgrade = false;
switch (upgradeType)
{
case UpgradeType.Root:
canUpgrade = root != null && ((!root.isUnlocked && root.touchData != null && root.touchData.touchIncreaseLevel >= root.unlockThreshold && LifeManager.Instance.HasSufficientWater(root.CalculateUpgradeCost()))
|| (root.isUnlocked && LifeManager.Instance.HasSufficientWater(root.CalculateUpgradeCost())));
break;
case UpgradeType.Spirit:
canUpgrade = spirit != null && LifeManager.Instance.HasSufficientWater(spirit.CalculateUpgradeCost());
break;
case UpgradeType.Touch:
canUpgrade = LifeManager.Instance.HasSufficientWater(LifeManager.Instance.touchData.upgradeLifeCost);
break;
case UpgradeType.Tree:
canUpgrade = LifeManager.Instance.HasSufficientWater(LifeManager.Instance.CalculateWaterNeededForUpgrade(upgradeAmount));
break;
}
upgradeButton.interactable = canUpgrade;
}
private void OnUpgradeButtonClicked()
{
switch (upgradeType)
{
case UpgradeType.Root:
HandleRootUpgradeOrUnlock();
break;
case UpgradeType.Spirit:
HandleSpiritUpgrade();
break;
case UpgradeType.Touch:
HandleTouchUpgrade();
break;
case UpgradeType.Tree:
HandleGeneralUpgrade();
break;
}
}
private void HandleRootUpgradeOrUnlock()
{
if (root == null) return;
if (!root.isUnlocked)
{
HandleRootUnlock();
}
else
{
HandleRootUpgrade();
}
}
private void HandleRootUnlock()
{
if (root == null || root.isUnlocked) return;
int unlockCost = root.CalculateUpgradeCost();
if (LifeManager.Instance.HasSufficientWater(unlockCost))
{
LifeManager.Instance.DecreaseWater(unlockCost);
root.Unlock();
root.UpdateUI();
resourceManager.UpdateTotalLifeIncreaseUI();
}
else
{
Debug.Log("물이 부족하여 해금할 수 없습니다.");
}
}
private void HandleRootUpgrade()
{
if (root == null || !root.isUnlocked) return;
int upgradeCost = root.CalculateUpgradeCost();
if (LifeManager.Instance.HasSufficientWater(upgradeCost))
{
LifeManager.Instance.DecreaseWater(upgradeCost);
root.UpgradeLifeGeneration();
root.UpdateUI();
resourceManager.UpdateTotalLifeIncreaseUI();
}
else
{
Debug.Log("물이 부족하여 강화할 수 없습니다.");
}
}
private void HandleSpiritUpgrade()
{
int upgradeCost = spirit.CalculateUpgradeCost();
if (LifeManager.Instance.HasSufficientWater(upgradeCost))
{
LifeManager.Instance.DecreaseWater(upgradeCost);
spirit.spiritLevel++;
spirit.upgradeEnergyCost *= 2;
spirit.UpdateUI();
}
else
{
Debug.Log("에너지가 부족하여 강화할 수 없습니다.");
}
}
private void HandleTouchUpgrade()
{
TouchData touchData = LifeManager.Instance.touchData;
int upgradeLifeCost = LifeManager.Instance.touchData.upgradeLifeCost;
if (LifeManager.Instance.HasSufficientWater(upgradeLifeCost))
{
LifeManager.Instance.DecreaseWater(upgradeLifeCost);
LifeManager.Instance.touchData.UpgradeTouchGeneration();
UIManager.Instance.touchData.UpdateTouchUI(touchData.touchIncreaseLevel, touchData.touchIncreaseAmount, touchData.upgradeLifeCost);
}
else
{
Debug.Log("물이 부족하여 강화할 수 없습니다.");
}
}
private void HandleGeneralUpgrade()
{
int waterNeededForUpgrade = LifeManager.Instance.CalculateWaterNeededForUpgrade(upgradeAmount);
if (LifeManager.Instance.HasSufficientWater(waterNeededForUpgrade))
{
LifeManager.Instance.DecreaseWater(waterNeededForUpgrade);
LifeManager.Instance.currentLevel += upgradeAmount;
resourceManager.UpdateUI();
resourceManager.UpdateGroundSize();
}
else
{
Debug.Log("물이 부족하여 강화할 수 없습니다.");
}
}
private void UpdateUpgradeCostUI(int newLevel)
{
if (upgradeType == UpgradeType.Root && root != null)
{
int upgradeCost = root.CalculateUpgradeCost();
UIManager.Instance.root.UpdateRootLevelUI(root.rootLevel, upgradeCost);
}
else if (upgradeType == UpgradeType.Spirit && spirit != null)
{
int upgradeCost = spirit.upgradeEnergyCost;
UIManager.Instance.spiritData.UpdateSpiritLevelUI(spirit.spiritLevel, upgradeCost);
}
else if (upgradeType == UpgradeType.Touch && touchInputManager != null)
{
UIManager.Instance.touchData.UpdateTouchUI(LifeManager.Instance.touchData.touchIncreaseLevel,
LifeManager.Instance.touchData.touchIncreaseAmount,
LifeManager.Instance.touchData.upgradeLifeCost);
}
else if (upgradeType == UpgradeType.Tree && resourceManager != null)
{
int waterNeededForCurrentLevel = resourceManager.lifeManager.CalculateWaterNeededForUpgrade(1);
// uiManager.UpdateUpgradeRequirementUI(resourceManager.lifeManager.currentLevel, waterNeededForCurrentLevel);
}
}
}
결론
오늘의 작업을 통해 Root1 클래스의 해금 조건을 보다 명확하게 정의하고, UI와 상호작용이 보다 직관적으로 이루어지도록 개선하였습니다.
