10/11 TIL 3D FPS(2)

Cheorii·2024년 10월 11일

오늘은 코루틴에 대해 자세히 알아보려고 한다.

Invoke vs Coroutine

Invoke

함수의 이름과, 시간을 인자로 받아 그 함수를 받은 인자만큼의 시간 이후에 실행

Invoke( "함수명"(string) , 지연시간(float));

즉, 어떤 명령을 조금 있다가 사용하기 위해 사용하는 함수

Invoke특징

  • GameObject가 비활성화 되도 동작
  • InvokeRepeating을 통해 지속적으로 반복 동작 가능
InvokeRepeating( 함수명(String), 지연시간(float), 반복간격(float));
  • CancelInvoke 을 통해 인자로 받은 Invoke 함수의 실행을 중지
CancelInvoke("함수명"(String));

Coroutine

시간의 경과에 따른 명령을 주고 싶을때 사용하게 되는 유니티 문법

코루틴 호출 / 정의
StartCoroutine과 함께 사용

 StartCoroutine(DestroyTrail(go));

코루틴 작성 방법

 StartCoroutine(DestroyTrail(go));

IEnumerator DestroyTrail(GameObject obj)   // IEnumerator반환형으로 시작
{
    yield return new WaitForSeconds(0.1f); // 반환하는 yield return 반드시 포함

    Destroy(obj);   
}

yield return 의 종류

  • yield return null; : 다음 프레임에 실행 됨.

  • yield return new WaitForSeconds( float ); : 매개변수로 입력한 숫자에 해당하는 초만 큼 기다렸다가 실행됨.

  • yield return new WaitForSecondsRealtime( flaot ); : 매개변수로 입력한 숫자에 해당하는 초만큼 기다렸다가 실행됨.

  • yeild break; : 코루틴 내부에서 함수 진행을 즉시 종료(진행중인 코루틴 흐름 중단)

Coroutine특징

  • C# 기반의 반복기(enumerator)를 사용하는 개념(IEnumerator로 만들어진 함수를 사용)

  • yield return을 호출하여 프레임 단위, 시간 단위, 특정 조건이 만족이 될 때 등으로 대기가 가능

  • StartCoroutine()으로 실행 가능하며, Coroutine이라는 변수를 선언해 실행한 코루틴을 담을 수 있다. ex) Coroutine co = StartCoroutine("함수 이름");

  • 코루틴이 호출된 게임오브젝트(또는 호출한 컴포넌트)가 활성화 상태일 때만 실행 가능하다.

  • 반대로 코루틴이 정상적으로 실행된 상태에서 게임오브젝트(또는 호출한 컴포넌트)가 비활성화되면 중단되며, StopCoroutine()을 통하여 중지 가능하다.

yeild break vs StopCoroutine()

둘 다 코루틴을 중단하지만 뭐가 다른가 싶어서 챗 지피티에게 물어봄!

yield break는 코루틴 내에서 코드를 종료하고자 할 때, 코루틴 자체에서 명시적으로 종료하는 방식입니다.
StopCoroutine은 외부에서 코루틴을 제어할 때 사용되며, 특정 코루틴을 중단하거나 모든 코루틴을 한꺼번에 중지할 수 있습니다.


Invoke와 Coroutine 성능

  • Reflection
    - 프로그램 실행 중에 객체의 정보를 얻거나, 다른 모듈에 선언된 인스턴스를 생성하거나, 기존 개체에서 형식을 가져오고 해당하는 메소드를 호출, 또는 해당 필드와 속성에 접근할 수 있는 기능을 제공.

Invoke는 Coroutine이 메소드 자체를 인자로 받아가는 것과는 다르게, 메소드 이름을 받아간다.
이걸 Reflection을 통해 값을 가져가는데, 이 과정이 Coroutine보다 느리다.

그래서 Unity공식 문서에서도 더 좋은 성능을 내고 싶으면 Invoke보다는 Coroutine을 권장하고 있다.


파티클 시스템(Particle System)

이 프로젝트에서 총에 맞은 지점에 이펙트를 만들기 위해 사용했다.
-> 파티클(2D입자를 흩뿌리는 이펙트)

자세한 내용은 유니티 공식 문서를 활용하면 편하다
https://docs.unity3d.com/kr/2020.3/Manual/class-ParticleSystem.html

파티클 시스템을 이용해서 제작을 하니 아래와 같이 파편이 튀는 것 처럼 제작되었다.

  • NavMesh
    게임 월드에서 걸을 수 있는 표면을 뜻하며, NavMesh를 사용하여 게임 월드 안의 한 위치에서 다른 위치로 이동할 수 있는 경로를 찾을 수 있다.

  • NavMesh는 이 표면을 Convex 폴리곤으로 저장한다.

  • Convex 폴리곤은 폴리곤 안의 두 지점 사이에 아무런 장애물이 없기 때문에 이런한 목적으로 유용하게 사용된다.

  • 폴리곤의 경계를 비롯하여 서로 이웃한 폴리곤에 대한 정보도 저장하며 걸을 수 있는 모든 영역을 탐색할 수 있다.

적용하는 방법은 간단하게 진행했다.
자세한 내용은 유니티 공식문서를 보고 진행했다.
https://docs.unity3d.com/kr/2023.1/Manual/nav-BuildingNavMesh.html

NavMesh를 사용해서 월드를 제작하고
Bake된 지역에 한해서 내가 이동한 위치에 따라 적이 이동할 수 있도록 작성했다.

using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;

public class EnemyController : MonoBehaviour
{
    GameObject player;
    NavMeshAgent agent;
    public float walkSpeed = 3;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        player = GameObject.FindWithTag("Player");
        agent = GetComponent<NavMeshAgent>();

        // 적의 기본 이동 속도를 설정
        agent.speed = walkSpeed;

        agent.destination = player.transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        //agent.destination = player.transform.position;
        if(agent.remainingDistance < 1f)    //목적지까지 남은 거리가 1m 미만이면
        {
            agent.destination = player.transform.position;
        }
    }
}

실행 영상이다

업로드중..

profile
코딩테스트는 진짜 못하겠어요 ㅠㅠ

0개의 댓글