이번 포스팅에서는 플레이어(Player), 적(Enemy)와 같은 캐릭터를 정해진 위치에 생성, 스폰(Spawn)하는 위치 와 이러한 게임로직을 조율하고 실행하는 역할을 담당하는 게임 매니저를 만들 것입니다.
포스팅은 유니티 2D 게임 개발(게임 개발 프로그래밍)에 나온 예제로 진행합니다.
플레이어와 적 캐릭터를 정해진 위치에서 생성하고 적이 스폰할 때 일정한 간격을 두고 스폰하는 스크립트를 만들고 게임의 로직을 조율하고 담당하는 게임 매니저 스크립트를 만들겠습니다
SpawnPoint(스폰위치) 스크립트
1. Hierarchy창 > 마우스 오른쪽 클릭 > Create Empty > 이름을 SpawnPoint로 변경하여 새로운 게임 오브젝트를 생성합니다.
2. Assets > Scripts > MonoBehaviour 폴더 > SpawnPoint 스크립트(C#)를 생성합니다.
생성한 SpawnPoint 오브젝트에 SpawnPoint 스크립트(C#) 컴포넌트를 추가합니다.
SpawnPoint 스크립트(C#)의 전체 코드입니다.
using UnityEngine;
public class SpawnPoint : MonoBehaviour
{
public GameObject prefabToSpawn;
public float repeatInterval;
public void Start()
{
if(repeatInterval > 0)
{
InvokeRepeating("SpawnObject", 0.0f, repeatInterval);
}
}
public GameObject SpawnObject()
{
if(prefabToSpawn != null)
{
return Instantiate(prefabToSpawn,transform.position, Quaternion.identity);
}
return null;
}
}
작성한 코드를 저장하겠습니다
코드를 확인해보도록 하겠습니다.
public GameObject prefabToSpawn;
public float repeatInterval;
한번 혹은 일정한 간격을 두고 계속 스폰(생성)할 프리팹입니다. public으로 되어있고 유니티에서 설정하겠습니다.
일정한 간격을 두고 프리팹을 스폰하기 위해 설정한 속성값입니다.
Start() 메서드를 확인하기 전에 SpawnObject() 메서드부터 확인하겠습니다.
public GameObject SpawnObject()
{
if(prefabToSpawn != null)
{
return Instantiate(prefabToSpawn,transform.position, Quaternion.identity);
}
return null;
}
SpawnObject() 메서드가 실제로 프리팹을 인스턴스화 해서 오브젝트를 스폰하는 역할을 합니다.
반환형식은 GameObject 형식이며 외부에서 이 메서드를 호출할 수 있게 public 으로 설정하였습니다.
if문을 확인하겠습니다.
prefabToSpawn이 null이 아닌지 확인합니다.
Instantiate() 메서드를 사용하여 값을 반환합니다.
SpawnObject() 메서드에서 사용한Instatiate()의 매개변수는 프리팹 , Vector3 , 쿼터니언 입니다.
Vector3는 위치를 나타내는것입니다.
쿼터니언(Quaternion)은 회전을 표현할때 사용하지만 Quaternion.identity는 회전이 없음을 나타냅니다.
지금까지 설정하였던 SpawnPoint 오브젝트를 프리팹으로 만들고 Hierarchy창에 있던 SpawnPoint 오브젝트를 삭제합니다.
1. Prefabs폴더에서 플레이어를 생성하고 싶은 위치로 SpawnPoint 프리팹을 드래그앤 드롭합니다.
2. 해당 SpawnPoint 오브젝트의 이름을 PlayerSpawnPoint로 변경합니다.
3. Scene뷰에서 해당 오브젝트를 잘 찾을 수 있도록 사진과 같이 아이콘을 변경합니다.
4. Scene뷰 오른쪽 상단에 Gizmos가 선택이 되어있는지 확인합니다.
1. PlayerSpawnPoint 오브젝트의 SpawnPoint 스크립트(C#)의 속성을 설정합니다.
2. Prefab To Spawn 설정에 Prefabs 폴더에 있는 PlayerObjcet를 드래그 앤 드롭합니다.
3. Hierarchy창에 있는 PlayerObject는 삭제하여도 좋습니다.
적(Enemy) 스폰위치 또한 만들어 보도록 하겠습니다.
1.위와 같은 방법으로 SpawnPoint 프리팹을 원하는 위치에 드래그앤 드롭합니다.
2. Inspector창을 사진과 같이 설정합니다.
이름 : EnemySpawnPoint
Spawn Point(Script) 컴포넌트 > Prefab To Spawn 속성 > EnemyObjecy 프리팹으로 설정
Spawn Point(Script) 컴포넌트 > Repeat Interval 속성 > 10 으로 설정합니다.
적(Enemy)는 10초마다 스폰합니다.
PlayerSpawnPoint, EnemySpawnPoint의 Transform 컴포넌트 > Position > z 속성의 값을 0으로 변경해줍니다.
게임매니저 스크립트(C#)를 만들어보도록 하겠습니다.
Singleton(싱글톤)
게임매니저 스크립트(C#)을 만들기 전에 Singleton(싱글톤) 소프트웨어 디자인 패턴을 알아보겠습니다.
Singleton은 애플리케이션이 끝날 때까지 딱 하나의 인스턴스만 만들어야 할 클래스가 있을 때 사용합니다.
싱글톤의 장점
게임 로직을 조율하는 게임 매니저 클래스처럼 여러 클래스가 사용할 기능을 하나의 클래스로 제공해야 한다면 싱글톤이 유용할 수 있습니다.
어디서든 싱글톤 클래스와 기능에 접근할 수 있는 경로를 하나로 통합해서 제공할 수 있습니다.
인스턴스화 하는 코드가 있어도 인스턴스를 만들지 않고 실제로 처음 사용할 때 인스턴스를 만드는 인스턴스화 지연이 가능합니다.
싱글톤의 단점
싱글톤의 장점이 단점이 되기도 합니다. 싱글톤이 하나의 접근 경로를 제공할 수 있다는 말은 싱글톤에 들어 있는 값이 어디서든 접근할 수 있는 불확실한 상태의 값이라는 의미입니다.
즉 게임의 모든 코드가 싱글톤의 데이터를 이용하거나 수정할 수 있습니다.
만약 값이 잘못 설정된 싱글톤의 속성은 20개 이상의 클래스가 가져다 쓰는 경우가 있을 수 있습니다.
또한 싱글톤은 인스턴스화 시점을 정확하게 통제하기 어렵다는 단점이 있습니다.
우리의 예제에서는 싱글톤으로 게임매니저를 구현할 것입니다.
게임매니저 스크립트(C#)
게임매니저 오브젝트와 게임매니저 스크립트를 담을 폴더를 만들겠습니다.
1. Hierarchy창 > 마우스 오른쪽 클릭 > Create Empty > 이름을 RPGGameManager 생성합니다.
2. Scripts > Managers 폴더 생성합니다.
1. Scripts > Managers 폴더 > RPGGameManager 스크립트(C#)을 생성합니다.
2. RPGGameManager 오브젝트의 Inspector창에서 RPGGameManager 스크립트(C#) 컴포넌트를 추가합니다.
RPGGameManager 스크립트(C#)의 전체코드입니다.
using UnityEngine;
public class RPGGameManager : MonoBehaviour
{
public static RPGGameManager sharedInstance = null;
public SpawnPoint playerSpawnPoint;
void Awake()
{
if (sharedInstance != null && sharedInstance != this)
{
Destroy(gameObject);
}
else
{
sharedInstance = this;
}
}
void Start()
{
SetupScene();
}
public void SetupScene()
{
SpawnPlayer();
}
public void SpawnPlayer()
{
if (playerSpawnPoint != null)
{
GameObject player = playerSpawnPoint.SpawnObject();
}
}
}
코드를 저장합니다.
코드를 확인해 보도록 하겠습니다.
public static RPGGameManager sharedInstance = null;
public SpawnPoint playerSpawnPoint;
static 변수인 sharedInstance는 싱글톤 오브젝트에 접근할 때 사용합니다. 싱글톤은 이 속성을 통해서만 접근합니다.
static 변수가 클래스의 특정 인스턴스가 아닌 RPGGameManager 클래스 자체에 속합니다.
클래스 자체에 속하므로 RPGGameManager.sharedInstance의 복사본은 메모리에 단 하나 존재합니다.
playerSpawnPoint 속성에 플레이어 스폰 위치의 참조를 저장합니다. 유니티에서 설정하겠습니다.
Awake()메서드를 확인하겠습니다.
void Awake()
{
if (sharedInstance != null && sharedInstance != this)
{
Destroy(gameObject);
}
else
{
sharedInstance = this;
}
}
Awake()메서드는 Start() 메서드가 실행되기 이전 및 프리팹의 인스턴스화 직후에 실행이됩니다.
if문을 보면 sharedInstance가 null이 아닌지, sharedInstance가 현재 인스턴스와 다른 인스턴스인지 확인합니다.
만약 sharedInstance가 null이 아니고 현재 인스턴스가 아니라면 제거합니다.
else문은 현재 인스턴스가 유일한 인스턴스라면 현재 오브젝트를 SharedInstance에 대입합니다.
SpawnPlayer() 메서드를 확인하겠습니다.
public void SpawnPlayer()
{
if (playerSpawnPoint != null)
{
GameObject player = playerSpawnPoint.SpawnObject();
}
}
if()문을 확인하면 playerSpawnPoint 가 null이아닌지 확인합니다.
playerSpawnPoint의 SpawnObject() 메서드를 호출하고 player 인스턴스에 참조를 저장합니다.
RPGGameManager을 Prefabs 폴더로 드래그 앤 드롭하여 프리팹으로 만듭니다.
Hierarchy창에 있는 RPGGameManager 오브젝트의 Inspector창에서 Player Spawn Point 속성을 Hierarchy 창에 있는 PlayerSpawnPoint(SpawnPoint)오브젝트로 설정합니다.
재생버튼을 눌러 게임을 진행합니다.
플레이어(Player) ,적(Enemy) 캐릭터가 등장하는것을 볼 수 있습니다. 플레이어를 움직여보면 카메라가 추적하지 않는 것을 볼 수 있습니다.
다음포스팅에서는 카메라 매니저를 사용하여 카메라가 플레이어를 추적하도록 만들겠습니다.
마지막으로 Ctrl + S를 눌러 Scene을 저장합니다!
감사합니다! :)
'유니티2D' 카테고리의 다른 글
#18 유니티 코루틴(Coroutine), Character 보강 (7) | 2020.12.21 |
---|---|
#17 유니티 카메라 매니저(플레이어 추적) (7) | 2020.12.19 |
#15-2 유니티 인벤토리 만들기_스크립트(C#) (0) | 2020.12.17 |
#15-1 유니티 인벤토리 만들기(캔버스, UI, 텍스트) (0) | 2020.12.16 |
#14-2 유니티 체력바 만들기_스크립트(C#) (2) | 2020.12.15 |