Unity 엔진 내에서 C# 코드로 구현하는 코루틴(Coroutine) 방식을 공부해보자.
예제를 한번 던져보고 예제를 통해 공부를 한다.
아래는
회피와 저스트 회피에 대해서 Unity 에서 제공되는 클래스, 메서드등을 이용해 코루틴으로 구현한 예제다.
완벽한 예제는 아니고, 간단하게 약식으로 이해를 돕기위해 작성한 코드다.
먼저 회피 (프레임회피)
using UnityEngine;
using System.Collections;
public class FrameDodge : MonoBehaviour
{
// Unity 엔진에서 제공하는 Animator 컴포넌트 (애니메이션 재생)
public Animator animator;
// Rigidbody로 물리 기반 이동을 구현할 경우 사용
public Rigidbody rb;
// 회피 동작 중 무적 상태를 유지하는 시간 (초 단위)
public float invincibilityDuration = 0.5f;
// 회피 속도 (이동 구현을 위한 값)
public float dodgeSpeed = 5f;
// 회피 상태를 추적하는 변수
private bool isDodging = false;
void Update()
{
// 예제에서는 Space 키를 회피 버튼으로 사용
if (Input.GetKeyDown(KeyCode.Space) && !isDodging)
{
StartCoroutine(PerformDodge());
}
}
IEnumerator PerformDodge()
{
isDodging = true;
// Animator에서 "Dodge" 애니메이션 재생 (애니메이션 클립은 엔진에서 제공하거나 사용자가 추가)
animator.SetTrigger("Dodge");
// 회피 시작과 동시에 무적 상태로 설정 (예: PlayerController에 무적 플래그가 있을 경우)
SetInvincible(true);
// 간단하게 전방으로 dodgeSpeed 만큼 이동 (실제 게임에서는 이동 경로, 애니메이션 커브 등과 연동 가능)
Vector3 dodgeDirection = transform.forward;
rb.velocity = dodgeDirection * dodgeSpeed;
// 무적 상태를 일정 시간 유지
yield return new WaitForSeconds(invincibilityDuration);
// 무적 해제
SetInvincible(false);
isDodging = false;
// 이동 속도를 초기화 (예시로 단순히 0으로 설정)
rb.velocity = Vector3.zero;
}
// 무적 상태를 설정하는 메서드 (이 예제에서는 단순히 Debug.Log로 표현)
void SetInvincible(bool state)
{
// 만약 실제 게임에서 충돌 판정을 제어한다면, collider의 레이어 변경이나, 무적 플래그를 업데이트할 수 있음
Debug.Log("Invincibility set to: " + state);
}
}
그다음은 저스트회피다.
using UnityEngine;
using System.Collections;
public class JustDodge : MonoBehaviour
{
public Animator animator;
public Rigidbody rb;
// 일반 회피의 무적 시간
public float invincibilityDuration = 0.5f;
// 저스트 회피 추가 보너스 시간 (정확한 타이밍 시)
public float justBonusDuration = 0.3f;
// 회피 속도
public float dodgeSpeed = 5f;
// 저스트 회피 성공 판정을 위한 이상적인 타이밍 (회피 애니메이션 중 무적이 시작되는 이상적인 시간, 초 단위)
public float idealDodgeTime = 0.2f;
// 저스트 허용 오차 (타이밍이 idealDodgeTime으로부터 벗어날 수 있는 최대 허용 오차, 초 단위)
public float justTimingTolerance = 0.1f;
private bool isDodging = false;
private float dodgeStartTime;
void Update()
{
// 예제에서는 Space 키로 회피 입력 처리
if (Input.GetKeyDown(KeyCode.Space) && !isDodging)
{
dodgeStartTime = Time.time;
StartCoroutine(PerformJustDodge());
}
}
IEnumerator PerformJustDodge()
{
isDodging = true;
animator.SetTrigger("Dodge");
// 일반 회피 시작: 무적 활성화
SetInvincible(true);
rb.velocity = transform.forward * dodgeSpeed;
// 대기: 이상적인 회피 타이밍에 도달할 때까지 기다림
yield return new WaitForSeconds(idealDodgeTime);
// 플레이어가 입력한 회피 타이밍과 이상적인 시간의 차이 계산
float inputDelay = Time.time - dodgeStartTime;
bool isJustSuccessful = Mathf.Abs(inputDelay - idealDodgeTime) <= justTimingTolerance;
if (isJustSuccessful)
{
// 저스트 회피 성공: 추가 보너스 무적 효과 적용
Debug.Log("Just Dodge 성공! 추가 보너스 적용");
yield return new WaitForSeconds(justBonusDuration);
}
else
{
Debug.Log("일반 회피로 처리");
}
// 무적 해제
SetInvincible(false);
isDodging = false;
rb.velocity = Vector3.zero;
}
void SetInvincible(bool state)
{
Debug.Log("Invincibility set to: " + state);
}
}
간단하게 비교하자면
프레임회피는, 회피 시간동안 무적판정인것이고
저스트회피는, 회피 시간안에서도 저스트 판정 시간이 따로 존재하며 이 타이밍에 맞춰 회피한다면, 오차범위 내에 있을때 인정해주면서 추가적인 보너스(예제에서는 무적시간 보너스) 를 적용해주는 메커니즘인것이다.
우선, 예제를 해석해보기위해 Unity 에서 제공해주는 몇가지를 공부해보자.
Animator에 대해 알아보자.
1. Unity의 애니메이션 시스템에서 게임 오브젝트(주로 캐릭터나 UI 등)의 애니메이션 상태를 관리하는 컴포넌트
2. Animator Controller와 함께 동작하며, 여러 애니메이션 클립들을 상태 머신(State Machine)으로 구성하여, 조건이나 이벤트에 따라 애니메이션을 전환
3. 관련 기능 및 구성요소
- Animation Clip: 개별 애니메이션 시퀀스(걷기, 뛰기, 공격 등).
- Animator Controller: 여러 Animation Clip과 전환 규칙을 관리하는 에셋.
- 파라미터(Parameter): 애니메이터 컨트롤러 내에서 전환 조건을 정의하기 위한 값(예: Bool, Trigger, Float, Int).
- Transition: 애니메이션 간의 전환을 정의하는 규칙 및 조건.
- Layer: 여러 애니메이션 계층을 구성하여 동시에 재생할 수 있도록 함.
사용 이유
- 애니메이션 관리의 중앙 집중화: 여러 애니메이션 클립을 한 곳에서 관리하고, 상황에 따라 자연스러운 전환을 만들어낼 수 있음.
- 복잡한 행동 구현: 상태 머신을 통해 다양한 상황(예: 이동, 공격, 회피 등)에 맞는 애니메이션 전환을 쉽게 구성할 수 있음.
- 재사용성과 확장성: 같은 캐릭터라도 다른 상황에 맞춰 애니메이션을 유연하게 변경할 수 있으므로 코드의 재사용성이 높아짐.
Rigidbody 에 대해 알아보자.
1. Rigidbody는 Unity에서 물리 기반의 움직임과 충돌 처리를 담당하는 컴포넌트
2. 게임 오브젝트에 부착하면, 중력, 충돌, 물리 법칙(힘, 토크, 마찰 등)에 따라 자동으로 움직임과 상호작용이 구현된다.
엔진상 GameObject를 생성하고 컴포넌트로 (생성)붙여줄 수 있다
3. 관련 기능 및 구성요소
- 물리 연산: 중력, 관성, 마찰력 등의 물리 법칙을 적용.
- Force(힘) 적용: AddForce, AddTorque 등의 메서드를 통해 힘을 직접 적용할 수 있음.
- 충돌 감지: Collider와 함께 사용되어 충돌 이벤트를 감지하고 처리할 수 있음.
- Kinematic 옵션: 물리 연산의 영향을 받지 않고 스크립트로 직접 움직임을 제어할 수 있도록 설정 가능. 해당 옵션은 Rigidbody 에서 Dynamic 으로 되어있는 옵션을 Kinematic으로 변경후, 스크립트에서 필요한 메서드를 호출해서 사용 가능하다. 보통 collider와 rigidbody는 함께 움직이는데, rigidbody에서 kinematic으로 설정한다면, collider 컴포넌트에서 Is trigger 옵션에 체크 표시를 해준다. 물리연산의 영향을 받는게아니라, 스크립에서 제어할때 트리거가 되는 메서드를 호출할때 연동시키기 때문이다.
사용 이유
- 자연스러운 움직임: 물리 기반 연산을 통해 보다 현실감 있는 움직임을 구현할 수 있음.
- 충돌 처리: 충돌체와 상호작용하며, 충돌 감지를 통한 게임 로직(예: 데미지 처리, 반동 효과 등)을 구현할 수 있음.
- 효율적인 이동 제어: 단순히 트랜스폼을 조작하는 것보다 물리 엔진을 이용하면 자연스러운 가속, 감속, 회전 등이 가능함.
Input 에 대해서 알아보자.
1. Input은 UnityEngine 네임스페이스에 포함되어 있는 클래스이며, 키보드, 마우스, 게임패드 등 사용자의 입력을 감지하고 처리하는 역할을 한다.
2. 관련 기능 및 구성요소
- Input.GetKey, Input.GetKeyDown, Input.GetKeyUp: 키보드 입력을 감지하는 메서드.
- 예: Input.GetKeyDown(KeyCode.Space)는 스페이스바를 누르는 순간을 감지.
- Input.GetAxis, Input.GetAxisRaw: 아날로그 입력(예: 조이스틱, 마우스 이동)을 감지하는 메서드.
- Input.mousePosition: 현재 마우스의 스크린 좌표를 반환.
- Input.touches: 터치 입력 정보를 배열로 제공(모바일 개발 시 사용).
사용 이유
- 사용자와의 상호작용: 게임 내에서 사용자 입력에 따라 캐릭터의 움직임, 공격, 메뉴 조작 등 다양한 이벤트를 발생시킴.
- 유연성: 여러 종류의 입력 장치를 지원하며, 상황에 맞게 입력 데이터를 해석할 수 있음.
다음은 대망의 코루틴이다.
코루틴 (Coroutine)이란?
- 코루틴은 Unity에서 비동기 처리를 위해 사용하는 메서드로, 일반 메서드와 달리 실행을 중간에 일시 중지(yield)했다가 특정 조건이나 시간 후에 다시 이어서 실행할 수 있습니다.
- IEnumerator를 반환하는 메서드로 구현되며, 주로 시간 지연, 애니메이션 동기화, 연속적인 행동 실행 등에 사용됩니다.
- Update 메서드와 차이점: Update는 매 프레임마다 호출되지만, 코루틴은 특정 조건(예: 일정 시간 지연) 후에 재개되므로, 시간 기반 처리가 필요할 때 더 유용합니다.
- 비동기 처리: 동기 방식으로 작성하기 복잡한 시간 지연 로직을 단순하게 구현할 수 있게 해줍니다.
- 비동기와 동기처리에 대하여, 그리고 차이점.
동기 처리와 비동기 처리는 작업(태스크)을 실행하는 방식의 차이를 설명하는 개념입니다.
1. 동기처리
- 동기 처리는 작업을 순차적으로 실행하는 방식입니다.
- 한 작업이 완료되어야 다음 작업이 시작됩니다.
- 즉각적인 실행: 각 작업이 순서대로 실행되므로, 이전 작업이 끝나기 전에는 다음 작업이 대기 상태가 됩니다.
예시
- 요리하는 것: 레시피를 따르는데, 먼저 재료를 손질하고, 그 다음에 조리하는 식입니다. 한 단계가 끝나야 다음 단계로 넘어갑니다.
void ProcessTasks()
{
TaskA(); // TaskA가 끝나야
TaskB(); // 그 후에 TaskB 실행됨
}
- 장점: 코드의 실행 순서가 명확하여 이해하기 쉽습니다.
- 단점: 한 작업이 오래 걸릴 경우, 전체 프로세스가 지연될 수 있습니다. (예: 파일 다운로드를 동기적으로 실행하면 전체 프로그램이 멈출 수 있음)
2. 비동기처리 ( Asynchronous Processing) C# 코드에서 unityengine을 안쓸땐 async 키워드를 쓴다. 아래에서 공부
- 비동기 처리는 작업을 동시에 또는 병렬로 실행하는 방식입니다.
- 한 작업의 완료를 기다리지 않고, 다른 작업을 동시에 진행할 수 있습니다.
- 대기 시간 활용: 작업 중 기다려야 하는 시간(예: 네트워크 응답, 파일 입출력)이 있는 경우, 그 시간 동안 다른 작업을 수행할 수 있습니다.
예시
- 요리하는 것: 요리를 할 때, 물이 끓는 동안 다른 재료를 준비하는 것처럼, 동시에 여러 작업을 진행합니다.
async void ProcessTasksAsync()
{
await TaskAAsync(); // TaskAAsync가 완료될 때까지 기다리지만, 그 사이 다른 작업을 수행할 수 있음
await TaskBAsync(); // TaskAAsync 완료 후 TaskBAsync 실행
}
Unity 코루틴 예제:
IEnumerator WaitAndPrint()
{
Debug.Log("시작");
yield return new WaitForSeconds(2f); // 2초 동안 대기하는 동안 다른 작업 진행 가능
Debug.Log("2초 후 출력");
}
코루틴 필요 이유
- 시간 제어: 특정 시간 동안 대기하거나, 여러 프레임에 걸쳐 실행되는 로직을 작성할 때 유용합니다.
- 코드 가독성 향상: 복잡한 타이밍 제어나 비동기 처리를 함수 내부에서 순차적으로 작성할 수 있어 코드의 가독성이 높아집니다.
- 자원 효율성: 메인 스레드를 블로킹하지 않고 실행되므로, 성능에 미치는 영향이 적습니다.
또다른 Unity 코루틴 예제;
using UnityEngine;
using System.Collections;
public class CoroutineExample : MonoBehaviour
{
void Start()
{
// 코루틴 실행
StartCoroutine(PrintMessages());
}
// 코루틴 메서드: 순차적으로 메시지를 출력하면서 일정 시간 대기
IEnumerator PrintMessages()
{
Debug.Log("메시지 1: 시작!");
// 2초 대기
yield return new WaitForSeconds(2f);
Debug.Log("메시지 2: 2초 후!");
// 다음 프레임까지 대기
yield return null;
Debug.Log("메시지 3: 다음 프레임!");
// 1초 대기
yield return new WaitForSeconds(1f);
Debug.Log("메시지 4: 1초 후 완료!");
}
}
사용법
- 정의: 반환형을 IEnumerator로 정의합니다. IEnumerator<T> 란? 참고: https://muchmercy.tistory.com/27
- Yield Statement: yield return을 사용하여 중단 시점을 지정합니다.
- yield return null;은 다음 프레임까지 대기합니다.
- yield return new WaitForSeconds(n);는 n초 대기합니다.
- 실행: StartCoroutine(YourCoroutine());을 통해 코루틴을 실행합니다.
해당 예제는 Unity Engine 이라는 네임스페이스를 쓰지않고, C#으로만으로도 비슷하게 구현 가능하다.
using System;
using System.Threading.Tasks;
public class CoroutineExample
{
// 비동기 메서드로 코루틴과 유사한 동작을 구현합니다.
public static async Task PrintMessagesAsync()
{
Console.WriteLine("메시지 1: 시작!");
// 2초 대기: Unity의 yield return new WaitForSeconds(2f)와 유사
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine("메시지 2: 2초 후!");
// 다음 "프레임"까지 대기: 현재 컨텍스트에서 다른 작업으로 양보
await Task.Yield();
Console.WriteLine("메시지 3: 다음 프레임!");
// 1초 대기
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine("메시지 4: 1초 후 완료!");
}
// C# 7.1 이상에서는 Main 메서드를 async로 만들 수 있습니다.
public static async Task Main(string[] args)
{
await PrintMessagesAsync();
}
}
코드 설명
- 비동기 메서드 (PrintMessagesAsync)
이 메서드는 async/await 패턴을 사용하여, Unity의 코루틴처럼 일정 시간 대기 후 다음 코드를 실행합니다. - Task.Delay(TimeSpan.FromSeconds(2))
2초 동안 대기합니다. 이는 Unity의 WaitForSeconds(2f)와 동일한 역할을 합니다. - Task.Yield()
현재 작업을 잠시 중단하고, 다른 작업(예를 들어 UI 업데이트 등)에게 실행 제어를 양보합니다. Unity의 yield return null과 유사한 효과를 줍니다. - Main 메서드
비동기 메서드를 호출하여 프로그램의 시작점에서 PrintMessagesAsync()를 실행합니다.
여기서 좀더 키워드들에 대해 자세히 설명해보자면
async 키워드
- async 키워드는 메서드, 람다, 익명 메서드를 비동기적으로 실행할 수 있도록 표시하는 예약어입니다.
- 이 키워드가 붙은 메서드는 내부에서 비동기 작업을 수행할 수 있으며, 보통 Task 또는 Task<T>를 반환합니다.
- 핵심 포인트:
- 메서드가 비동기 작업을 포함할 수 있게 해줍니다.
- 컴파일러에게 이 메서드 내부에 await가 있을 수 있음을 알립니다.
사용 이유
- 비동기 작업을 손쉽게 구현하여, 긴 작업(예: 네트워크 요청, 파일 I/O, 긴 계산)을 실행하는 동안 애플리케이션이 멈추지 않도록 도와줍니다.
- 코드의 가독성을 높이며, 콜백 지옥(callback hell)과 같은 복잡한 코드 구조를 피할 수 있습니다.
// async 키워드가 붙은 메서드입니다.
public async Task DoWorkAsync()
{
// 비동기 작업 수행
await Task.Delay(1000); // 1초 대기
Console.WriteLine("작업 완료!");
}
await 키워드
- await 키워드는 async 메서드 내에서 비동기 작업이 완료될 때까지 기다리도록 하는 예약어입니다.
- 비동기 작업(Task)이 완료되기 전까지 메서드의 실행을 일시 중지하지만, 그 동안 다른 작업이 진행될 수 있도록 제어권을 반환합니다.
- 핵심 포인트:
- 비동기 작업의 결과를 기다리는 동안, 스레드를 블로킹하지 않습니다.
- 코드가 마치 동기 코드처럼 순차적으로 보이도록 도와줍니다.
사용 이유
- 비동기 작업의 완료를 기다리면서도 애플리케이션이 멈추지 않도록 하여, UI가 응답 상태를 유지하거나 다른 작업을 동시에 처리할 수 있게 합니다.
- 복잡한 비동기 작업을 간단하고 직관적으로 작성할 수 있습니다.
public async Task<int> CalculateValueAsync()
{
// 2초 후에 결과 반환 (비동기 대기)
await Task.Delay(2000);
return 42;
}
public async Task UseValueAsync()
{
// CalculateValueAsync 메서드의 결과가 준비될 때까지 기다림
int result = await CalculateValueAsync();
Console.WriteLine("계산된 값: " + result);
}
Task
정의 및 역할
- Task는 C#의 비동기 작업(태스크)을 나타내는 클래스입니다.
- 작업의 실행, 완료, 실패 등의 상태를 관리하며, 작업이 완료되면 결과를 반환하거나 완료되었음을 알립니다.
- Task는 반환 값이 없는 비동기 메서드에 사용되고, Task<T>는 T 타입의 결과를 반환하는 비동기 메서드에 사용됩니다.
사용 이유
- 비동기 작업의 상태를 추적하고, 결과를 반환받기 위해 사용됩니다.
- 스레드 풀(thread pool)을 활용하여 효율적으로 비동기 작업을 수행할 수 있습니다.
- Task를 통해 비동기 작업들을 조합하거나, 동기화(concatenate)할 수 있으며, 예외 처리를 일관되게 관리할 수 있습니다.
// 반환값이 없는 Task를 사용하는 예제
public async Task PerformAsyncTask()
{
Console.WriteLine("비동기 작업 시작");
await Task.Delay(1000); // 1초 동안 대기
Console.WriteLine("비동기 작업 완료");
}
// 반환값이 있는 Task<T>를 사용하는 예제
public async Task<int> GetResultAsync()
{
await Task.Delay(1000);
return 100;
}
public async Task TestTaskAsync()
{
// 비동기 작업 호출
await PerformAsyncTask();
// 결과를 반환하는 비동기 작업 호출
int value = await GetResultAsync();
Console.WriteLine("받은 값: " + value);
}
스레드를 블로킹하지않는다에 대한,, 설명
스레드란?
- 정의:
스레드는 프로그램 내에서 실행되는 작업의 흐름(실행 경로)입니다. 운영체제는 각 스레드에 CPU 시간을 할당하여 동시에 여러 작업을 실행할 수 있도록 합니다. - 프로세스와의 관계:
- 프로세스: 실행 중인 프로그램으로, 메모리 공간과 자원을 독립적으로 관리합니다.
- 스레드: 하나의 프로세스 내에서 실행되는 경량화된 실행 단위로, 프로세스의 자원(메모리 등)을 공유하면서 독립적인 실행 흐름을 가집니다.
- 예시:
웹 브라우저는 사용자의 입력, 페이지 렌더링, 네트워크 요청 등 여러 작업을 동시에 처리해야 하므로 여러 스레드를 사용합니다.
따라서
"스레드를 블로킹하지 않는다"는 뜻
- 블로킹(Block):
어떤 작업을 수행하는 동안 해당 작업이 완료될 때까지 스레드가 다른 작업을 하지 못하고 멈춰 있는 상태를 말합니다. 예를 들어, 파일을 읽는 작업이 완료될 때까지 스레드가 아무것도 할 수 없는 상황입니다. - 블로킹하지 않는(Non-blocking):
반대로, 블로킹하지 않는 방식은 어떤 작업을 기다리는 동안에도 스레드가 다른 작업을 수행할 수 있도록 하는 것입니다.- 예를 들어, 네트워크 요청을 보내고 응답을 기다리는 동안, 스레드가 UI 업데이트나 다른 작업을 계속할 수 있다면, 이 작업은 비동기적이며 스레드를 블로킹하지 않는다고 말합니다.
- 비동기 작업의 관점:
C#에서 await 키워드를 사용하면, 해당 작업이 완료될 때까지 기다리는 동안 스레드가 다른 작업을 수행할 수 있습니다. 이때 스레드를 블로킹하지 않는다는 의미는, 작업을 기다리는 동안 스레드가 "멈추지 않고" 다른 작업을 처리할 수 있다는 뜻입니다.
블로킹:
// 이 코드는 Task.Delay(2000)이 끝날 때까지 스레드가 아무 것도 못함.
Thread.Sleep(2000);
Console.WriteLine("2초 후 출력");
여기서 스레드는 2초동안 멈춰있다.
비동기 (블로킹하지 않음):
public async Task PrintMessageAsync()
{
Console.WriteLine("대기 시작");
await Task.Delay(2000); // 2초 대기, 이 동안 스레드는 다른 작업을 처리할 수 있음.
Console.WriteLine("2초 후 출력");
}
위 코드에서 await Task.Delay(2000)는 2초 동안 기다리지만, 기다리는 동안 스레드는 다른 대기 중인 작업이나 이벤트를 처리할 수 있으므로, 전체 프로그램의 반응성이 유지됩니다.
스레드 풀(thread pool)
주요 개념
- 미리 생성된 스레드 집합:
스레드 풀은 애플리케이션 시작 시 혹은 초기 요청 시 일정 개수의 스레드를 미리 만들어 둡니다. 필요할 때마다 이 스레드들을 재사용합니다. - 재사용:
작업이 끝난 스레드는 종료되지 않고, 다시 스레드 풀로 반환되어 다음 작업을 수행할 수 있습니다. 이를 통해 스레드 생성에 소요되는 비용을 절약합니다. - 관리 및 제어:
스레드 풀은 내부적으로 생성되는 스레드 수, 최대 스레드 수 등을 관리하며, 시스템 부하에 따라 동적으로 스레드 수를 조정할 수 있습니다.
using System;
using System.Threading;
public class ThreadPoolExample
{
public static void Main(string[] args)
{
// ThreadPool.QueueUserWorkItem을 사용하여 스레드 풀에서 작업 실행
ThreadPool.QueueUserWorkItem(DoWork, "작업 1");
ThreadPool.QueueUserWorkItem(DoWork, "작업 2");
// 작업이 완료될 때까지 잠시 대기
Console.WriteLine("메인 스레드가 다른 작업을 수행합니다...");
Thread.Sleep(3000);
}
// 스레드 풀에서 실행할 작업
static void DoWork(object state)
{
Console.WriteLine($"{state} 시작 (스레드 ID: {Thread.CurrentThread.ManagedThreadId})");
Thread.Sleep(1000); // 작업 시뮬레이션
Console.WriteLine($"{state} 완료 (스레드 ID: {Thread.CurrentThread.ManagedThreadId})");
}
}
그렇다면 최상단 회피와 저스트 회피는 왜 코루틴을 사용하였는가?
간단하다,
코루틴 사용 이유
- 비동기 작업 처리:
코루틴은 특정 작업(예: 시간 지연, 여러 프레임에 걸친 연산)을 처리할 때, 한 프레임에서 멈추고 다음 프레임에 이어서 실행할 수 있습니다.
예를 들어, 회피 동작에서 0.5초 동안 무적 상태를 유지하는 동안 다른 로직이 계속 실행되도록 하기 위해 사용합니다. - 메인 스레드 블로킹 방지:
코루틴은 Unity의 메인 스레드를 블로킹하지 않고, 비동기적으로 동작할 수 있게 해줍니다.
이로 인해 애니메이션이나 물리 연산 등 다른 게임 루프가 원활하게 돌아갑니다.
'Unity 개발 공부' 카테고리의 다른 글
| [내일배움캠프] 10일차 공통과제 오목 - 메인메뉴 (25.04.03) (0) | 2025.04.03 |
|---|---|
| [내배캠] 9일차 기초문법 활용해서 구구단, 최대값,최소값 내기 (25.04.02) (0) | 2025.04.01 |
| [내배캠] 8일차 게임속 상호작용 분석하기 (25.04.01) (1) | 2025.04.01 |
| [내배캠] 7일차 오목게임 기획 ( 사전 팀프로젝트) (0) | 2025.03.31 |
| [내배캠 사전캠프] 7일차 C# 기초 응용 수학문제풀이(25.03.31) (0) | 2025.03.31 |