Untiy 2D 팀 프로젝트 궁수의 전설 래퍼런스 작품 만들기
오늘로 팀프로젝트 2일차 시차 1일차때는 조원들과 프로젝트 계획과 약속을 정하고 끝이 나서 작품 제작은 2일차 부터 시작이 되었다.
이 프로젝트에서 내가 담당한 파트
- 모든 투사체 관리
- 스킬 담당
이 두가지를 메인으로 담당을 하게 되었다.
그래서 오늘 궁수의 전설에서 맵이 클리어 되었을 때 스킬을 선택하는 기능을 구연해 보았다.
먼저 스킬의 종류를 플레이어 스탯효과, 투사체 스탯효과, 액티브 스킬, 패시브 스킬로 나누어 작성하였다.
스킬 리스트를 만들기 위해 ScriptableObject를 사용하여 Skill Data를 만들어 주었다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum SkillCategory
{
Player,
Projectile,
Active,
Passive
}
[CreateAssetMenu(fileName = "Skill Data", menuName = "Scriptable Object/Skill Data", order = int.MaxValue)]
public class SkillInfo : ScriptableObject
{
[Header("Skill Info")]
[SerializeField] private string skillname;
public string Name { get { return skillname; } }
[SerializeField] private SkillCategory category;
public SkillCategory Category { get { return category; } }
[Header("Player State")]
[SerializeField] private int health;
public int Health { get { return health; } }
[SerializeField] private float moveSpeed;
public float MoveSpeed { get { return moveSpeed; } }
[SerializeField] private float attackFreq;
public float AttackFreq { get { return attackFreq; } }
[SerializeField] private float skillFreq;
public float SkillFreq { get { return skillFreq; } }
[SerializeField] private float drainRatio;
public float DrainRaio { get { return drainRatio; } }
[SerializeField] protected float knockbackResistance;
public float KnockbackResistance { get { return knockbackResistance; } }
[SerializeField] private int projectileNumber;
public int ProjectileNumber { get { return projectileNumber; } }
[SerializeField] private float shootingRange;
public float ShootingRange { get { return shootingRange; } }
[Header("Projectile State")]
[SerializeField] private float damage;
public float Damage { get { return damage; } }
[SerializeField] private float projectileSpeed;
public float ProjectileSpeed { get { return projectileSpeed; } }
[SerializeField] private float size;
public float Size { get { return size; } }
[SerializeField] private int penetration;
public int Penetration { get { return penetration; } }
[SerializeField] private int reflection;
public int Reflection { get { return reflection; } }
[SerializeField] private float knockbackDistance;
public float KnockbackDistance { get { return knockbackDistance; } }
//<액티브>
//피버타임 (일정 시간동안 화살 발사 속도 x배 증가)
//대시
//<패시브 스킬>
//마늘 - 캐릭터 일정 범위 내 근접 시 데미지
//책 - 캐릭터 돌면서 충돌 시 데미지
//비둘기 - 추가 투사체 발사
//오망성 - 맵 전체 몬스터에 일정 데미지
}
이렇게 작성하면 아래 이미지처럼 Create 목록에 Scriptable Object가 새롭게 생성된다
![]() |
![]() |
그렇게 만들어진 Skill Data들을 관리해줄 Skill Manager를 만들어주자
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SkillManager : SingleTon<SkillManager>
{
[SerializeField] private SkillInfo[] skillInfo; // Skill Data 담을 리스트
[SerializeField] private List<SkillInfo> SkillList; // Skill Data 담을 리스트 복제
public List<SkillInfo> randomSkillList = new List<SkillInfo>(); // 랜덤으로 뽑은 스킬 담을 리스트
public void GetRandomSkill(int count)
{
randomSkillList.Clear();
if (skillInfo == null || skillInfo.Length == 0)
{
Debug.LogWarning("스킬 리스트가 비어있습니다!");
return;
}
SkillList = new List<SkillInfo>(skillInfo);
while (randomSkillList.Count < count && SkillList.Count > 0)
{
int random = Random.Range(0, SkillList.Count);
randomSkillList.Add(SkillList[random]);
SkillList.RemoveAt(random);
}
}
}
이제 스킬들을 리스트에 담았으니 스킬을 뽑는 기능을 추가해 주자
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SkillPicker : MonoBehaviour
{
private SkillManager skillManager;
private PlayerStat playerStat;
//테스트용 UI
public Text text1;
public Text text2;
public Text text3;
public Button[] buttons;
//테스트용 UI
private void Awake()
{
playerStat = FindObjectOfType<PlayerStat>();
skillManager = SkillManager.Instance;
}
private void Start()
{
// 버튼 배열의 길이가 3이라고 가정 (인덱스 0, 1, 2)
for (int i = 0; i < buttons.Length; i++)
{
int value = i; // 현재 인덱스 값을 복사
buttons[i].onClick.AddListener(() => SelectSkill(value));
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
SkillPickerList();
}
}
public void SkillPickerList()
{
Debug.Log("Input A Key");
skillManager.GetRandomSkill(3);
//테스트용 UI
text1.text = skillManager.randomSkillList[0].Name;
text2.text = skillManager.randomSkillList[1].Name;
text3.text = skillManager.randomSkillList[2].Name;
//테스트용 UI
for (int i = 0; i < skillManager.randomSkillList.Count; i++) // 디버그용
{
Debug.Log($"스킬 뽑기 : {skillManager.randomSkillList[i].Name}, {skillManager.randomSkillList[i].Category}");
}
}
public void SelectSkill(int select)
{
Debug.Log($"뽑은 스킬 : {skillManager.randomSkillList[select].Name}, {skillManager.randomSkillList[select].Category}");
//뽑은 스킬들 플레이어 스텟에 적용 시키기
SkillInfo selectedSkill = skillManager.randomSkillList[select];
switch (selectedSkill.Category)
{
case SkillCategory.Player:
playerStat.Health += selectedSkill.Health;
playerStat.MoveSpeed += selectedSkill.MoveSpeed;
playerStat.AttackFreq += selectedSkill.AttackFreq;
playerStat.ShootingRange += selectedSkill.ShootingRange;
playerStat.SkillFreq += selectedSkill.SkillFreq;
playerStat.DrainRatio += selectedSkill.DrainRaio;
playerStat.KnockbackResistance += selectedSkill.KnockbackResistance;
playerStat.ProjectileNumber += selectedSkill.ProjectileNumber;
break;
case SkillCategory.Projectile:
//waponHandler에 적용 시키기
break;
case SkillCategory.Active:
break;
case SkillCategory.Passive:
break;
}
}
}
이제 UI에 버튼을 추가해 버튼의 입력 값에 따라 리스트 인덱스 값을 부여하여 스킬을 선택해 준다
그렇게 선택된 스킬은 Skill Data에 따라 능력치를 적용해주면 궁수의 전설에서 맵을 클리어 했을때 스킬을 선택하는 기능이 완성된다.
'내일배움캠프 > Unity TeamProject' 카테고리의 다른 글
Unity 2D 팀 프로젝트 - 마지막 날 (0) | 2025.02.28 |
---|---|
Unity 2D 팀 프로젝트 - 4 (0) | 2025.02.27 |
Unity 2D 팀 프로젝트 - 2 (0) | 2025.02.25 |