이번 포스팅은 #14-1 유니티 체력바 만들기(캔버스, UI, 텍스트)포스팅에 이어 진행하겠습니다.
저번 포스팅에는 체력바(UI)를 만들었습니다. 이번에는 체력아이템을 먹으면 체력을 회복하는 즉 저번 포스팅에서 만든 체력바(UI)가 채워지는 기능을 만들겠습니다.
체력아이템에 관한 포스팅 링크는 하단에 배치하였습니다.
#13-1 유니티 아이템(써클 콜라이더) ~ #13-3 유니티 아이템(OnTriggerEnter2D)를 참고하시면 되겠습니다.
#13-1 유니티 아이템(써클 콜라이더)링크는 하단에 배치하겠습니다.
#14-2 유니티 체력바 만들기(캔버스, UI, 텍스트)링크는 하단에 배치하였습니다.
포스팅은 유니티 2D 게임 개발(게임 개발 프로그래밍)에 나온 예제로 진행합니다.
체력 바 스크립트(C#)
스크립팅 가능한 오브젝트를 만들어서 체력 바와 Player 클래스가 체력 데이터를 공유하게 만들겠습니다.
Player클래스는 Character 클래스의 HP 속성을 상속 받고 있습니다.
HitPoints 스크립터블 오브젝트를 새로 만들고 Character 클래스와 Player 클래스를 수정하겠습니다.
Assets > Scripts > Scriptable Objects 폴더에 HitPoints 스크립트(C#)을 생성하였습니다.
HitPoints 스크립트(C#)의 전체 코드 입니다.
using UnityEngine;
[CreateAssetMenu(menuName = "HitPoints")]
public class HitPoints : ScriptableObject
{
public float value;
}
CreateAssetMenu를 사용하여 생성 메뉴 안에 하위 메뉴를 추가해서 스크립터블 오브젝트를 만들었습니다.
HitPoints 클래스는 ScriptableObject를 상속받고 있습니다.
float을 사용하여 체력 값을 저장합니다. 체력 바에 속한 HPMeter 이미지 오브젝트의 fill Amount 속성에 float 을 사용하여 값을 대입하여야 합니다.
HitPoints 스크립트(C#)을 저장합니다.
스크립터블 오브젝트에 관한 포스팅은 아래에 첨부하겠습니다.
HitPoints 스크립터블 오브젝트를 만들도록 하겠습니다.
Projects창 > Assets > Scripts > Scriptable Objects 폴더 > 마우스 오른쪽 클릭 > Create > HitPoints를 선택합니다.
새롭게 생성된 Object의 이름을 HitPoints로 변경하였습니다.
Character 스크립트(C#)를 수정하겠습니다.
Character 클래스의 전체 코드입니다.
using UnityEngine;
public abstract class Character : MonoBehaviour
{
public HitPoints HP;
public float maxHP;
public float StartingHP;
}
HP 속성의 형식을 HitPoints(스크립터블 오브젝트)로 변경하였습니다.
maxHP는 float로 변경하였고 StartingHP 속성을 추가하였습니다. StartingHP는 캐릭터의 최초 체력을 설정하겠습니다.
Player 스크립트(C#)를 수정하겠습니다.
Player 클래스의 전체 코드입니다.
using UnityEngine;
public class Player : Character
{
public HealthBar healthBarPrefab;
HealthBar healthBar;
float speed = 10;
public void Start()
{
HP.value = StartingHP;
healthBar = Instantiate(healthBarPrefab);
healthBar.Character = this;
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("CanBePickedUp"))
{
Item hitObject = collision.gameObject.GetComponent<Consumable>().item;
if(hitObject != null)
{
bool shouldDisappear = false;
print("Hit: " + hitObject.objectName);
switch (hitObject.itemType)
{
case Item.ItemType.COIN:
shouldDisappear = true;
break;
case Item.ItemType.HEALTH:
shouldDisappear = AdjustHP(hitObject.quantity);
break;
default:
break;
}
if (shouldDisappear)
{
collision.gameObject.SetActive(false);
}
}
}
}
public bool AdjustHP(int amount)
{
if(HP.value < maxHP)
{
HP.value += amount;
print("Adjusted HP by: " + amount + ". New Value: " + HP.value);
return true;
}
return false;
}
}
수정된 코드만 살펴보도록 하겠습니다.
public HealthBar healthBarPrefab;
HealthBar healthBar;
HealtbBar 프리팹의 참조를 저장합니다. HealthBar 스크립트는 밑에서 만들도록 하겠습니다.
healthBar 는 HealthBar 형식으로 인스턴스화한 HealthBar의 참조를 저장합니다.
public void Start()
{
HP.value = StartingHP;
healthBar = Instantiate(healthBarPrefab);
healthBar.Character = this;
}
Start() 메서드가 추가가되었습니다. 이 메서드는 스크립트가 활성화할때 딱 한번 불립니다.
HP.value에 StartingHP가 대입합니다. 플레이어의 초기 체력입니다.
HealthBar 프리팹의 복사본을 인스턴스화하고 메모리에 만들어진 인스턴스의 참조를 저장합니다.
healthBar.Character = this 는 밑에서 만들 HealthBar 스크립트의 Character 라는 Player 오브젝트의 maxHP를 가져올때 기능합니다.
OnTriggerEnter2D() 메서드를 확인하기 전에 AdjustHP() 메서드부터 확인하겠습니다.
public bool AdjustHP(int amount)
{
if(HP.value < maxHP)
{
HP.value += amount;
print("Adjusted HP by: " + amount + ". New Value: " + HP.value);
return true;
}
return false;
}
int형식의 AdjustHP()메서드를 bool형식으로 변경하였습니다.
if문을 추가하여 현재 체력값이 최대 체력보다 작은지 확인합니다.
플레이어의 현재 HP에 amount 값을 반영합니다.
체력이 바뀌었으면 true를 반환하고 아니면 false를 반환합니다.
OnTriggerEnter2D() 메서드입니다.
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("CanBePickedUp"))
{
Item hitObject = collision.gameObject.GetComponent<Consumable>().item;
if(hitObject != null)
{
//수정한 부분 <------
bool shouldDisappear = false;
// ------>
print("Hit: " + hitObject.objectName);
switch (hitObject.itemType)
{
case Item.ItemType.COIN:
//수정한 부분 <-----
shouldDisappear = true;
//------->
break;
case Item.ItemType.HEALTH:
//수정한 부분 <-----
shouldDisappear = AdjustHP(hitObject.quantity);
//----->
break;
default:
break;
}
// 수정한 부분 <--------
if (shouldDisappear)
{
collision.gameObject.SetActive(false);
}
// ------->
}
}
}
수정한 부분을 확인하기 편하도록 표시를 해두었습니다.
첫번째 수정한 부분은 bool타입으로 충돌한 오브젝트를 감춰야 할지 나타내는 값입니다.
두번째는 동전과 충돌하였을때 오브젝트를 감추고 인벤토리에 추가해야 합니다. 인벤토리는 다음에 만들겠습니다.
세번째는 Player 클래스가 Character 클래스에서 상속받는 MaxHP 속성 값을 넘지못하는 로직을 추가하였습니다. AdjustHP() 메서드는 체력의 변화가 있으면 true를 반환하고 아니면 false를 반환합니다.
플레이어의 체력이 최대체력이라면 AdjustHP() 메서드는 false를 반환하고 하트는 Scene에 남아있습니다.
위에서 언급하였던 HealthBar 스크립트를 만들겠습니다.
HealthBar 스크립트(C#)는 MonoBehaviour 클래스를 상속 받습니다.
Assets > Scripts > MonoBehaviour 폴더에 HealthBar 스크립트(C#)을 생성하였습니다.
HealthBar 클래스의 전체 코드입니다.
using UnityEngine;
using UnityEngine.UI;
public class HealthBar : MonoBehaviour
{
public HitPoints HP;
[HideInInspector]
public Player Character;
public Image HPMeterImage;
public Text HPText;
float maxHP;
void Start()
{
maxHP = Character.maxHP;
}
void Update()
{
if(Character != null)
{
HPMeterImage.fillAmount = HP.value / maxHP;
HPText.text = "HP:" + (HPMeterImage.fillAmount * 100);
}
}
}
코드를 확인하고 저장합니다.
using UnityEngine.UI;
스크립트에서 UI요소를 사용하려면 UnityEngine.UI 네임스페이스를 임포트해야 합니다.
HealthBar 스크립트에서 UI요소는 Image , Text 입니다.
public HitPoints HP;
[HideInInspector]
public Player Character;
public Image HPmeterImage;
public Text HPText;
float maxHP;
HitPoints는 스크립터블 오브젝트인 HitPoints에셋을 가리키는 참조입니다.
[HideInInspector]는 인스펙터창에서 public 속성을 감추려고 사용하였습니다.
maxHP를 얻으려면 Player 오브젝트의 참조가 필요하지만 유니티의 인스펙터에서 설정하는 것이 아니라 코드를 통하여 설정하려고 인스펙터에서 감추었습니다.
Image, Text는 유니티의 UI요소입니다. 인스펙터창에서 드래그 앤 드롭으로 설정하기 위하여 public 으로 적었습니다.
float형식으로 최대체력을 정의하였습니다.
void Start()
{
maxHP = Character.maxHP;
}
Start() 메서드입니다. Character에서 최대체력을 가져와서 maxHP 에 저장합니다.
Character.maxHP는 Player 스크립트에서 healthBar.Character = this를 통하여 maxHP를 가져옵니다.
void Update()
{
if(Character != null)
{
HPMeterImage.fillAmount = HP.value / maxHP;
HPText.text = "HP:" + (HPMeterImage.fillAmount * 100);
}
}
Update()메서드입니다. 먼저 if문으로 Character가 null이 아닌지 확인합니다.
이미지 오브젝트의 Fill Amount 속성값은 0~1사이여야 합니다. 현재 체력 값을 최대체력값으로 나누어 현재 체력의 퍼센트 값을 구하고 이미지 오브젝트의 fillAmount에 대입합니다.
HPText의 텍스트 속성을 수정하여 남아있는 체력을 정수로 보여줍니다. fillAmount에 100을 곱하여 정수로 만듭니다.
HealBarObject에 추가하도록 하겠습니다.
1. Add Component > Health Bar(Script) 컴포넌트를 추가합니다.
2. HP 속성에 HitPoints(스크립터블 오브젝트)를 추가합니다.
3. HP Meter Image에 HPmeter 이미지 오브젝트를 드래그 앤드롭 합니다.
4. HP Text 속성에 HPText 텍스트 오브젝트를 드래그 앤 드롭합니다.
5. 오른쪽 상단에 Overrides > Apply All을 선택하여 프리팹의 모든 인스턴스에 적용합니다.
PlayerObject를 설정하겠습니다.
PlayerObject의 Player(Script)컴포넌트를 사진과 같이 설정합니다.
HP 속성에 HitPoints(스크립터블 오브젝트)를 드래그 앤 드롭합니다.
Starting HP를 5로 설정합니다.
Heath Bar Prefab을 HealthBarObject(HealthBar)로 설정합니다.
다 설정하였으면 Overrides > Apply All 선택합니다.
재생버튼을 눌러 게임을 진행해봅니다.
체력아이템에 플레이어가 충돌하면 체력이 증가하는지 확인합니다.
확인을 다 했다면 Hierarchy창에 존재하는 HealthBarObject를 삭제하여도 괜찮습니다.
Scene뷰에서 사라졌지만 게임이 시작되면 체력 바가 등장할 것입니다.
마지막으로 Ctrl + S를 눌러 Scene을 저장합니다!
감사합니다! :)
'유니티2D' 카테고리의 다른 글
#15-2 유니티 인벤토리 만들기_스크립트(C#) (0) | 2020.12.17 |
---|---|
#15-1 유니티 인벤토리 만들기(캔버스, UI, 텍스트) (0) | 2020.12.16 |
#14-1 유니티 체력바 만들기(캔버스, UI, 텍스트) (0) | 2020.12.14 |
#13-3 유니티 아이템 (OnTriggerEnter2D) (0) | 2020.12.12 |
#13-2 유니티 아이템 Scriptable Object(스크립터블 오브젝트) (0) | 2020.12.11 |