[Unity] 20. ResourcesManager

치치·2025년 3월 24일
0

Unity

목록 보기
22/27
post-thumbnail

오늘 배운 구현

  • 타이머 (분 : 초 : 밀리초)
  • 장애물 생성 시 Resources폴더에서 가져와서 동적 생성하는데, 이 방법 대신에 Resources폴더에서 가져와서 생성을 담당하는 ResourcesManager 만들기
  • 캐릭터가 장애물에 닿으면 Die 애니메이션이 실행되고, GameManagerFinish() 함수 호출
    Finish가 호출되면 스위치가 OFF 되어 state = false
    → 스테이지 실행에 연관되어 있는 스크립트들 모두 중지 (도로매니저, 장애물 매니저, 캐릭터 이동)


타이머 (Watch 전체 코드)

update()로 타이머를 구현하는 대신 코루틴을 사용한다

해당 스크립트가 부착된 Text 컴포넌트의 프로퍼티 text가 함수 호출되고 매 프레임마다 변경된다

타이머도, GameManagerbool 변수가 true여야 실행된다


코드 설명

  • Time.deltatime = 자료형 float
  • time 변수는 현재(전체) 시간을 나타내며 '초'로 나타낸다
  1. minute : 60초로 나눈 몫
  2. second : 60초로 나눈 나머지 중 정수부분 (int)
  3. milseconds : (현재 시간초 * 100) % 100
    -> 소수점 2자리가 출력

string.Format ( { }, --- );

문자열 안에 변수를 삽입하거나, 특정 형식으로 값을 출력할 수 있도록 해주는 메서드

"{몇번째 인지 : 자료형 타입 문자열 자리 수}"

ex) 정수 포멧 & 실수 포멧

int integer = 10;
float floating = 1.23;

text = string.Format({0 : D2} : { 1 : F2 } , integer, floating);

Debug.Log(text);

-> 결과값 : 10 : 1.23

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Watch : MonoBehaviour
{
    [SerializeField] Text textTime;

    [SerializeField] float time;

    [SerializeField] int minute;
    [SerializeField] int second;
    [SerializeField] int milseconds;


    private void Awake()
    {
        textTime = GetComponent<Text>();
        
    }
    
    void Start()
    { 
        StartCoroutine(Measure());
    }

    IEnumerator Measure()
    {
        while (GameManager.Instance.State)
        {
            time += Time.deltaTime;

            minute = (int)time / 60;
            second = (int)time % 60;
            milseconds = (int)(time * 100) % 100;

            textTime.text = string.Format("{0:D2} : {1:D2} : {2:D2}", minute, second, milseconds);

            yield return null; 
        }

    } 

}


ResourcesManager

제네릭을 사용하여 T Resources.Load<T>(path)를 간단하게 바꿔보자


랩핑을 사용하여 Instantiate 메서드를 재정의 해보자

랩핑 (Wrapping)

기존 클래스나 객체, 기능을 새로운 방식으로 재 포장하는 방법
기존 유니티에서 제공하는 함수를 우리가 원하는 방식으로 재포장한다

1. T Load<T>(string path) 를 제네릭으로 선언

호출하면 Resources.Load<T>(path);가 반환된다
-> Resources 폴더내의 path에 해당하는 게임 오브젝트가 반환된다

✅ 왜 제네릭으로 정의해야할까

매번 Resources 폴더에서 호출하는 Resources.Load<T>(string path)를 줄이기 위해

제네릭을 사용하면 Load<T>()입력만 하면 바로 Resources 폴더에서 해당값이 반환된다


2. 랩핑을 사용한 Instantiate 함수

Instantiate는 이미 유니티에서 제공하는 메서드이다

Load<T> 에서 반환된 게임 오브젝트를 prefab 참조변수로 참조한다

동적으로 생성한 게임 오브젝트를 clone 참조변수에 담기

  • 게임 오브젝트 타입인 clone을 반환한다


랩핑 Instantiate를 사용하기

  • 기존 코드

  • 랩핑을 사용한 Instantiate


랩핑을 사용하는 이유

동일한 기능을 하는 함수에서 새로운 기능을 추가하여 사용하기 위함



ResourcesManager 전체코드

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

public class ResourcesManager : Singleton<ResourcesManager>
{   

    // 제네릭 타입
    public T Load<T>(string path) where T : Object
    {
        return Resources.Load<T>(path);
    }

    // Instantiate 랩핑
    public GameObject Instantiate(string path, Transform parent = null)
    {
        GameObject prefab = Load<GameObject>(path);

        if(prefab == null)
        {
            Debug.Log("Failed to Load Prefab : " + path);
            return null;
        }

        // Object는 생략가능
        // 생성된 prefab 객체를 반환하기 위해서 참조변수 clone에 담기
        GameObject clone = Object.Instantiate(prefab, parent);

        // 읽기전용이라 대입해야된다
        clone.name = clone.name.Replace("(Clone)", "");

        return clone;
    }
}


스테이지 클리어 실패 호출 (Runner 스크립트)

  1. 충돌한 otherObstacle 컴포넌트가 없다면
    참조 변수 obstaclenull값을 가지기 때문에 아래의 조건문을 시행x
    -> 즉, 장애물이라면 Obstacle 스크립트가 붙어있기 때문에 실행

  2. Runner 스크립트에서 만약 장애물과 충돌한다면 Die 애니메이션을 즉각 실행하기
    -> animator.Play("애니메이션 클립 이름");

  3. GameManagerFinish()함수 호출

  4. Finish가 호출되면 스위치가 OFF 되어 state = false
    스테이지 실행에 연관되어 있는 스크립트들 모두 중지 (도로매니저, 장애물 매니저, 캐릭터 이동)

profile
뉴비 개발자

0개의 댓글