일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 다이나믹 프로그래밍
- 기초
- 2022년
- 유니티 심화과정
- 4월
- 2025년
- 3월
- 코딩 기초 트레이닝
- 유니티
- 개인 프로젝트
- 5월
- 개인 프로젝트 - 런앤건
- 1월
- 백준
- todolist
- 골드메탈
- 7월
- 2023년
- 단계별로 풀어보기
- 수학
- 자료 구조
- 프로그래머스
- 2024년
- 입문
- 게임 엔진 공부
- 2월
- c++
- 10월
- C/C++
- 코딩 테스트
- Today
- Total
기록 보관소
[Unity/유니티] 기초-뱀서라이크: 오브젝트 풀링으로 소환하기[06] 본문
개요
유니티 독학을 위해 아래 링크의 골드메탈님의 영상들을 보고 직접 따라 해보면서 진행 상황을 쓰고 배웠던 점을 요약한다.
https://youtube.com/playlist?list=PLO-mt5Iu5TeYI4dbYwWP8JqZMC9iuUIW2
📚유니티 기초 강좌
유니티 게임 개발을 배우고 싶은 분들을 위한 기초 강좌
www.youtube.com
뱀서라이크: 오브젝트 풀링으로 소환하기[06]
1. 프리펩 만들기
- 위 캡쳐를 자세히 보면 Scale 항목 옆에 체인 모양 아이콘이 있다. 이를 클릭해 활성화 하면, 화면에 있는 해당 프리펩 오브젝트들이 변경한 내역에 맞춰서 크기가 바뀌게 된다(변경 전에 생성된 것도 같이 적용된다).
2. 오브젝트 풀 만들기
// PoolManager Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolManager : MonoBehaviour {
// 프리펩들을 보관할 변수
public GameObject[] prefabs;
// 풀 담당을 하는 리스트들
List<GameObject>[] pools;
void Awake() {
pools = new List<GameObject>[prefabs.Length];
for (int index = 0; index < pools.Length; index++) {
pools[index] = new List<GameObject>();
}
}
}
3. 풀링 함수 작성
// PoolManager Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PoolManager : MonoBehaviour {
public GameObject[] prefabs; // 프리펩들을 보관할 변수
List<GameObject>[] pools; // 풀 담당을 하는 리스트들
void Awake() {
pools = new List<GameObject>[prefabs.Length];
for (int index = 0; index < pools.Length; index++) {
pools[index] = new List<GameObject>();
}
}
public GameObject Get(int index) {
GameObject select = null;
// 선택한 풀에서 비활성화된 게임 오브젝트에 접근
foreach (GameObject item in pools[index]) {
if (!item.activeSelf) {
// 발견시 select 변수에 할당
select = item;
select.SetActive(true);
break;
}
}
// 만약 활성화된 게임 오브젝트가 없다면
if (select == null) {
//새롭게 생성 후 select 변수에 할당
select = Instantiate(prefabs[index], transform);
pools[index].Add(select);
}
return select;
}
}
- 이번 챕터에서 구현한 오브젝트(몬스터)를 불러오는, 즉 풀링하는 함수는 간단하게 상황에 따라서 비활성화된 오브젝트를 확인해보고 없으면 새로 생성하는 방식이다.
4. 풀링 사용해보기
//GameManager Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour {
public Player player;
public PoolManager pool;
public static GameManager instance;
void Awake() {
instance = this;
}
}
- 생성한 Spawner에서 PoolManager에 쉽게 접근할 수 있도록 GameManager 스크립트 파일에 PoolManager 변수를 추가.
- 이제 Spawner에서 아래처럼 스페이스바 입력 같은 것을 통해 프리펩을 생성하도록 작성할 수 있다.
// Spawner Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour {
void Update() {
if (Input.GetButtonDown("Jump")) {
GameManager.instance.pool.Get(1);
}
}
}
- 그러나 이렇게하고 테스트해볼 경우, 생성된 몬스터(프리펩)는 플레이어를 따라오지 않는다. 프리펩은 Scene에 있는 오브젝트를 접근할 수 없기 때문이다.
- 참고로 위 Spawner 코드 자체도 나는 실행이 잘 안됐었다. 그러니까 스페이스바를 눌러도 생성이 안됐었다. 이 문제는 아래 보너스 챕터를 확인하면 해당 문제를 해결할 수 있으니, 그것을 참고하면 될 것이다.
- 따라서 Enemy 스크립트에 생성되었을 때 Player를 Target으로 할 수 있게 변경해야한다.
// Enemy Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour {
public float speed;
public Rigidbody2D target;
bool isLive = true; //테스트용 변수 초기화
Rigidbody2D rigid;
SpriteRenderer spriter;
void Awake() {
rigid = GetComponent<Rigidbody2D>();
spriter = GetComponent<SpriteRenderer>();
}
void FixedUpdate() {
if (!isLive)
return;
Vector2 dirVec = target.position - rigid.position; // 방향 = 위치 차이의 정규화(Normalized). 위치 차이 = 타겟 위치 - 나의 위치.
Vector2 nextVec = dirVec.normalized * speed * Time.fixedDeltaTime;
rigid.MovePosition(rigid.position + nextVec); //플레이어의 키 입력값을 더한 이동 = 몬스터의 방향 값을 더한 이동
rigid.velocity = Vector2.zero; //물리 속도가 이동에 영향을 주지 않도록 속도 제거
}
void LateUpdate() {
if (!isLive)
return;
spriter.flipX = target.position.x < rigid.position.x;
}
void OnEnable() {
target = GameManager.instance.player.GetComponent<Rigidbody2D>(); //플레이어 할당
}
}
4+. Spawner 스크립트 Input 에러 해결 방법
- 앞선 Spawner 스크립트처럼 작성해서 테스트를 위해 실행해봤는데, 'InvalidOperationException: You are trying to read Input using the UnityEngine.Input class, but you have switched active Input handling to Input System package in Player Settings.'라는 에러가 발생했다.
- 댓글을 보니까 새로운 입력 시스템을 사용해서 발생한 에러인듯하다. 프로젝트 세팅을 예전 버전과 동시에 사용하는 것으로 바꿔주면 된다고 한다.
- 이렇게 설정하면 프로젝트가 잠시 꺼졌다가 다시 실행되면서 적용된다.
- 이후에 Assets -> Reimport All 까지 해주면 끝.
5. 주변에 생성하기
- 앞선 PoolManager 스크립트에서 구현한 프리펩 생성 위치는 그냥 PoolManager 오브젝트의 위치, 즉 0, 0, 0에서 생성되도록 만들었다.
- 강의에서 구현하려는 게임 장르에서는 화면 밖에서 몬스터가 생성되어 플레이어를 쫓아야 한다. 따라서 이번 챕터에서는 화면 밖에 생성 포인트를 만들어서 그곳에서 생성되도록 만든다.
// Spawner Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour {
public Transform[] spawnPoint;
float timer;
void Awake() {
spawnPoint = GetComponentsInChildren<Transform>();
}
void Update() {
timer += Time.deltaTime;
if (timer > 0.2f) {
timer = 0;
Spawn();
}
}
void Spawn() {
GameObject enemy = GameManager.instance.pool.Get(Random.Range(0, 2));
enemy.transform.position = spawnPoint[Random.Range(1, spawnPoint.Length)].position; // Random Range가 1부터 시작하는 이유는 spawnPoint 초기화 함수 GetComponentsInChildren에 자기 자신(Spawner)도 포함되기 때문에.
}
}
- 위 코드를 작성하면 Spawner에 Spawn Point 리스트 변수가 있긴한데, 따로 할당해줄 필요는 없다. GetComponentsInChildren<Transform>()으로 할당해주니까...
- 이제 완성되었으니 테스트를 해보자
'유니티 프로젝트 > 뱀서라이크' 카테고리의 다른 글
[Unity/유니티] 기초-뱀서라이크: 회전하는 근접무기 구현[07] (0) | 2023.06.01 |
---|---|
[Unity/유니티] 기초-뱀서라이크: 소환 레벨 적용하기[06+] (0) | 2023.05.29 |
[Unity/유니티] 기초-뱀서라이크: 몬스터 만들기[05] (0) | 2023.05.22 |
[Unity/유니티] 기초-뱀서라이크: 무한 맵 이동[04] (0) | 2023.04.08 |
[Unity/유니티] 기초-뱀서라이크: 2D 셀 애니메이션 제작하기[03] (0) | 2023.04.06 |