반응형
SMALL
유저의 스탯을 관리하는 UI 제작을 완료하였다.
구현한 기능은 아래와 같다.
- 현재 유저가 장착중인 무기 종류에 따라 바뀌는 무기 이미지 및 스킬 아이콘 변경 (info매니저 & atlas 매니저 참조)
- 유저의 능력치 상승시 영구적인 상승과 일시적인 상능 기능 분리(info 매니저 메서드 생성)
- 스킬 셋 이미지 터치시 팝업창 팝업, 상세 스킬별 상세 정보 확인 (손을 뗄시 팝업창 닫기)
- 무기의 스탯 및 숙련도 info 매니저 참조를 통한 실시간 변경
코드
UIWeaponCharacteristic
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;
using UnityEngine.UI;
public class UIWeaponCharacteristic : MonoBehaviour
{
[SerializeField]
private Text txtWeaponProficiency;
[SerializeField]
private Slider WeaponProficiencySlider;
[SerializeField]
private Text txtWeaponProficiencySlider;
[SerializeField]
private Image imgWeapon_Icon;
[SerializeField]
private Image WeaponSkill1_Icon;
[SerializeField]
private Image WeaponSkill2_Icon;
[SerializeField]
private Image WeaponSkill3_Icon;
[SerializeField]
private Text txtBulletAmount;
[SerializeField]
private Text txtPenetrate;
[SerializeField]
private Text txtkNockBackCharacteristic;
[SerializeField]
private Text txtkMovespeedCharacteristic;
[SerializeField]
private Text txtDashRecover;
[SerializeField]
private UIWeaponSkillPopUp uiWeaponSkillPopUp;
public Action<Vector3,string> onSkillPopup;
public Action onSkillPopupClose;
private SpriteAtlas weaponIconAtlas;
private SpriteAtlas skillIconAtlas;
public void Init()
{
this.onSkillPopup = (pos,skillName) =>
{
this.uiWeaponSkillPopUp.gameObject.SetActive(true);
this.uiWeaponSkillPopUp.RefreshPopup(skillName);
this.uiWeaponSkillPopUp.transform.localPosition = new Vector3(pos.x, pos.y+5, pos.z);
};
this.onSkillPopupClose = () =>
{
this.uiWeaponSkillPopUp.gameObject.SetActive(false);
};
this.weaponIconAtlas = AtlasManager.instance.GetAtlasByName("UIWeaponIcon");
this.skillIconAtlas = AtlasManager.instance.GetAtlasByName("UISkillIcon");
this.RefreshWeaponStat();
this.uiWeaponSkillPopUp.Init();
}
private void OnEnable()
{
this.RefreshWeaponStat();
}
public void RefreshWeaponStat()
{
this.SetWeaponIcon();
this.SetWeaponProficiency();
this.SetWeaponCharactoristic();
}
/// <summary>
/// 무기 아이콘 업데이트
/// </summary>
public void SetWeaponIcon()
{
this.imgWeapon_Icon.sprite = this.weaponIconAtlas.GetSprite(InfoManager.instance.charactoristicInfo.currentWeaponName);
this.SetSkillIcon();
}
/// <summary>
/// 무기 숙련도 업데이트
/// </summary>
public void SetWeaponProficiency()
{
this.txtWeaponProficiency.text = string.Format("숙련도 : {0}", InfoManager.instance.charactoristicInfo.weaponProficiencyLevel);
this.WeaponProficiencySlider.value = InfoManager.instance.charactoristicInfo.weaponProficiencyEXP * 0.01f;
this.txtWeaponProficiencySlider.text = string.Format("{0}/{1}", InfoManager.instance.charactoristicInfo.weaponProficiencyEXP * 100 , 100);
}
/// <summary>
/// 무기 특성 업데이트
/// </summary>
public void SetWeaponCharactoristic()
{
this.txtBulletAmount.text = string.Format("총알 갯수 : {0}", 1);
this.txtPenetrate.text = string.Format("관통력 : {0}", 1);
this.txtkNockBackCharacteristic.text = string.Format("넉백 : {0}", 1);
this.txtkMovespeedCharacteristic.text = string.Format("이동속도 : {0}", 1);
this.txtDashRecover.text = string.Format("대시 회복 : {0}", 1);
}
/// <summary>
/// 스킬 아이콘 업데이트
/// </summary>
public void SetSkillIcon()
{
switch (InfoManager.instance.charactoristicInfo.currentWeaponName)
{
case "AK47":
this.WeaponSkill1_Icon.sprite = this.skillIconAtlas.GetSprite("IconAssultRifleSkill_01");
this.WeaponSkill2_Icon.sprite = this.skillIconAtlas.GetSprite("IconAssultRifleSkill_02");
this.WeaponSkill3_Icon.sprite = this.skillIconAtlas.GetSprite("IconAssultRifleSkill_03");
break;
case "SPAS-12":
this.WeaponSkill1_Icon.sprite = this.skillIconAtlas.GetSprite("IconShotGunSkill_01");
this.WeaponSkill2_Icon.sprite = this.skillIconAtlas.GetSprite("IconShotGunSkill_02");
this.WeaponSkill3_Icon.sprite = this.skillIconAtlas.GetSprite("IconShotGunSkill_03");
break;
case "AWP":
this.WeaponSkill1_Icon.sprite = this.skillIconAtlas.GetSprite("IconSniperRifleSkill_01");
this.WeaponSkill2_Icon.sprite = this.skillIconAtlas.GetSprite("IconSniperRifleSkill_02");
this.WeaponSkill3_Icon.sprite = this.skillIconAtlas.GetSprite("IconSniperRifleSkill_03");
break;
case "UZI":
this.WeaponSkill1_Icon.sprite = this.skillIconAtlas.GetSprite("IconSubmachineGunSkill_01");
this.WeaponSkill2_Icon.sprite = this.skillIconAtlas.GetSprite("IconSubmachineGunSkill_02");
this.WeaponSkill3_Icon.sprite = this.skillIconAtlas.GetSprite("IconSubmachineGunSkill_03");
break;
}
}
// 테스트용
void Update()
{
if(Input.GetMouseButtonDown(1))
{
if(InfoManager.instance.charactoristicInfo.currentWeaponName == "AK47")
{
InfoManager.instance.charactoristicInfo.currentWeaponName = "AWP";
this.SetWeaponIcon();
}
else if (InfoManager.instance.charactoristicInfo.currentWeaponName == "AWP")
{
InfoManager.instance.charactoristicInfo.currentWeaponName = "UZI";
this.SetWeaponIcon();
}
else if(InfoManager.instance.charactoristicInfo.currentWeaponName == "UZI")
{
InfoManager.instance.charactoristicInfo.currentWeaponName = "SPAS-12";
this.SetWeaponIcon();
}
else if(InfoManager.instance.charactoristicInfo.currentWeaponName == "SPAS-12")
{
InfoManager.instance.charactoristicInfo.currentWeaponName = "AK47";
this.SetWeaponIcon();
}
}
}
}
UIWeaponSkillPopUp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.U2D;
public class UIWeaponSkillPopUp : MonoBehaviour
{
[SerializeField]
private Image imgStatPopUpSkill;
[SerializeField]
private Text txtStatPopUpSkillName;
[SerializeField]
private Text txtStatPopUpSkillDetail;
private SpriteAtlas uiSkillAtlas;
public void Init()
{
this.uiSkillAtlas = AtlasManager.instance.GetAtlasByName("UISkillIcon");
this.gameObject.SetActive(false);
}
public void RefreshPopup(string skillName)
{
//실제 게임에서는 데이터 매니저 참고해서 할당 예정
switch(skillName)
{
case "IconAssultRifleSkill_01":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "AssultRifleSkill_01";
this.txtStatPopUpSkillDetail.text = "AssultRifleSkill_01 스킬 상세 설명";
break;
case "IconAssultRifleSkill_02":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "AssultRifleSkill_02";
this.txtStatPopUpSkillDetail.text = "AssultRifleSkill_02 스킬 상세 설명";
break;
case "IconAssultRifleSkill_03":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "AssultRifleSkill_03";
this.txtStatPopUpSkillDetail.text = "AssultRifleSkill_03 스킬 상세 설명";
break;
case "IconShotGunSkill_01":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "ShotGunSkill_01";
this.txtStatPopUpSkillDetail.text = "ShotGunSkill_01 스킬 상세 설명";
break;
case "IconShotGunSkill_02":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "IconShotGunSkill_02";
this.txtStatPopUpSkillDetail.text = "ShotGunSkill_02 스킬 상세 설명";
break;
case "IconShotGunSkill_03":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "IconShotGunSkill_03";
this.txtStatPopUpSkillDetail.text = "ShotGunSkill_03 스킬 상세 설명";
break;
case "IconSniperRifleSkill_01":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "SniperRifleSkill_01";
this.txtStatPopUpSkillDetail.text = "SniperRifleSkill_01 스킬 상세 설명";
break;
case "IconSniperRifleSkill_02":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "AssultRifleSkill_02";
this.txtStatPopUpSkillDetail.text = "AssultRifleSkill_02 스킬 상세 설명";
break;
case "IconSniperRifleSkill_03":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "SniperRifleSkill_03";
this.txtStatPopUpSkillDetail.text = "SniperRifleSkill_03 스킬 상세 설명";
break;
case "IconSubmachineGunSkill_01":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "SubmachineGunSkill_01";
this.txtStatPopUpSkillDetail.text = "SubmachineGunSkill_01 스킬 상세 설명";
break;
case "IconSubmachineGunSkill_02":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "SubmachineGunSkill_02";
this.txtStatPopUpSkillDetail.text = "SubmachineGunSkill_02 스킬 상세 설명";
break;
case "IconSubmachineGunSkill_03":
this.imgStatPopUpSkill.sprite = this.uiSkillAtlas.GetSprite(skillName);
this.txtStatPopUpSkillName.text = "SubmachineGunSkill_03";
this.txtStatPopUpSkillDetail.text = "SubmachineGunSkill_03 스킬 상세 설명";
break;
}
}
}
WeaponSkillCell
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class WeaponSkillCell : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
[SerializeField]
private UIWeaponCharacteristic uIWeaponCharacteristic;
public void OnPointerDown(PointerEventData eventData)
{
var weaponSkillIcon = this.transform.GetChild(0);
var skillName = weaponSkillIcon.GetComponent<Image>().sprite.name.Replace("(Clone)","");
Debug.Log(skillName);
this.uIWeaponCharacteristic.onSkillPopup(this.transform.localPosition, skillName);
}
public void OnPointerUp(PointerEventData eventData)
{
this.uIWeaponCharacteristic.onSkillPopupClose();
}
}
InfoManager
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.IO;
public class InfoManager
{
public static readonly InfoManager instance = new InfoManager();
public InfoManager() { }
public StatInfo statInfo = new StatInfo();
public InventoryInfo inventoryInfo = new InventoryInfo();
public WeaponCharactoristicInfo charactoristicInfo = new WeaponCharactoristicInfo();
/// <summary>
/// 능력치 초기화 메서드 + 자동저장
/// </summary>
/// <param name="powerStat">최종 수정 공격력</param>
/// <param name="fireRateStat">최종 수정 공격속도</param>
/// <param name="criticalHitAmount">최종 수정 치명타 피해</param>
/// <param name="criticalHitChance">최종 수정 치명타 확률</param>
public void InitStats(int powerStat,int fireRateStat,int criticalHitAmount,int criticalHitChance)
{
this.statInfo.powerStat = powerStat;
this.statInfo.fireRateStat = fireRateStat;
this.statInfo.criticalHitAmount = criticalHitAmount;
this.statInfo.criticalHitChance = criticalHitChance;
this.SaveStatInfo();
}
/// <summary>
/// 총기특성 초기화 + 총기 숙련도 초기화 ( 던전씬 엔드시 반드시 호출 )
/// </summary>
public void InitCharactorlisticsAndWeaponProficiency()
{
this.charactoristicInfo.movespeedCharacteristic = 1;
this.charactoristicInfo.knockBackCharacteristic = 1;
this.charactoristicInfo.bulletAmountCharacteristic = 1;
this.charactoristicInfo.dashRecoverCharacteristic = 1;
this.charactoristicInfo.penetrateCharacteristic = 1;
this.charactoristicInfo.weaponProficiencyLevel = 0;
this.charactoristicInfo.weaponProficiencyEXP = 0;
}
/// <summary>
/// 플레이어 능력치 : 공격력 영구증가 + 자동 저장
/// </summary>
/// <param name="amount">영구증가시킬 공격력(기본값 1)</param>
public void PermanentPowerStatIncrease(int amount = 1)
{
this.statInfo.powerStat += amount;
this.SaveStatInfo();
}
/// <summary>
/// 플레이어 능력치 : 공격속도 영구증가 + 자동 저장
/// </summary>
/// <param name="amount">영구증가시킬 공격속도(기본값 1)</param>
public void PermanentFireRateStatIncrease(int amount = 1)
{
this.statInfo.fireRateStat += amount;
this.SaveStatInfo();
}
/// <summary>
/// 플레이어 능력치 : 치명타 확률 영구증가 + 자동 저장
/// </summary>
/// <param name="amount">영구증가시킬 치명타 피해(기본값 1)</param>
public void PermanentCriticalHitAmountIncrease(int amount = 1)
{
this.statInfo.criticalHitAmount += amount;
this.SaveStatInfo();
}
/// <summary>
/// 플레이어 능력치 : 치명타 확률 영구증가 + 자동 저장
/// </summary>
/// <param name="amount">영구증가시킬 치명타 확률(기본값 1)</param>
public void PermanentCriticalHitChanceIncrease(int amount = 1)
{
this.statInfo.criticalHitChance += amount;
this.SaveStatInfo();
}
/// <summary>
/// 플레이어 StatInfo 불러오기
/// </summary>
public void LoadStatInfo()
{
string path = string.Format("{0}/stat_info.json", Application.persistentDataPath);
string json = File.ReadAllText(path);
this.statInfo = JsonConvert.DeserializeObject<StatInfo>(json);
Debug.Log("플레이어 능력치 데이터 로드 완료");
}
/// <summary>
/// 플레이어 StatInfo 저장
/// </summary>
public void SaveStatInfo()
{
string path = string.Format("{0}/stat_info.json", Application.persistentDataPath);
string json = JsonConvert.SerializeObject(this.statInfo);
File.WriteAllText(path, json);
Debug.Log("플레이어 능력치데이터 저장 완료");
}
/// <summary>
/// 인벤토리 갯수 영구 증가(1개) + 자동 저장
/// </summary>
public void PermanentInventoryCountIncrease()
{
this.inventoryInfo.InventoryCount += 1;
this.SaveInventoryInfo();
}
/// <summary>
/// 플레이어 InventoryInfo 불러오기
/// </summary>
public void LoadInventoryInfo()
{
string path = string.Format("{0}/Inventory_Info.json", Application.persistentDataPath);
string json = File.ReadAllText(path);
this.inventoryInfo = JsonConvert.DeserializeObject<InventoryInfo>(json);
Debug.Log("인벤토리 데이터 로드 완료");
}
/// <summary>
/// 플레이어 Inventory 저장
/// </summary>
public void SaveInventoryInfo()
{
string path = string.Format("{0}/Inventory_Info.json", Application.persistentDataPath);
string json = JsonConvert.SerializeObject(this.inventoryInfo);
File.WriteAllText(path, json);
Debug.Log("인벤토리 데이터 저장 완료");
}
/// <summary>
/// 총기특성 : 이동 속도 증가 + 1
/// </summary>
public void IncreaseMovespeedCharacteristic()
{
this.charactoristicInfo.movespeedCharacteristic += 1;
}
/// <summary>
/// 총기특성 : 넉백 증가 + 1
/// </summary>
public void IncreaseKnockBackCharacteristic()
{
this.charactoristicInfo.knockBackCharacteristic += 1;
}
/// <summary>
/// 총기특성 : 총알 숫자 증가 + 1
/// </summary>
public void IncreaseBulletAmountCharacteristic()
{
this.charactoristicInfo.bulletAmountCharacteristic += 1;
}
/// <summary>
/// 총기특성 : 대시 회복 속도 증가 + 1
/// </summary>
public void IncreaseDashRecoverCharacteristic()
{
this.charactoristicInfo.dashRecoverCharacteristic += 1;
}
/// <summary>
/// 총기특성 : 관통력 증가 + 1
/// </summary>
public void IncreasePenetrateCharacteristic()
{
this.charactoristicInfo.penetrateCharacteristic += 1;
}
/// <summary>
/// 총기 숙련도 증가 +1
/// </summary>
public void IncreaseWeaponPreficiencyLevel()
{
this.charactoristicInfo.weaponProficiencyLevel += 1;
}
/// <summary>
/// 총기 경험치 증가 +4
/// </summary>
public void IncreaseWeaponProficiencyEXP()
{
this.charactoristicInfo.weaponProficiencyEXP += 4;
}
/// <summary>
/// 현재 들고 있는 총기 이름 변경 (AK47, AWP, UZI, SPAS-12) (기본값 : AK47)
/// </summary>
/// <param name="weaponName">현재 들고 있는 무기 이름</param>
public void ChangeCurrentWeaponName(string weaponName = "AK47")
{
this.charactoristicInfo.currentWeaponName = weaponName;
}
}
명시적으로 메서드를 하나하나 구현해 주다보니 인포매니저의 역할이 커지고 스크립트가 길어졌다.
해결할수 있는 방법이 있을지 고민해 보아야겠다.
반응형
LIST
'프로젝트 > 건즈앤 레이첼스' 카테고리의 다른 글
[유니티 프로젝트] 인벤토리 스탯창 구현 .4 - 인벤토리 상세 기능 구현 (0) | 2023.04.13 |
---|---|
[GPGS] 구글 개발자 등록 방법 (1) | 2023.04.11 |
[유니티 프로젝트] 인벤토리 스탯창 구현 .1 (1) | 2023.04.09 |
[유니티 프로젝트] A* 알고리즘을 이용한 맵 생성 (로직 변경) (0) | 2023.04.05 |
[유니티 프로젝트] 옵션 UI .3 (0) | 2023.04.03 |