다른 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년에 작성한 오래 전 글이라 내용이 많이 불친절한 편입니다. 기본적인 내용은 많이 바뀌지 않겠지만, 유니티 버전이 많이 바뀌면서 좀 더 알아보기 쉽게 새로 작성할 계획은 오래 전부터 세워둔 상태였는데, 이래저래 시간을 보내면서 아직까지 작성하지 못했습니다. 최대한 이른 시일 내로 새로운 버전으로 작성해보도록 하겠습니다.

반응형
  1. 료용 2019.12.26 02:02

    닉네임도 ㅇㅇ이라는 싸가지없는 닉으로 해놨는데 답변해주셔서감사합니다.

싱글플레이 게임을 멀티플레이 게임으로 


발전시켰을 때 적 AI가 플레이어를 


인식하지 못하는 문제


UNet Tutorial (13) - 네트워크 애니메이터(Network Animator) 글에 달아주신 myouzing님의 질문 댓글에 대한 답변입니다. 질문의 내용은 다음과 같습니다.


 

질문의 내용으로는 싱글플레이 FPS 게임을 만드시다가, UNet을 이용해서 그 게임을 멀티플레이로 발전시켰을 때, 적 AI가 플레이어를 인식하지 못하는 것으로 보입니다. 


질문 댓글의 내용이 간략하고 자세한 정황과 멀티플레이 설계가 어떻게 되어있는지 알 수 없기 때문에 완전한 해결책은 알려드리기 어려울 것 같습니다. 하지만 증상을 미루어보아 짐작했을 때, 의심이되는 상황이 있습니다.


의심이 되는 부분은 서버와 클라이언트에서 양 측에 적 AI 오브젝트와 플레이어 오브젝트가 둘 다 정상적으로 네트워크 오브젝트로서 생성되어 있는가 하는 부분입니다. 예를 들어 서버와 클라이언트에 적 AI가 생성되어 동기화 되고 있는데 플레이어 오브젝트가 클라이언트에서만 생성되서 서버에서는 생성되지 않은 경우라면, 클라이언트의 플레이어가 적 AI에게 다가가도 서버 측의 적 AI가 보았을 때는 주변에 아무도 없기 때문에 플레이어를 인식하지 못하는 경우가 발생할 수 있습니다.


그 외에도 기본적인 문제로 신텍스 에러가 발생하지 않더라도 플레이하는 도중에 Null Reference나 Missing Reference 같은 오류가 발생한다면 코드가 진행하다가 멈추기 때문에 로그를 잘 확인해보셔야 할 것 같습니다.

반응형

+ Recent posts