다른 cs 파일의 클래스 호출과 static 로직에 대하여
로딩 씬(Loading Scene) 구현하기 글에 달아주신 ㅇㅇ님의 질문 댓글에 대한 답변입니다. 질문의 내용은 아래와 같습니다.
로딩 씬 구현하기 글을 보면 LoadingSceneManager 클래스는 아래와 같이 구현되어 있습니다.
LoadingSceneManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LoadingSceneManager : MonoBehaviour
{
public static string nextScene;
[SerializeField]
Image progressBar;
private void Start()
{
StartCoroutine(LoadScene());
}
public static void LoadScene(string sceneName)
{
nextScene = sceneName;
SceneManager.LoadScene("LoadingScene");
}
IEnumerator LoadScene()
{
yield return null;
AsyncOperation op = SceneManager.LoadSceneAsync(nextScene);
op.allowSceneActivation = false;
float timer = 0.0f;
while (!op.isDone)
{
yield return null;
timer += Time.deltaTime;
if (op.progress >= 0.9f)
{
progressBar.fillAmount = Mathf.Lerp(progressBar.fillAmount, 1f, timer);
if (progressBar.fillAmount == 1.0f)
op.allowSceneActivation = true;
}
else
{
progressBar.fillAmount = Mathf.Lerp(progressBar.fillAmount, op.progress, timer);
if (progressBar.fillAmount >= op.progress)
{
timer = 0f;
}
}
}
}
}
첫 번째 질문에서의 LoadingSceneManager.LoadScene("Scene2");를 호출하는 클래스는 아래와 같이 구현되어 있었습니다.
TestCode.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestCode : MonoBehaviour
{
// Use this for initialization
void Start ()
{
LoadingSceneManager.LoadScene("Scene2");
}
}
다른 cs 파일의 클래스 호출
우선 첫 번째로 LoadingSceneManager.cs 파일에 구현된 LoadingSceneManager 클래스를 어떻게 TestCode.cs 파일로 다른 선언 없이 바로 호출할 수 있었느냐라는 의도로 질문하신 것 같습니다. 어떻게 다른 cs 파일에 정의된 클래스를 바로 호출할 수 있었냐는 질문을 하신 걸로 보아, ㅇㅇ님께서는 아마 유니티를 배우시기 이전에 C/C++과 같이 다른 소스 파일의 코드를 불러오기 위해서는 별도의 include 등의 전처리가 필요한 언어를 배우신게 아닌가 싶습니다.
그런 C/C++에서는 다른 소스 파일의 클래스를 불러와서 사용하기 위해서는 아래의 예시와 같이 전처리기에서 사용하고자 하는 클래스가 담긴 헤더를 포함시켜주어야 합니다.
LoadingSceneManager.h
#include <string>
#pragma once
class LoadingSceneManager
{
public:
static void LoadingScene(std::string sceneName)
{
// 씬 로딩 처리 ...
}
};
TestCode.h
#include "LoadingSceneManager.h" // C/C++에서는 이렇게 호출하고자 하는 클래스가 담긴 헤더를 호출해주어야 한다.
#pragma once
class TestCode
{
public:
void Start()
{
LoadingSceneManager::LoadingScene("Scene2");
}
};
하지만 C#에서는 헤더 파일이 따로 존재하지 않고 cs파일만 존재하며, 같은 프로젝트 안에 있는 cs파일이라면, 다른 cs 파일 안에 정의된 클래스를 가져와서 사용할 수 있다는 뜻입니다.
정적 함수(Static Function)
두 번째 질문으로는 static으로 선언된 LoadScene() 함수가 LoadSceneManager 오브젝트가 없는 다른 씬에서 어떻게 호출될 수 있는가 입니다.
로딩 씬 구현하기 글에서 구현한 방식을 그림으로 표현하면 위의 이미지와 같습니다. 씬은 Scene1, LoadingScene, Scene2가 존재하고 TestCode 클래스의 인스턴스는 Scene1에서만 존재하고 LoadSceneManager 클래스의 인스턴스는 LoadingScene에서만 존재합니다. 그런데 Scene1에서 LoadScene에만 존재하는 LoadSceneManager의 함수를 호출할 수 있느냐가 메인인데, 이 부분은 정적 함수(static function)에 대한 기본적인 이해가 필요합니다.
public static void LoadScene(string sceneName)
{
nextScene = sceneName;
SceneManager.LoadScene("LoadingScene");}
코드를 다시 보면 아시겠지만, LoadSceneManager 클래스의 LoadScene(string) 함수는 static으로 선언되어 있습니다. 이렇게 static으로 선언된 함수를 정적 함수라고 하며, 이러한 정적 함수는 클래스의 인스턴스가 생성되지 않았더라도 컴파일 시점에 전역에 할당되어 있습니다. 그렇기 때문에 TestCode.cs에서와 같이 해당 클래스의 이름을 통해서 곧바로 접근이 가능해집니다.
다시 한번 풀어서 이야기하자면, TestCode.cs가 실행되는 때에는 LoadSceneManager 클래스의 인스턴스가 생성되어 있지 않지만, 전역에 할당되어 있는 LoadSceneManager 클래스의 전역 함수에 접근하여 정적 변수(이것 역시 전역에 할당되어 모든 LoadSceneManager 클래스의 인스턴스들이 공유한다.)인 nextSceneName에 다음으로 넘어갈 씬 이름을 전달하고 LoadingScene을 불러옵니다.
LoadingScene이 전부 불러와지면 LoadSceneManager 클래스의 인스턴스가 생성되고, LoadSceneManager의 Start() 함수가 실행되면서 LoadScene 코루틴을 호출하는 순서로 동작합니다.
PS.
로딩 씬 구현하기 글은 2017년에 작성한 오래 전 글이라 내용이 많이 불친절한 편입니다. 기본적인 내용은 많이 바뀌지 않겠지만, 유니티 버전이 많이 바뀌면서 좀 더 알아보기 쉽게 새로 작성할 계획은 오래 전부터 세워둔 상태였는데, 이래저래 시간을 보내면서 아직까지 작성하지 못했습니다. 최대한 이른 시일 내로 새로운 버전으로 작성해보도록 하겠습니다.
[유니티 어필리에이트 프로그램]
아래의 링크를 통해 에셋을 구매하시거나 유니티를 구독하시면 수익의 일부가 베르에게 수수료로 지급되어 채널의 운영에 도움이 됩니다.
[투네이션]
[Patreon]
[디스코드 채널]
'Q&A' 카테고리의 다른 글
[Q&A/Unity3D] 싱글플레이 게임을 멀티플레이 게임으로 발전시켰을 때 적 AI가 플레이어를 인식하지 못하는 문제 (0) | 2019.08.19 |
---|---|
[Q&A/Unity3D] 일반 클래스 내부에 MonoBehaviour 상속 클래스 멤버 변수 저장하기 (0) | 2019.07.22 |