본문 바로가기
게임 프로그래밍/유니티 활용

[유니티 활용] ScriptableObject 로 HP Bar 만들기 - #1

by 레오란다 2022. 12. 29.
반응형

유니티는 ScriptableObject 라는 독특한 형태의 데이터 컨테이너를 제공합니다. 이 글에서는 유니티 공식 페이지에서 ScriptableObject 의 활용법으로 올라온 모듈형 디자인의 한 예제로 소개된 방식을 직접 구현해 보도록 하겠습니다.

 

들어가기에 앞서서 이 글에서는 ScriptableObject 의 다음 특징을 이용합니다.

  • 변수 값은 자동으로 Serialization 기능을 통해 디스크에 저장됩니다. 이 값은 런타임 시에 변경돼도 저장됩니다.
  • 변수 값은 모든 객체에서 동일하게 유지됩니다.

 

공식 페이지의 문서는 다음의 링크를 참조하시면 됩니다.

 

|

스크립터블 오브젝트로 코드를 설계하면 코드를 유연하고 간편하며 디버깅에 용이한 상태로 유지할 수 있습니다.

unity.com

 

 

▶ 준비사항

예제로 사용한 에셋은 여기를 클릭하시면 무료로 받을 수 있습니다. 다운로드 후 프로젝트에 import 해 주세요.

 

 

▶ 캐릭터에 HP Bar UI 만들기

  • Project 창에서 경로 [Assets > SunnyLand Artwork > Sprites > player > idle] 로 이동합니다.
  • 이미지 "player-idle-1" 를 클릭하고 Inspector 창에서 Pixels Per Unit 을 33 으로 설정하고 [Apply] 를 클릭합니다.
  • 이미지 "player-idle-1" 을 Hierarchy 창으로 드래그 하고 이름을 Player 로 변경합니다.

캐릭터 이미지 드래그
Player 객체 생성

  • Player 객체를 선택하고 마우스 우클릭 [UI > Canvas] 를 선택해 자식 객체를 만들어 줍니다.
  • Canvas 객체를 다음과 같이 설정합니다.

Canvas 설정

  • 먼저 Render Mode 를 World Space 로 변경합니다.
  • Rect Transform 의 Pos X / Pos Y / Width / Height 를 모두 0 으로 변경합니다.
  • Event Camera 에 Main Camera 를 연결합니다.
  • Canvas 객체를 선택하고 마우스 우클릭 [UI > Image] 를 선택해서 자식으로 Image 객체를 생성하고 이름을 HealthBar 로 변경합니다.
  • HealthBar 의 RectTransform 값을 다음과 같이 설정합니다.

HealthBar의 RectTransform 설정 값
HealthBar 의 RectTransform

  • HealthBar의 Image 컴포넌트의 Color 를 검은 색으로 설정합니다.
  • HealthBar의 자식 객체로 다시 UI > Image 를 생성하고 이름을 Fill 로 변경합니다.
  • Fill 의 RectTransform 을 다음과 같이 설정합니다.

Fill의 RectTransform 설정 값
Fill 의 RectTransform

  • Image 컴포넌트의 Image Type: Filled 를 사용하기 위해선 Source Image 필드에 이미지를 연결해 주어야 합니다.
  • Project 창에서 Assets 밑에 Sprites 폴더를 만들고 그 안에 마우스 우클릭 [Create > 2D > Sprites > Square] 를 선택합니다.
  • 생성된 Square 이미지를 Fill 객체의 Image 컴포넌트에 연결하고 다음과 같이 설정합니다.

Fill 객체의 Image 컴포넌트 설정

  • Color = Red / Image Type = Filled / Fill Method = Horizontal 로 변경합니다.

 

▶ ScriptableObject 만들기

  • Proejct 창에서 Assets 밑에 Scripts 폴더를 생성합니다.

  ▷ FloatVariable

  • Scripts 폴더에서 마우스 우클릭 [Create > C# Script] 로 새로운 스크립트를 생성하고 이름을 FloatVariable 로 변경하고 코드를 다음과 같이 수정합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu]
public class FloatVariable : ScriptableObject, ISerializationCallbackReceiver
{
   // 초기 설정 값
   public float initValue;

   // 실제 게임 실행 시 사용할 값
   // NonSerialized 이기 때문에 runtimeValue 는
   // 디스크에 저장되지 않습니다.
   [System.NonSerialized]
   public float runtimeValue;

   // 디스크에 저장된 값을 역직렬화로 initValue 로 가져온 후   
   public void OnAfterDeserialize()
   {
      runtimeValue = initValue;
   }

   public void OnBeforeSerialize() { }
}
  • Project 창에서 경로 [Assets > Scripts] 에서 마우스 우클릭 [Create > Float Variable] 을 선택해서 새로운 FloatVariable을 생성하고 이름을 FloatHP 로 변경합니다.
  • FloatHP 를 선택하고 Inspector 창에서 InitValue 값을 100 으로 설정합니다.

  ▷ GameEvent

  • Scripts 폴더에서 마우스 우클릭 [Create > C# Script] 로 새로운 스크립트를 생성하고 이름을 GameEvent 로 변경한 후 코드를 다음과 같이 수정합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu]
public class GameEvent : ScriptableObject
{
	// 발생 시킨 이벤트를 수신할 listener 목록
	private List<GameEventListener> listeners = new List<GameEventListener>();

	// 이벤트 발생
	public void Raise()
	{
		for (int i = listeners.Count - 1; i >= 0; i--)
			listeners[i].OnEventRaised();
	}

	// listener 등록
	public void RegisterListener(GameEventListener listener)
	{ 
		listeners.Add(listener); 
	}

	// 등록된 listener 해제
	public void UnregisterListener(GameEventListener listener)
	{ 
		listeners.Remove(listener); 
	}
}

* 이 코드까지 작성하면 GameEventListener 가 없기 때문에 컴파일 에러가 발생합니다.

 

 

▶ GameEventListener

  • Scripts 폴더에서 마우스 우클릭 [Create > C# Script] 로 새로운 스크립트를 생성하고 이름을 GameEventListener 로 변경한 후 코드를 다음과 같이 수정합니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class GameEventListener : MonoBehaviour
{
   public GameEvent Event;
   public UnityEvent Response;

   // 스크립트가 활성화 되면 GameEvent 에 등록합니다.
   private void OnEnable()
   { 
      Event.RegisterListener(this); 
   }

   // 스크립트가 비활성화 되면 GameEvent 에서 해제합니다.
   private void OnDisable()
   { 
      Event.UnregisterListener(this); 
   }

   // 유니티 에디터에서 UnityEvent에 등록한 함수를 호출합니다.
   public void OnEventRaised()
   { 
      Response.Invoke(); 
   }
}
  • Project 창에서 경로 [Assets > Scripts] 에서 마우스 우클릭 [Create > GameEvent] 을 선택해서 새로운 GameEvent를 생성하고 이름을 HPEvent 로 변경합니다.

여기 까지가 SciptableObject 와 유니티 이벤트를 이용한 모듈화를 위한 기본 코드들입니다.

 

위 코드들의 흐름은 다음과 같습니다.

  1. 캐릭터의 HP (FloatHP 의 runtimeValue) 가 변하면 GameEvent 의 Raise() 함수 호출
  2. GameEvent 의 Raise() 함수에서 등록된 GameEventListener 의 OnEventRaised() 함수 호출
  3. GameEventListener 의 OnEventRaised() 함수에서 UnityEvent에 등록한 스크립트의 함수 호출 (Response.Invoke())
  4. 스크립트의 함수에서 FloatHP의 runtimeValue 값에 따라 HP Bar UI 갱신

자세한 구현은 2부에서 진행하도록 하겠습니다.

 

 

 

[유니티 활용] ScriptableObject 로 HP Bar 만들기 - #2

이 글은 "ScriptablObject 로 HP Bar 만들기 - #1" 에 이어서 작성하는 글입니다. ▶ PlayerObj 스크립트 작성 Hierarchy 창에서 Player 객체를 선택하고 PlayerObj 이름으로 새 스크립트를 생성합니다. PlayerObj 의

ugames.tistory.com

 

반응형

댓글