SceneManager.GetActiveScene()

현재 활성화 되어있는 Scene을 반환한다.

 

SceneManager.GetActiveScene().name

> 활성화 된 Scene중 이름 반환

 

SceneManager.GetActiveScene().buildIndex

> 활성화 된 Scene중 인덱스 반환


AddListener

버튼의 경우 인스펙터 창에서 수동으로 할당 후 함수를 추가하는 방법이 있는데

메서드 이름이 바뀔경우 다시 추가해야 하는 불편함이 있다.

그럴경우 스크립트를 통해 AddListener 메서드를 사용하여 버튼 연결이 가능하다.

 

 private Button Restart;
 
    private void Start()
    {
        Restart = gameOverPanel.GetComponentInChildren<Button>();
        Restart.onClick.AddListener(GameRetry);
    }
    
    private void GameRetry()
    {
        Debug.Log("게임 재시작");
    }

 

게임오브젝트에 버튼이 달려있는 컴포넌트를 가져오고

onclick 이벤트를 통해 실행할 메서드를 지정해준다. 

 

인자값이 있는 경우 람다, delegate를 쓴다.

private void Start()
{
    Restart = gameOverPanel.GetComponentInChildren<Button>();
    Restart.onClick.AddListener(() => GameRetry());
}

 

'Unity' 카테고리의 다른 글

월드좌표, 로컬좌표  (0) 2025.04.24
리소스 데이터 관리(제네릭 T, TryGetValue, TryAdd)  (0) 2025.04.08
플레이어까지 거리(벡터) 구하기  (0) 2025.03.19
[Resource.Load]  (0) 2024.11.13
[코루틴 사용법]  (3) 2024.11.06
private void Shoot(GameObject bulletPrefab, Vector3 position, Quaternion rotation)
{
    GameObject bullet = Instantiate(bulletPrefab, position, rotation);
    Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
    Vector3 direction = _enemy.player.transform.position - transform.position;
    rb.velocity = direction.normalized * bulletSpeed;
}

 

특정 거리를 구하려면 벡터를 이용하면 된다.

벡터 연산 공식을 빌려 A에서 B까지 방향과 거리는 B-A다.


이것을 계산하면 현재 지점에서 도착 지점까지 방향과 거리가 나온다.

 

여기서 direction = _enemy.player.transform.position - transform.position은

적 기준 플레이어까지 거리(벡터)를 표현한 것

 

 플레이어가 멀리 있을수록 벡터 크기가 커진다.

 

따라서 direction * bulletSpeed 를 하면 거리(벡터 크기)에 따라 속도가 달라진다.

즉, 가까이 있을수록 속도는 낮고 멀리 있을수록 속도는 커진다.

일정하지 않는 속도는 사용자 입장에서 예측하기 어려운 요소

 

해결방법

normalized를 사용하자

이유방향을 유지하면서 속도를 일정하게 만들기 위해서다

벡터를 정규화 하여 크기가 1인 벡터, 방향 벡터를  만들면

항상 동일한 속도로 플레이가 가능해진다. 

 

 

 

'Unity' 카테고리의 다른 글

리소스 데이터 관리(제네릭 T, TryGetValue, TryAdd)  (0) 2025.04.08
SceneManager.GetActiveScene, AddListener  (0) 2025.03.21
[Resource.Load]  (0) 2024.11.13
[코루틴 사용법]  (3) 2024.11.06
[activeSelf]  (1) 2024.11.05

오브젝트 풀링을 사용하는 이유

Instantiate, Destory를 반복하면서 조각난 메모리가 쌓인다.

 

이러한 조각난 메모리를 해결하기 위해서 가비지 컬렉터(GC)가 실행된다.

 

가비지컬렉터 (garbage collector)

1) 메모리 관리를 담당하는 시스템

2) 메모리에서 더 이상 사용하지 않는 객체를 제거하여 메모리 회수하는 기능이 있다.

 

이 가비지 컬렉터가 실행되면서 게임에 버벅임이 발생하는데

메모리가 많을경우 많은 끊김 현상이 발생한다.

 

이러한 것을 방지하기 위한 최적화 기법이 오브젝트 풀링이다.

 

오브젝트 풀링

오브젝트 풀링은 게임 오브젝트를 생성 또는 파괴하지 않는다.

필요한 만큼 미리 생성해두고, 비활성화

파괴(Destroy) 대신 오브젝트를 비 활성화하여 풀에 추가

생성(Instantiate) 대신 풀에서 꺼낸 뒤 활성화한다.

더보기
public class ObjectManager : MonoBehaviour
{
    // 풀에 대한 정보를 담는 구조체 정의
    // 프리팹, 크기, 풀에 대한 키 값을 저장
    [System.Serializable]
    public class Pool
    {
        public string key; // 오브젝트 풀의 고유 이름 (예: "Enemy", "Bullet")
        public GameObject prefab; // 생성할 오브젝트의 프리팹
        public int size; // 풀에 생성할 오브젝트의 개수
    }

    // 여러 풀을 관리하는 리스트 (Inspector에서 설정)
    public List<Pool> poolList;

    // 각 풀을 이름별로 관리하는 딕셔너리
    // key: 풀의 이름 (key), value: 해당 이름에 맞는 오브젝트 큐(Queue)
    private Dictionary<string, Queue<GameObject>> PoolDictionary = new Dictionary<string, Queue<GameObject>>();

    
    private void Awake()
    {
        // poolList에 저장된 풀 정보를 이용하여 각각의 풀을 초기화
        foreach (var pool in poolList)
        {
            Queue<GameObject> queue = new Queue<GameObject>(); // 큐를 생성하여 오브젝트들을 담을 준비

            // 풀 크기만큼 오브젝트를 생성하고 큐에 비활성화된 상태로 넣음
            for (int i = 0; i < pool.size; i++)
            {
                GameObject obj = Instantiate(pool.prefab);
                obj.SetActive(false);
                queue.Enqueue(obj); 
            }

            // 생성한 큐를 PoolDictionary에 추가 (key는 pool.key)
            PoolDictionary.Add(pool.key, queue);
        }
    }

    // 오브젝트 풀에서 비활성화된 오브젝트를 꺼내 활성화하고 반환
    public GameObject GetObject(string key)
    {
        // 해당 key에 해당하는 큐가 존재하고, 큐에 오브젝트가 있다면
        if (PoolDictionary.ContainsKey(key) && PoolDictionary[key].Count > 0)
        {
            // 큐에서 오브젝트를 하나 꺼냄 (FIFO)
            GameObject obj = PoolDictionary[key].Dequeue();
            obj.SetActive(true); // 꺼낸 오브젝트를 활성화
            return obj; // 꺼낸 오브젝트 반환
        }

        // 오브젝트가 없으면 null 반환
        return null;
    }

    // 오브젝트를 풀에 다시 반환 (비활성화 후 큐에 넣기)
    public void ReturnObject(string key, GameObject obj)
    {
        // 해당 key에 대한 큐가 존재하는지 확인
        if (!PoolDictionary.ContainsKey(key)) return;

        // 오브젝트를 비활성화하고 다시 큐에 넣어 재사용할 수 있게 함
        obj.SetActive(false);
        PoolDictionary[key].Enqueue(obj);
    }
}



 

인스펙터창에 해당하는 프리팹과 타입, 개수를 할당해준다.

'Unity > 디자인 패턴' 카테고리의 다른 글

싱글톤 패턴  (0) 2025.05.02

유니티 프리팹을 instantiate 하는 방법은

 

퍼블릭으로 게임오브젝트를 선언한뒤 

 

instantiate 해주고 프리팹을 드래그 앤 드랍하는 방법이 있다.

 

하지만 프리팹을 드래그 앤 드랍 하지 않고도 사용할 수 있는 방법이 있는데

 

바로 Resource.Load 함수를 사용하는 것이다.

 

Resource.Load<가져올 타입>("경로");

 


이 함수를 사용하려면 Resources 폴더를 생성하는 과정이 선행되어야 한다.  

Resources
   Prefabs
      file

 

이런식으로 Resources 폴더를 만들고 계층구조 최상위에 위치 시켜야 한다.

 

위 사진처럼 게임오브젝트 타입이고, Prefabs에 있는 file 프리팹을 로드해야한다면

 

Private void Start()
{
   GameObject obj = Resource.Load<GameObject>("Prefabs/file");
}

 

이런식으로 작성하면 된다.

 

그외 추가적으로 typeof와 asgameobject를 사용하는 방법도 있다.

 

Resources.Load("경로", typeOf(GameObject)) as GameObject

 

유니티에서 추천하는 방법은 첫번째 방법이다. 일단 보기에도 간결하니 가독성이 좋다.

'Unity' 카테고리의 다른 글

SceneManager.GetActiveScene, AddListener  (0) 2025.03.21
플레이어까지 거리(벡터) 구하기  (0) 2025.03.19
[코루틴 사용법]  (3) 2024.11.06
[activeSelf]  (1) 2024.11.05
[모듈러 연산, Event]  (0) 2024.10.24

왜 코루틴을 사용하는가?

코루틴은 특정 코드를 내가 원할때 사용을 할 수 있는 함수다.

Update()에서는 매 프레임마다 호출을 하기에 자원낭비가 심하지만

코루틴을 사용하면 내가 원하는 순간에 호출을 할 수 있어 자원 낭비를 막을 수 있어 효율적이다.

 

코루틴 실행방법

코루틴 실행은 StartCoroutine() 함수를 사용하여 실행이 가능하다.

실행이 가능한 방법은 2가지인데

StartCoroutine(TestCoroutine()); 처럼 함수를 호출하거나

StartCoroutine("TestCoroutine"); 처럼 문자로 호출할 수 있다.

 

다만, StartCoroutine("TestCoroutine");처럼 상수 형태의 문자열은 추천되지 않는데

문자열인 만큼 오타 발생 가능성이 존재하며 이 경우 코루틴 함수가 실행되지 않는 위험이 존재한다.

 

 

코루틴 정지방법

코루틴 정지는 StopCoroutine() 함수를 사용하여 실행이 가능하다.

정지가 가능한 방법은 시작방법과 비슷한 함수를 사용한다.

StopCoroutine(TestCoroutine()); 처럼 함수를 호출하거나

StopCoroutine("TestCoroutine"); 처럼 문자로 호출할 수 있다.

 

코루틴을 정지시키는 함수로  StopAllCoroutines()도 있는데 이 함수는 특정 코루틴이 아닌

스크립트 내 작성된 모든 코루틴을 정지시키므로 특정 코루틴은 실행해야 하는 경우

사용에 주의가 요구된다.

StopAllCoroutines();을 사용하면 TestCoroutine(), TestCoroutine1()

스크립트 내 2개의 코루틴 함수가 모두 종료된다.

StopAllCoroutines()은 함수 특성 상  StartCoroutine(), StopCoroutine()과 달리

함수를 호출하거나 문자로 호출하여 특정 코루틴을 정지시킬 수 없다.

 

코루틴 선언하기

코루틴은 반환타입 IEnumerator인 함수로써 IEnumerator를 반환한 코루틴은

yield키워드를 반드시 사용하여 retrun 해야한다.

 

코루틴을 사용하기 위해서는 System.Collections 네임스페이스를 사용해야한다.

 

이와 같은 특징으로 봤을때 코루틴은 아래 코드와 같은 형태를 가진다.

 

여기서 yield return 다음에 조건 null이 붙었는데

yield return null은 Update()가 함수가 호출되기전까지

실행을 유예하고 끝나면 다음 프레임에 실행된다.

 

여기서 사용되는 yield 키워드는 영어 뜻 그대로 양보하는 코루틴의 특성을 가지고 있으며

yield return 다음에 조건식에 따라 코루틴 함수에 대한 특성이 달라진다.

 

[yield return + 조건식] 의 종류

(자주 사용하는 함수 파란색)

1) yield return null :  업데이트가 끝나고 다음 프레임까지 대기 후 실행 됨.

2) yield return new WaitForEndOfFrame() : 한 프레임워크가 완전히 종료된 후 실행된다.

3) yield return new WaitForFixedUpdate() : FixedUpdate()가 끝나면 실행된다.

4) yield return new WaitForSeconds(float)  :  실수형 상수에 입력된 시간(초)이 경과하면 실행된다.

5) yield return new WaitForSecondsRealtime(float)  :  new WaitForSeconds(float)와 동일하지만

Time.timeScale의 영향을 받지 않는다.

6) yield break : 사용한 시점에 코루틴이 정지된다.

 

마무리

코루틴은 내가 원하는 순간에 호출을 할 수 있어

Update처럼 매 프레임 원하지 않을때 실행되지 않으므로 자원 낭비를 막을 수 있어 효율적이다.

실무에서 빈번하게 사용된다고 하니 알아두면 좋을 것 같다.

 

'Unity' 카테고리의 다른 글

플레이어까지 거리(벡터) 구하기  (0) 2025.03.19
[Resource.Load]  (0) 2024.11.13
[activeSelf]  (1) 2024.11.05
[모듈러 연산, Event]  (0) 2024.10.24
241023(수) [Skybox, Raycast]  (1) 2024.10.23

+ Recent posts