본문 바로가기
TIL

12.13 (TIL - Unity)

by 오랑이귀엽다 2023. 12. 13.

오브젝트 풀 구현 - 핵심내용

오브젝트 풀링

게임 개발에 널리 사용되는 테크닉으로, 게임의 성능을 개선하기 위해 사용

 

오브젝트 풀링은 객체를 미리 생성해 두고 필요할 때 가져다 사용하고,

사용이 끝나면 다시 풀에 반납하는 방식을 말한다.

 

오브젝트 풀링은 생성(Instantiate)과 소멸(Destroy)이라는 비용이 큰 작업을 최소화함으로써

성능을 향상시키는 데 중요한 역할을 한다.

 

이는 특히 빈번하게 생성하고 파괴되는 객체(예: 총알, 입자 등)에 대해 중요하며,

이런 객체들을 풀에 저장해 놓고 재사용함으로써 메모리 할당과 가비지 컬렉션에 따른 성능 저하를 방지할 수 있다.

 

오브젝트 풀링은 적절히 사용하면 큰 성능 개선을 가져올 수 있지만, 불필요한 메모리 사용을 증가시킬 수 있으므로 사용 시에는 신중해야 한다.

오브젝트 풀의 크기를 적절히 조절하는 것이 중요하다.

 

 

오브젝트 풀 만들기

1. ObjectPool 만들기

더보기

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectPool : MonoBehaviour
{
    [System.Serializable]
    public struct Pool
    {
        public string tag;
        public GameObject prefab;
        public int size;
    }

    public List<Pool> pools;
    public Dictionary<string, Queue<GameObject>> poolDictionary;

    private void Awake()
    {
        poolDictionary = new Dictionary<string, Queue<GameObject>>();
        foreach (var pool in pools)
        {
            Queue<GameObject> objectPool = new Queue<GameObject> ();
            for (int i = 0; i < pool.size; i++)
            {
                GameObject obj = Instantiate(pool.prefab);
                obj.SetActive(false);
                objectPool.Enqueue (obj);
            }
            poolDictionary.Add (pool.tag, objectPool);
        }
    }

    public GameObject SpawnFromPool(string tag)
    {
        if (!poolDictionary.ContainsKey(tag))
            return null;

        GameObject obj = poolDictionary[tag].Dequeue();
        poolDictionary[tag].Enqueue(obj);

        return obj;
    }
}

 

2. 오브젝트 풀 적용하기

  • ProjectileManager에 Object Pool 추가
  • 다음과 같이 Object Pool 수정

 

3. ProjectileManager 수정

더보기

[SerializeField] private GameObject testObj;
private ObjectPool objectPool;

void Start()
{
    objectPool = GetComponent<ObjectPool>();
}

public void ShootBullet(Vector2 startPostiion, Vector2 direction, RangedAttackData attackData)
{
    GameObject obj = Instantiate(testObj);
    GameObject obj = objectPool.SpawnFromPool(attackData.bulletNameTag);

    obj.transform.position = startPostiion;
--------------------- 생략 ---------------------

 

 

애니메이션 컨트롤 - 핵심내용

1. Animation & Animator

Animation:

  • Animation 컴포넌트는 게임 오브젝트에 애니메이션을 추가하는 데 사용
  • 이 컴포넌트는 애니메이션 클립을 재생할 수 있다.
  • Animation 컴포넌트는 간단한 애니메이션에 적합하며, 스크립트를 통해 직접 제어
  • 애니메이션 클립은 Unity의 Animation window를 통해 생성하거나 편집할 수 있다..
  • 예를 들어, 이 컴포넌트를 사용하여 오브젝트의 크기를 변경하거나 색상을 변환하는 등의 간단한 애니메이션을 생성

Animator:

  • Animator 컴포넌트는 애니메이션의 상태를 제어하고 전환을 관리하는 데 사용
  • Animator 컴포넌트는 Animation Controller를 사용하여 애니메이션의 복잡한 상태 기계를 구현
  • Animator 컴포넌트는 여러 애니메이션 클립을 조절하고, 애니메이션 간의 전환을 제어하고, 복잡한 애니메이션 시퀀스를 구현하는 데 적합
  • 예를 들어, 캐릭터의 걷기, 뛰기, 점프 등의 애니메이션을 관리하는 데 사용될 수 있다.
  • Animator 컴포넌트는 Mecanim 애니메이션 시스템의 일부로서, 애니메이션 블렌딩, 트리, 상태 머신 등의 기능을 제공

이 두 컴포넌트는 서로 다른 목적과 사용 케이스에 따라 애니메이션을 제어하는 데 사용

Animation은 더 간단한 애니메이션에 사용되며, Animator는 더 복잡한 애니메이션 시퀀스와 상태 관리에 사용

 

2. StringToHash

유니티 애니메이션 시스템에서 자주 사용되는 기능

문자열을 해시 값으로 변환하며, 이로써 성능을 개선하고 코드의 가독성을 유지

  • 문자열 비교는 상대적으로 연산 비용이 큰 작업. "StringToHash"는 문자열을 고유한 정수 값인 해시 값으로 변환하여 이 연산 비용을 크게 줄일 수 있다.
  • 해시 값은 고유하기 때문에 다른 문자열이 동일한 해시 값을 갖는 확률이 매우 낮다. 이를 활용해 문자열을 해시로 변환하면 효율적으로 문자열을 비교할 수 있다.
  • 애니메이션 파라미터를 지정할 때 문자열 대신 해시 값을 사용하면 CPU 시간을 절약하고 애니메이션 성능을 향상시킬 수 있다.
  • 그러나 주의할 점은 동일한 문자열은 항상 동일한 해시 값을 반환하지만, 반대로 동일한 해시 값이 항상 동일한 문자열을 반환하지는 않는다. 이 점으로 인해 해시 충돌이 발생할 수 있다.
  • 또한, "StringToHash" 함수는 문자열을 해시 값으로 변환할 때 일방향으로 작동하기 때문에, 해시 값을 다시 원래의 문자열로 변환하는 것은 불가능하다.

 

적구현 - 핵심내용

1. FindGameObjectWithTag

  • FindGameObjectWithTag"는 지정된 태그와 일치하는 첫 번째 활성 GameObject를 반환합니다. 이 메서드는 특정 태그를 가진 오브젝트를 빠르게 찾을 수 있도록 돕는다.
  • 태그를 사용하면 씬 내에서 특정 유형의 오브젝트를 쉽게 찾을 수 있으며, 코드에서 게임 오브젝트를 참조할 때 유용함
  • 그러나 "FindGameObjectWithTag"는 매우 비싼 연산. 즉, 이 메서드를 사용하면 CPU를 많이 사용하게 된다. 따라서 이 메서드를 매 프레임마다 호출하면 게임 성능에 심각한 영향을 미칠 수 있다.
  • 따라서 일반적으로는 이 메서드를 Start나 Awake와 같은 초기화 메서드에서 한 번만 호출하는 것이 권장. 오브젝트를 찾은 후에는 참조를 저장하고 나중에 재사용
  • 게임 오브젝트가 많은 큰 씬에서는 태그 대신 레이어나 다른 메서드를 사용하는 것이 더 효율적일 수 있다.

2. Physics.Raycast 또는 Physics2D.Raycast

  • Raycasting은 일련의 콜라이더와 교차하는지를 감지하는 데 사용되는 기술. 이는 레이저 포인터나 총알을 쏘는 효과를 만들거나, 플레이어의 시야를 계산하는 등 다양한 방식으로 사용
  • Unity에서는 Physics.Raycast 또는 **Physics2D.Raycast**를 사용하여 Raycast를 수행할 수 있다. 이들 메서드는 시작점, 방향, 최대 거리, 그리고 선택적으로 레이어 마스크를 매개변수로 받는다.
  • Raycast는 hit 정보를 반환. 이 정보에는 충돌한 객체, 충돌 지점, 충돌 지점의 정규화된 벡터 등이 포함.
  • Raycast는 충돌 검사에 비해 계산 비용이 많이 든다. 따라서 불필요한 Raycast를 줄이고, 가능한 경우 레이어 마스크를 사용하여 검사 범위를 제한하는 것이 성능에 좋다.
  • Raycast는 비주얼 디버깅을 위해 **Debug.DrawRay**와 함께 사용할 수 있다. 이를 통해 Scene 뷰에서 Raycast의 경로를 시각적으로 확인할 수 있다.

 

파티클 생성 - 핵심내용

1. 파티클 시스템(Particle System)

  • 파티클 시스템은 수 천개의 작은 2D 또는 3D 오브젝트들을 관리하고, 그들의 동작과 생애를 제어. 각각의 작은 오브젝트를 '파티클'이라고 부른다.
  • 파티클 시스템의 주요 컴포넌트는 'emitter'(발사체), 'particles'(파티클), 'animator'(애니메이터), 'renderer'(렌더러) 등으로 이루어져 있다.
  • Unity의 파티클 시스템은 시간에 따른 파티클의 행동을 시뮬레이션하며, 이를 위해 각 파티클에 대해 위치, 속도, 수명, 색상, 크기 등의 정보를 저장
  • 파티클 시스템은 성능 최적화를 위해 다양한 기능을 제공. 예를 들어, 시스템의 최대 파티클 수를 제한하거나, 파티클의 적용 범위를 제한하는 등의 기능이 있다.

2. 에니메이션 이벤트(Animation Events)

  • 에니메이션 이벤트를 사용하면 애니메이션이 진행되는 동안 코드를 실행시킬 수 있다. 예를 들어, 캐릭터가 특정 동작을 할 때 사운드를 재생하거나, 특정 애니메이션 프레임에서 파티클 시스템을 발사하는 등의 작업을 할 수 있다.
  • 에니메이션 이벤트는 Unity 애니메이션 편집기에서 설정할 수 있다. 편집기를 통해 애니메이션 타임라인에 이벤트를 추가하고, 해당 이벤트가 호출할 함수를 지정할 수 있다.
  • 에니메이션 이벤트는 해당 애니메이션 클립이 재생되는 게임 오브젝트에 연결된 모든 스크립트에서 호출할 수 있는 함수를 실행할 수 있다.
  • 이벤트는 특정 프레임에서만 실행되며, 애니메이션 상태가 변경될 때에도 자동으로 실행되지 않는다.
  • 에니메이션 이벤트를 사용하면 애니메이션과 코드의 상호작용을 더욱 유연하게 관리할 수 있다. 이를 통해 애니메이션의 시각적 효과와 사운드, 효과 등의 프로그래밍적 요소를 조화롭게 통합할 수 있다.
  • 에니메이션 이벤트를 통해 호출되는 함수는 일반적으로 공용 함수(public function)이어야 하며, 매개변수가 없거나 최대 하나의 매개변수를 가질 수 있다.

 

'TIL' 카테고리의 다른 글

12.15 (TIL-Unity3D)  (0) 2023.12.15
12.14 (TIL - Unity)  (0) 2023.12.14
12.12 (TIL-Unity)  (0) 2023.12.12
12.11 (TIL-Unity)  (0) 2023.12.11
12.08 (TIL-코딩문제)  (1) 2023.12.08