일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- gameplay ability system
- gameplay effect
- 보안
- gas
- local prediction
- nanite
- animation
- 언리얼엔진
- 게임개발
- Unreal Engine
- stride
- 게임 개발
- photon fusion2
- 언리얼 엔진
- MAC
- UI
- attribute
- ability task
- unity
- Aegis
- listen server
- rpc
- CTF
- Multiplay
- widget
- 유니티
- gameplay tag
- map design
- os
- Replication
- Today
- Total
Replicated
[Unity6 Tutorial] #3 적 만들기1: 트리거 처리와 Scriptable Object, Coroutine을 통한 Spawner 만들기 본문
[Unity6 Tutorial] #3 적 만들기1: 트리거 처리와 Scriptable Object, Coroutine을 통한 Spawner 만들기
라구넹 2025. 4. 25. 13:351. 트리거 처리
목표: 맞으면 플레이어 체력이 감소되도록 하기
public class PlayerController : MonoBehaviour
{
public float HP { get; set; } = 100.0f;
플레이어 컨트롤러에 자동 구현 프로퍼티 HP 생성
- 자동 구현 프로퍼티 → 알아서 getter, setter 설정된 변수 만드는 거
EnemyController 스크립트 만들고
using UnityEngine;
public class EnemyController : MonoBehaviour
{
private const string playerBodyTag = "PlayerBody";
private float attack = 20.0f;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag(playerBodyTag))
{
PlayerController player = collision.transform.parent.GetComponent<PlayerController>();
if (player != null)
{
player.HP -= attack;
}
Debug.Log("Current Player HP : " + player.HP);
}
}
}
내용물은 이렇게 넣어주면 됨
OnTiggerEnter2D: 트리거랑 겹친 다른 트리거가 있으면 발동되는 이벤트
collision은 발생한 트리거의 정보를 가져옴
충돌 판정이 났는데, 충돌체의 태그가 playerBodyTag랑 일치하는 경우,
player를 가져와서 attack 만큼 체력을 깎음
픽셀 어드벤쳐의 Rock Head 들고 와서
씬에 배치하고
EnemyController 추가, BoxCollider2D 추가
이때, BoxCollider2D는 Is Trigger 설정 ⇒ 이제 이 컬라이더는 트리거가 됨
- 물론 하위 오브젝트로 분리하는 것이 설계 상 좋긴 한데, 이건 튜토리얼이고 어차피 Player에서 해봐서 어떻게 하는지 아니까 편의상 Enemy는 하나의 오브젝트로 진행
Player는 Trigger를 만들어주고
사이즈 조정, 그리고 컬라이더 크기도 조정
그리고 Tag 누른 다음 Add Tag
PlayerBody 추가한 다음
Tag로 설정해주면 됨
콘솔에 로그 찍히는 거 보면 이벤트 발생해서 체력이 바로바로 줄어드는 것을 확인 가능
이제 이걸 움직이도록 해보자
에너미에 RigidBody2D 추가, Freeze Position Y 체크
using UnityEngine;
public class EnemyController : MonoBehaviour
{
private Rigidbody2D rb;
private const string playerBodyTag = "PlayerBody";
private float attack = 20.0f;
private float speed = 1.0f;
private bool bIsXDirIsPositive = false;
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
if (rb != null)
{
float xDir = ( bIsXDirIsPositive ) ? 1.0f : -1.0f;
rb.linearVelocityX = xDir * speed;
}
}
Enemy 일부 코드 (밑에 부분 생략)
RigidBody2D를 가져오고, FixedUpdate에서 선형 X 속도를 xDir랑 speed 기반으로 계산
Enemy가 왼쪽으로 때리면서 지나가는 걸 확인 가능
2. Scriptable Object
EnemyData 추가
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "EnemyData", menuName = "Scriptable Object/Enemy Data")]
public class EnemyData : ScriptableObject
{
[SerializeField] private float spped = 1.0f;
public float Spped { get { return spped; } }
[SerializeField] private float attack = 10.0f;
public float Attack { get { return attack; } }
[SerializeField] private bool isXDirPositive = false;
public bool IsXDirPositive { get { return isXDirPositive; } }
}
[CreateAssetMenu(fileName = "EnemyData", menuName = "Scriptable Object/Enemy Data")]
→ 유니티 에디터에 메뉴가 생김
이제 이걸 기반으로
Create 시 Scriptable Object 생성 가능
Scriptable Objects 폴더 만들고 그 안에
아까 만든 스크립터블 오브젝트 기반으로 EnemyData를 만들어보면
인스펙터에서 저 값을 매우 조정하는 것으로 값 조정을 쉽게 할 수 있음
EnemyController에 EnemyData SerializeField로 추가해서 인스펙터에서 설정 가능하도록 하고
에너미의 EnemyData에
방금 만든 EnemyData 설정
public class EnemyController : MonoBehaviour
{
private Rigidbody2D rb;
[SerializeField] private EnemyData enemyData;
private const string playerBodyTag = "PlayerBody";
private float attack = 20.0f;
private float speed = 1.0f;
private bool bIsXDirIsPositive = false;
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
private void Start()
{
if (enemyData != null)
{
attack = enemyData.Attack;
speed = enemyData.Spped;
bIsXDirIsPositive = enemyData.IsXDirPositive;
}
}
Enemy Contorller의 Start에서 해당하는 데이터들을 꺼내옴
이제 아까 만들었던 Enemy Data를 자유롭게 바꾸면 알아서 변경됨
이런식으로, 값을 하드코딩하는 대신 외부 데이터를 참조하도록 하는 것을 데이터 기반 설계라고 함
데이터 기반 설계의 장점
- 확장성에 좋음
- 디자이너와 협업하기 좋음
3. 코루틴을 통한 오브젝트 스포닝
Prefab 폴더 만들고
Enemy를
폴더에다가 잡아다 끌어주면 Prefab이 됨
- Prefab: 오브젝트의 컴포넌트, 설정, 오브젝트 간 설계를 미리 조합해서 지정해두는 유니티의 기술
Sapwner 스크립트 생성
using System.Collections;
using Unity.VisualScripting;
using UnityEngine;
public class Spawner : MonoBehaviour
{
[SerializeField] private GameObject SpawningTarget;
[SerializeField] private float spawningTime = 1.0f;
[SerializeField] private float lifeTime = 1.0f;
private void Start()
{
StartCoroutine(Spawn());
}
IEnumerator Spawn()
{
if (SpawningTarget == null) yield break;
while (true)
{
GameObject SpawnedObejct = Instantiate(SpawningTarget);
Destroy(SpawnedObejct, lifeTime);
yield return new WaitForSeconds(spawningTime);
}
}
}
유니티의 코루틴
→ 잠시 기다렸다가, 나중에 실행하도록 하는 기능
yield return new WaitForSeconds(spawningTime);
→ spawningTime 만큼 기다린다 .. 이외에도 프레임만큼 기다리게 하는 것 등등 가능
이런 기다리는 걸 while 문 안에 넣으면?
→ 주기적으로 실행하도록 설정 가능
* Destroy(SpawnedObejct, lifeTime); → lifeTime 이후 SpawnedObject를 파괴
Enemy 지우고 빈 Object 만들어서 Spawner라고 이름 지어주고
Sapwner 스크립트 추가
Sapwning Target은 아까 만들었던 Enemy Prefab 사용
실행해보면 설정한 대로 1마다 스폰하고, 1초 뒤 디스트로이 하는 모습을 볼 수 있음
그런데, Instanticate는 리소스 많이 요구하고,
Destroy 이후 가비지 컬렉터의 동작 또한 리소스를 많이 요구함
⇒ 이를 해결하는 것이 Object Pooling 기법 (다음 시간)
3주차 부록
코루틴 사용법
타입 설명
타입 | 설명 |
null | 한 프레임 대기 (yield return null) |
new WaitForSeconds(float seconds) | 지정된 시간(초)만큼 대기 |
new WaitForSecondsRealtime(float seconds) | 실제 시간 기준으로 대기 (Time.timeScale의 영향을 받지 않음) |
new WaitForEndOfFrame() | 프레임 렌더링이 끝날 때까지 대기 |
new WaitForFixedUpdate() | 다음 FixedUpdate()까지 대기 (물리 연산 타이밍) |
new WaitUntil(Func<bool> predicate) | 조건이 true가 될 때까지 대기 |
new WaitWhile(Func<bool> predicate) | 조건이 false가 될 때까지 대기 |
CustomYieldInstruction | 사용자 정의 코루틴 대기 조건 클래스 상속 가능 |
IEnumerator First() {
yield return new WaitForSeconds(1f);
Debug.Log("First Done");
}
IEnumerator Second() {
yield return StartCoroutine(First());
Debug.Log("Second Done");
}
코루틴 중단은 StopCoroutine()
그리고 씬 변경 시 자동 중단됨
IEnumerator로 리턴해야 하는 이유?
IEnumerator는 MoveNext 같은 다음 실행 지점을 알려주는 함수 규약을 가짐
-> StartCoroutine에 인자로 넘겨줘서 다음에 언제 실행할지 알려주는게 가능
'유니티 엔진 > Unity6 Tutorial' 카테고리의 다른 글
[Unity6 Tutorial] #2 애니메이션 & 액션 - 달리기, 점프, Grounded 체크 (0) | 2025.04.25 |
---|---|
[Unity6 Tutorial] #1 프로젝트 생성, 애셋 스토어, 유니티 물리, 유니티 생명 주기, 뉴 인풋 (0) | 2025.03.29 |