안녕하세요. 이번 글에서는 간단한 버프 시스템을 만들어 보는 방법에 대해서 알아보도록 하겠습니다. 이번 글은 이전에 작성한 아래의 글을 베이스로 작성하도록 하겠습니다. 이 글에서 작성하는 에셋 정보나 UI 설정 등은 아래 글을 참고해 주세요.
▶ 기본 개념
ScriptableObject 와 Reflection 을 이용하는 버프 시스템의 기본 개념은 다음과 같습니다.
- ScriptableObject 로 버프 정보 생성 (스탯 증가량, 지속 시간 등)
- Reflection 의 문자열로 객체의 변수를 제어하는 방법을 활용
▶ ScriptableObject 로 버프 정의하기
- Project 창에서 [Assets > Scripts] 에서 마우스 우클릭 하고 [Create > C# Script] 로 새 스크립트를 생성하고 이름을 SOBuff 로 변경합니다.
- SOBuff 의 코드를 다음과 같이 작성합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu]
public class SOBuff : ScriptableObject
{
// 버프 지속시간
public float durTime;
// 증가 값
public int value;
// 스탯 이름
public string statName;
}
- 다시 마우스 우클릭 [Create > SO Buff] 로 ScriptableObject 에셋을 만들고 이름을 StrBuff 로 변경 후 아래와 같이 설정합니다.
* StatName 은 Player 스크립트에 정의된 스탯 변수의 이름과 동일해야 합니다.
- StrBuff 를 선택하고 CTRL + D 로 복사한 다음 이름을 SpdBuff 로 변경하고 아래와 같이 설정합니다.
* StatName 은 Player 스크립트에 정의된 스탯 변수의 이름과 동일해야 합니다.
▶ Buff 객체 만들기
버프는 보통 지속 시간이 있기 때문에 이를 위해 코루틴을 사용할 것입니다. Buff 객체는 ScriptableObject 로 만들어진 버프 에셋 중 어떤 걸 사용하는지에 따라 버프의 종류가 결정됩니다.
- Project 창에서 Assets 밑에 Resources 폴더를 생성합니다.
- Resources 폴더 밑에 Buffs 폴더를 생성합니다.
- Buffs 폴더에서 마우스 우클릭 [Create > Prefab] 을 선택하고 이름을 StrBuff 로 변경합니다.
- StrBuff 에 Buff 라는 이름의 새 스크립트를 추가하고 다음과 같이 코드를 작성합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Reflection;
public class Buff : MonoBehaviour
{
// ScriptableObject 로 만든 버프
public SOBuff buff;
// 버프 적용
// obj 는 버프가 적용될 객체
// cbDone 은 버프가 끝났음을 obj 에게 알리는 용도
public void Activated(object obj, System.Action cbDone)
{
StartCoroutine(SC_Timer(obj, cbDone));
}
protected IEnumerator SC_Timer(object obj, System.Action cbDone)
{
// Reflection 으로 obj에 선언된 필드(변수) 를 가져온다
var fi = obj.GetType().GetTypeInfo().GetDeclaredField(buff.statName);
// 현재 값
int v = (int)fi.GetValue(obj);
// 버프가 적용된 값
int buffed = v + buff.value;
// obj에 버프된 스탯 적용
fi.SetValue(obj, buffed);
// 버프 시간 동안 대기
float elapsed = 0;
while (elapsed <= buff.durTime)
{
elapsed += Time.deltaTime;
yield return null;
}
// obj 에 값을 원래대로 되돌림
fi.SetValue(obj, v);
// obj 에 버프가 끝났음을 알림
cbDone.Invoke();
}
}
- StrBuff 를 선택하고 Inspector 창에서 다음과 같이 ScriptableObject 인 StrBuff 를 연결합니다.
- [Assets > Resources > Buffs] 에 있는 StrBuff 를 선택하고 CTRL + D 를 눌러 복사한다음 이름을 SpdBuff 로 변경합니다. 그리고 위와 동일한 방법으로 ScriptableObject 인 SpdBuff 를 연결해 줍니다.
▶ Player 스크립트
Player 스크립트는 위에 링크한 이전 글에서 작성한 스크립트에 추가적으로 작성하도록 하겠습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
Animator anim;
List<Buff> buffs = new List<Buff>();
// str 스탯
public int str;
// spd 스탯
public int spd;
private void Start()
{
anim = GetComponent<Animator>();
}
public void ActivateSkill(SOSkill skill)
{
anim.Play(skill.animationName);
print(string.Format("적에게 스킬 {0} 로 {1} 의 피해를 주었습니다.", skill.name, skill.damage));
}
// 버프 추가
public void AddBuff(Buff buff)
{
// 버프 목록에 이미 있으면 무시
if (buffs.Contains(buff) == false)
{
// 없으면 버프 목록에 추가
buffs.Add(buff);
// 버프 적용
buff.Activated(this, () =>
{
// 버프 시간이 끝나면 이 부분의 코드가 진행됨
buffs.Remove(buff);
Destroy(buff.gameObject);
print(buff.buff.name + ": 버프 제거됨");
PrintStats();
});
print(buff.buff.name + ": 버프 적용");
PrintStats();
}
}
// Console 창에 스탯 출력
void PrintStats()
{
print("str: " + str.ToString());
print("spd: " + spd.ToString());
}
}
▶ Test UI 만들기
이제 버프를 적용시키기 위한 테스트용 UI 를 작성하도록 하겠습니다. 테스트 UI 는 버튼을 만들고 클릭하면 Player 스크립트에 프리팹으로 생성한 버프 객체를 넣어주는 역할입니다.
- 버튼 UI 를 한 개 생성하고 좌측 하단에 배치해 줍니다. 이름은 StrBuffButton 으로 합니다.
- 버튼 객체에 TestBuff 라는 이름의 새 스크립트를 추가하고 다음과 같이 작성합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestBuff : MonoBehaviour
{
// 버프 프리팹
public Transform prefabBuff;
// Player 스크립트
public Player player;
// 버튼 클릭시 호출
public void OnClicked()
{
// 프리팹으로 객체 생성
var buff = Instantiate(prefabBuff);
// 생성된 버프 객체를 player에 추가
player.AddBuff(buff.GetComponent<Buff>());
}
}
- 아래와 같이 Inspector 창에서 TestBuff 와 버튼을 설정합니다.
- StrBuffButton 을 선택하고 CTRL+D 로 복사한 후 SpdBuffButton 으로 이름을 변경한 다음 위와 같은 방법으로 PrefabBuff 필드에 SpdBuff 프리팹을 연결해 줍니다.
위와 같이 구현하고 Play 한 다음 StrBuffButton 을 클릭하면 Console 창에 다음과 같이 str이 버프 된 Stat 이 출력되고 5 초후 다시 원상태로 돌아옵니다. SpdBuffButton 을 클릭하면 spd 가 버프됩니다.
이 코드를 기반으로 조금만 응용하면 중첩이 가능한 버프도 구현할 수 있습니다. 또 버프가 적용될 때 (코드 상에서는 Console 창에 "버프 적용" 이라고 출력하는 부분) 캐릭터 Animation 을 추가하거나 파티클을 추가하여 버프가 적용되는 효과를 줄 수도 있습니다.
'게임 프로그래밍 > 유니티 활용' 카테고리의 다른 글
[유니티 활용] 간단한 포물선 궤적 그리기 (3) | 2023.01.05 |
---|---|
[유니티 활용] ScriptableObject 를 이용한 아이템 관리 (0) | 2023.01.04 |
[유니티 활용] ScriptableObject 를 이용한 스킬 시스템 만들기 (7) | 2023.01.01 |
[유니티 활용] ScriptableObject 로 HP Bar 만들기 - #2 (3) | 2022.12.30 |
[유니티 활용] ScriptableObject 로 HP Bar 만들기 - #1 (1) | 2022.12.29 |
댓글