게임클라이언트 프로그래밍/Guns N Rachel's
UIShop 디자인 패턴 적용. Factory Pattern(팩토리패턴)
Game Client Lee Hwanguk
2023. 4. 21. 03:37
* 어제 만든 UIShop 에 수정해야하는 부분이 생겼다. 기존 방식은 모든 Cell을 생성해놓고 활성/ 비활성으로 동작하는 방식이었는데 기획해 놓은 시스템을 적용하려니 문제 투성이었다.
셀을 생성할때 셀의 요소들을 유연하게 제어하기 위하여 팩토리 패턴을 사용하여 생성하는 방식으로 변경해보았다
팩토리 패턴 중 추상 팩토리 패턴을 사용하였다.
구조를 먼저 짜보았다. AbsEquipmentFactory 클래스를 abstract 추상클래스로 만든 후 메서드들을정의한다
(image의 color변경 메서드, stat 변경 메서드)
AbsEquipmentFactory 를 상속받은 ShopSwordFactory 메서드를 만들었다(Sword,Axe,Arrow,Wand 가 있다. 모두 같은 방식으로 만들었다.) 상속받은 AbsEquipmentFactory 의 메서드를 구체화하였다.
ShopFactory 를 만들었다 ShopSwordFactory에서 조립된 부품들을 직접적으로 생산하는 클래스이다(Instantiate)
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
using UnityEngine.UI;
public abstract class AbsEquipmentFactory
{
public abstract Color32 MakeGradeBGColor(string grade);
public abstract Sprite MakeEquipmentImage(string grade);
public abstract int MakeEquipmentStat(string grade);
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ShopSwordFactory : AbsShopFactory
{
public override Color MakeFrameColor(string grade)
{
Color gradeColor = new Color();
switch (grade)
{
case "Wood":
gradeColor = new Color32(176, 82, 0, 255);
break;
case "Iron":
gradeColor = new Color32(192, 178, 166, 255);
break;
case "Gold":
gradeColor = new Color32(255, 255, 0, 255);
break;
case "Diamond":
gradeColor = new Color32(0, 255, 188, 255);
break;
}
return gradeColor;
}
public override Sprite MakeShopIconImage(string grade)
{
var atlas = AtlasManager.instance.GetAtlasByName("UIShopIcon");
Sprite SwordImage = null;
switch (grade)
{
case "Wood":
SwordImage = atlas.GetSprite("Wood_Sword");
break;
case "Iron":
SwordImage = atlas.GetSprite("Iron_Sword");
break;
case "Gold":
SwordImage = atlas.GetSprite("Gold_Sword");
break;
case "Diamond":
SwordImage = atlas.GetSprite("Diamond_Sword");
break;
}
return SwordImage;
}
public override string MakeShopName(string grade)
{
string name = null;
switch (grade)
{
case "Wood":
name = "나무검";
break;
case "Iron":
name = "강철검";
break;
case "Gold":
name = "황금검";
break;
case "Diamond":
name = "다이아몬드검";
break;
}
return name;
}
public override int MakeShopPowerStat(string grade)
{
int powerStat = 0;
switch (grade)
{
case "Wood":
powerStat = 10;
break;
case "Iron":
powerStat = 20;
break;
case "Gold":
powerStat = 30;
break;
case "Diamond":
powerStat = 40;
break;
}
return powerStat;
}
public override int MakeShopCriticalHitAmount(string grade)
{
int criticalHitAmount = 0;
switch (grade)
{
case "Wood":
criticalHitAmount = 0;
break;
case "Iron":
criticalHitAmount = 0;
break;
case "Gold":
criticalHitAmount = 0;
break;
case "Diamond":
criticalHitAmount = 0;
break;
}
return criticalHitAmount;
}
public override int MakeShopCriticalHitChance(string grade)
{
int criticalHitChance = 0;
switch (grade)
{
case "Wood":
criticalHitChance = 0;
break;
case "Iron":
criticalHitChance = 0;
break;
case "Gold":
criticalHitChance = 0;
break;
case "Diamond":
criticalHitChance = 0;
break;
}
return criticalHitChance;
}
public override int MakeShopFireRateStat(string grade)
{
int fireRateStat = 0;
switch (grade)
{
case "Wood":
fireRateStat = 0;
break;
case "Iron":
fireRateStat = 0;
break;
case "Gold":
fireRateStat = 0;
break;
case "Diamond":
fireRateStat = 0;
break;
}
return fireRateStat;
}
public override int MakeShopRecoveryAmount(string grade)
{
int recoveryAmount = 0;
switch (grade)
{
case "Wood":
recoveryAmount = 0;
break;
case "Iron":
recoveryAmount = 0;
break;
case "Gold":
recoveryAmount = 0;
break;
case "Diamond":
recoveryAmount = 0;
break;
}
return recoveryAmount;
}
}
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ShopFactory : MonoBehaviour
{
[SerializeField]
private GameObject swordPrefab;
[SerializeField]
private GameObject axePrefab;
[SerializeField]
private GameObject wandPrefab;
[SerializeField]
private GameObject arrowPrefab;
[SerializeField]
private GameObject foodPrefab;
public GameObject CreatShopCell(string cellName)
{
var grade=this.ExtractGrade(cellName);
GameObject shopCell=null;
//if (cellName.Contains("Sword")) this.CreatShopSword(grade);
//else if (cellName.Contains("Axe")) this.CreatShopAxe(grade);
//else if(cellName.Contains("Arrow")) this.CreatShopArrow(grade);
//else if (cellName.Contains("Wand")) this.CreatShopWand(grade);
//else if (cellName.Contains("Food")) this.CreatShopFood(grade);
return shopCell;
}
private string ExtractGrade(string EquipmentName)
{
var index = EquipmentName.IndexOf('_');
var grade = EquipmentName.Substring(0, index);
return grade;
}
public void CreatShopSword(string grade,Transform content)
{
AbsShopFactory swordFactory = new ShopSwordFactory();
var swordGo=Instantiate(this.swordPrefab, content).GetComponent<EquipmentCell>();
swordGo.name= swordFactory.MakeShopName(grade);
swordGo.powerStat= swordFactory.MakeShopPowerStat(grade);
swordGo.criticalHitAmount= swordFactory.MakeShopCriticalHitAmount(grade);
swordGo.criticalHitChance= swordFactory.MakeShopCriticalHitChance(grade);
swordGo.fireRateStat= swordFactory.MakeShopFireRateStat(grade);
swordGo.recoveryAmount= swordFactory.MakeShopRecoveryAmount(grade);
swordGo.transform.GetChild(1).GetComponent<Image>().sprite= swordFactory.MakeShopIconImage(grade);
swordGo.transform.GetChild(0).GetComponent<Image>().color= swordFactory.MakeFrameColor(grade);
}
//private void CreatShopAxe(string grade)
//{
// AbsShopFactory axeFactory= new ShopAxeFactory();
// var axeGo=Instantiate(this.axePrefab);
// axeFactory.MakeFrameColor(grade);
// axeFactory.MakeShopIconImage(grade);
// axeFactory.MakeShopName(grade);
// axeFactory.MakeShopPowerStat(grade);
// axeFactory.MakeShopCriticalHitAmount(grade);
// axeFactory.MakeShopCriticalHitChance(grade);
// axeFactory.MakeShopFireRateStat(grade);
// axeFactory.MakeShopRecoveryAmount(grade);
//}
//private void CreatShopArrow(string grade)
//{
// AbsShopFactory arrowFactory= new ShopArrowFactory();
// var arrowGo=Instantiate(this.arrowPrefab);
// arrowFactory.MakeFrameColor(grade);
// arrowFactory.MakeShopIconImage(grade);
// arrowFactory.MakeShopName(grade);
// arrowFactory.MakeShopPowerStat(grade);
// arrowFactory.MakeShopCriticalHitAmount(grade);
// arrowFactory.MakeShopCriticalHitChance(grade);
// arrowFactory.MakeShopFireRateStat(grade);
// arrowFactory.MakeShopRecoveryAmount(grade);
//}
//private void CreatShopWand(string grade)
//{
// AbsShopFactory wandFactory = new ShopWandFactory();
// var WandGo=Instantiate(this.wandPrefab);
// wandFactory.MakeFrameColor(grade);
// wandFactory.MakeShopIconImage(grade);
// wandFactory.MakeShopName(grade);
// wandFactory.MakeShopPowerStat(grade);
// wandFactory.MakeShopCriticalHitAmount(grade);
// wandFactory.MakeShopCriticalHitChance(grade);
// wandFactory.MakeShopFireRateStat(grade);
// wandFactory.MakeShopRecoveryAmount(grade);
//}
//private void CreatShopFood(string grade)
//{
// AbsShopFactory foodFactory = new ShopFoodFactory();
// Instantiate(this.foodPrefab);
// foodFactory.MakeFrameColor(grade);
// foodFactory.MakeShopIconImage(grade);
// foodFactory.MakeShopName(grade);
// foodFactory.MakeShopPowerStat(grade);
// foodFactory.MakeShopCriticalHitAmount(grade);
// foodFactory.MakeShopCriticalHitChance(grade);
// foodFactory.MakeShopFireRateStat(grade);
// foodFactory.MakeShopRecoveryAmount(grade);
//}
}
아직 만들어놓은 시스템으로 옴기기에는 공부가 조금 더 필요할 것 같아서 테스트 용으로 셀 하나만 생성해보았다
public void CreatNormaCell()
{
//Test
//Shuffle(this.ranGrad);
//List<string> list = new List<string>();
//list.Capacity = (int)eShopType.Dungeon;
//this.ranGrad.Clear();
this.shopFactory.CreatShopSword("Gold", this.content);
//this.shopFactory.CreatShopSword("Wood", this.content);
//this.shopFactory.CreatShopSword("Diamond", this.content);
//this.shopFactory.CreatShopSword("Wood", this.content);
}
매개변수인 "Gold"를 grade로 받아 생성되었다. 이제 기획해놓은 시스템으로 옴겨야겠다.