본문 바로가기

이론(면접)

Framework

//유틸리티 상수
public static partial class ADefine
{
	#region 씬 관리자
    
    public static readonly string NAME_UI_CAMERA = "UI Camera";
    public static readonly string NAME_MAIN_CAMERA = "Main Camera";
    
    public static readonly string NAME_UI_ROOT = "Canvas";
    public static readonly string NAME_OBJECT_ROOT = "ObjectRoot";
    public static readonly string NAME_SCENE_MANAGER = "SceneManager";
    
    public static readonly float DEFAULT_PLANE_DISTANCE = 5.0f;
    
    #end region

}

1. 확장성

2. 사용 편리

3. 은닉성(Monobehaviour을 잘 숨겨야 함. 메모리 관리를 위함)

 

 

partial: partial 키워드는 클래스, 구조체, 인터페이스 키워드 바로 앞에 위치시키며 2개 이상의 파일에 걸쳐 Type를 나눌 수 있게 된다.

 

-partial Class는 C# 2.0에 도입된 기능으로, 클래스를 여러 파일에 나눠서 정의할 수 있다.

- 여기서 사용되고 있는 KDefine는 논리적으로 1개의 클래스이다.

  => 컴파일될 때 병합시키기 때문.

 

 

 

// 1. 유틸리티 함수

public static partial class KDefine
{
	//readonly: 상수화
    
    const vs readonly
    const: 초기화 이후 값을 변경할 수 없음. 선언하는 시점에만 초기화 가능(컴파일 타임 상수)
    readonly: 초기화 이후 값을 변경할 수 없다. 선언하는 시점과 생성자에서 초기화(1번). 런타임 상수
    
	EX) 게임을 실행시키면 일단 한얓ㅎ 번 초기 해상도로 실행을 시키고 유저가 본인의 사양에 맞는 해상도를 설정하면 해상도를 상수화시켜버리는 행위 등에 자주 사용된다.
    해상도 자체는 한 번 설정이 되면 잘 안바뀌는 옵션
    
    //컴파일 타임 항수는 변수가 실제 값으로 대체가 되고 런타입 상수는 변수 참조형식이기 때문에 성능과 속도를 고려하면 const가 더 우수
    단 인스턴스마다 다른 값을 할당시키고 싶거나 사용자 정의 타입이라면 readonly를 사용하면 됨
	애초에 사용자 정의 타입은 const 안먹힌다.    

	//해상도
    public static readonly int SCREEN_WIDTH = 1280;
    public static readonly int SCREEN_HEIGHT = 720;
    
	public static readonly float UNIT_SCALE = 0.01f;
	//
    
    
}

 

 

 

//전역 메서드
/////////////////////////

//전역 함수
public static partial class Function
{
//게임 객체를 생성한다
	public static GameObject CreatObject(string, a_oName, GameObject.a_oParent, boolbIsStayWorldState = false);
	
    
    //SetParent의 월드 속성 유지 매개 변수가 true로 설정되면 월드 상에 존재했을 떄의 속성을
    그대로 유지하기 때문에 특정 객체의 하위에 종속이 될 경우 부모 객체의 크기에 따라 자식 객체 크기 값의
    변화가 발생한다.
    
    
	var oGameObject = new GameObject(a_oName);
    oGameobject.transform.SetParent(a+oParent?.transform, a_bIsStayWorld);
    
    return GameObejct;

	//1. 컴포넌트를 탐색한다.
    public static T FindComponent<T>(string a) where T : Component
    {
    	var GameObject = Gameobject.Find(a_oName);
        return oGamObject?.GetComponentChildrne<T>();
    }
    
    //1. 컴포넌트를 추가한다.
    public static T AddComponent<T>(GameObject a_oGameObject) where T : Component
    {
    	var oComponent = a_oGameObject.Getcomponent<T>();
        if(oComponent == null
		{
        oComponent = a_oGameObject.AddComponent<T>();
        }
        return oComponent;
    }
        
        
    //1. 비동기 작업을 대기한다.
    public static IEnumerator WaitAsyncOperation(AsyncOperation a_oAsyncOperation,
    System.Action<AsyncOperation> a_oCallBack)
    {
    	while(!a_oAsyncOperation.isDone)
        {
        	yield return new WaitForEndOfframe();
            a_oCallBack?.Invoke(a_oAsyncOperation);
        }
    }
    
	//! 함수를 지연 호출한다.
	private static IEnumerator DoLateCall(System.Action<object[]> a_oCallBack,
    float a_fDelay, object[] a_oParams)
    {
    	yield return new WaitForSeconds(a_fDelay);
        a_oCallBack?.Invoke(a_oParams);
    }
}

 

 

public class CSceneLoader : CSingleton<CSceneLoader>
{


//!씬을 변경한다
    public void LoadScene(int a_nIndex)
    {
    //GetScenePathByBuildIndex
    //SceneList의 빌드 인덱스가 가진 씬을 리스트로 담을 수 있다.
    //빌드 인덱스: 빌드 설정 창에 지정된 씬 목록에 대한 인덱스
    	string oScenePath = SceneUtility.GetScenePathByBuildIndex(a_nIndex);
        this.LoadScene(oScenePath);
    }
    
    
//!씬을 변경한다.
    public void LoadScene(string a_oName)
    {
     	SceneManager.LoadScene(a_oName, LoadSceneMode.Single); 
    }


//!씬을 로드한다.
    public void LoadScene(int a_nIndex, LoadSceneMode a_eLoadSceneMode = LoadSceneMode.Single)
    {
    /*
    
    LoadSceneMode.Single : 디폴트 값
    - 현재 씬의 오브젝트를 모두 Destroy하고 새롭게 씬을 로드.
    
    LoadSceneMode.Additive
    - 현재 씬에 새로운 씬을 추가적으로 덧대어 불러오겠다.
    
    */
    }
    
    //!씬을 로드한다.
  	public void LoadScene(string a_oName, LoadSceneMode a_eLoadSceneMode = LoadSceneMode.Single)
    {
        SceneManager.LoadScene(a_oName, a_eLoadSceneMode);
    }
    
    
    
    
    //! 씬을 로드한다
    publci void LoadSceneAsync(int a_nIndex,1System.Action<AsyncOperation> a_oCallback,
    float a_fDelay = 0,LoadSceneMode a_eLoadSceneMode = LoadSceneMode.Single)
    {
    
        string oScenePath = SceneUtility.GetScenePathByBuildIndex(a_nIndex);
        this.LoadSceneAsync(oScenePath, a_oCallBack, a_fDelay, a_eLoadSceneMode);
    
    }
    
    
        public void LoadSceneAsync(string a_oName,
    1System.Action<AsyncOperation> a_oCallback, float a_fDelay = 0,
    LoadSceneMode a_eLoadSceneMode = LoadSceneMode.Single;
    {
    
    StartCoroutine(this.DoLoadSceneAsynd(a_oName, a_oCallBack, a_fDelay, a_eLoadSceneMode));
    
    }
    
    
      private IEnumerator DoLoadSceneAsync(string a_oName)
    1System.Action<AsyncOperation> a_oCallback, float a_fDelay,
    LoadSceneMode a_eLoadSceneMode)
    {
    	yield return null;
    	var oAsyncOperation = SceneManager.LoadSceneAsync(a_oName, a_eLoadSceneMode);
        
        yield return Function.WaitAsyncOperation(oAsyncOperation, a_oCallBack);
    }
}

 

 

public abstract class CSingleton<T> : CComponent where T : CComponent
{
	private static T m_oInstance = null;
    
    public static T instance
    {
    	get
        {
        if(m_oInstance == null)
        {
        var oGameObject = new GameObject(typeof(T).ToString());
        m_oInstance = Function.AddComponent<T>(oGameObject);
        
        DontDestroyOnLoad(oGameObject);
        }
        }
    
    }
    
            
        //!인스턴트를 생성한다
        public static T Create()
        {
        return CSingleton<T>.Instance;
	
}

 

 

//!컴포넌트
//추상 클래스

public abstract class CComponent : MonoBehaviour
{
	#region
    [HideInInspector] public Transform m_oTransform = null;
    [HideInInspector] public Rigidbody m_oRigidbody = null;
    [HideInInspector] public Rigidbody2D m_oRigidbody2D = null;
    #endregion
    
    /*
    추상 클래스를 활용한 설계 단계에서는 호출 순서도 고민을 해봐야 한다.
    Awake() 함수는 해당 컴포넌트가 다른 게임 오브젝트에 추가되는 시점(AddComponent)에 호출되는 반면
    Start()함수는 해당 로직이 실행되는 프레임의 마지막 또는 다음 프레임이 동작할 때 호출된다.
	*/
    
    
    //초기화
    public virtual void Awake() //추상 클래스이므로 가상함수로 처리
    {
    	m_oTransform = this.transform;
        m_oRigidbody = this.GetComponentInChildren<Rigidbody>();
        m_oRigidbody2D = this.GetComponentInChildren<Rigidbody2D>();
    }
    
    
    //초기화
    public virtual void Start()
    {
   		 //! Do Nothing //아무것도 하지 않음을 알려주기 위해 메모..
    }
    
    
    //상태를 갱신
    public virtual void Update()
    {
  	 	 //! Do Nothing
    }
    
    
    //상태를 지연갱신
    public virtual void LateUpdate()
    {
    	//! Do Nothing
    }
}

 

//씬 관리자

public class CSceneManager : CComponent
{
	#region public 변수
    
    public float m_fPlaneDistance = KDefine.DEFAULT_PLANE_DISTANCE;
    
    #endregion
    
    //UI 카메라 프로퍼티
    public static Camera UICamera
    {
    get
    {
   	 return Function.FindComponent<Camera>(KDefine.NAME_UI_CAMERA);
     }
    }
    
    //메인 카메라 프로퍼티
	    public static Camera MainCamera
    {
    get
    {
   	 return Function.FindComponent<Camera>(KDefine.NAME_MAIN_CAMERA);
     }
    }
    
    
    // UI 루트 프로퍼티
        public static GameObject UIRoot
    {
    get
    {
   	 return GameObject.Find(KDefine.NAME_UI_ROOT);
     }
    }

        public static GameObject ObjectRoot
    {
    get
    {
   	 return GameObject.Find(KDefine.NAME_OBJECT_ROOT);
     }
    }
    
    
    //현재 씬 관리자 프로퍼티
       public static GameObject CurrentSceneManager
    {
    get
    {
   	 return GameObject.Find(KDefine.NAME_SCENE.MANAGER);
     }
    }
    
    //Find 느린데 쓰는 이유? 런타임 이전에 미리 찾아오고 시작하는 것이므로!
    
    
    
    
    //초기화
    public override void Awake()
    {
    base.Awake(); // 상속된 어웨이크도 작동하게 만들어줌.
    	SetupUICamera();
        SetupMainCamera();
        
        
        //모니터 주파수에 맞춰 렌더링 퍼포먼스를 조절하고 '티어링' 현상을 방지하겠다~는 목적
        QualitySetting.vSyncCount = 0;
        //60 프레임으로 고정
        Application.targetFrameRate = 60;
        
        Screen.SetResolution(KDefine.SCREEN_WIDTH, KDefine.SCREEN_HEIGHT, false);
    }
    
    
    //상태를 갱신
    public override void Update()
    {
    	base.Update();
        
    	if(Input.GetKeyDown(KeyCode.Escape))
        {
        	//CSceneLoader.Instance.LoadScene(0);
            CSceneLoader.Instance.LoadSceneAsync(0, (a_oAsyncOperation) =>
            {
            	Debug.LogFormat("Percent: {0}", a_oAsyncOperation.progress); //람다식 이용
            });
        }
    
    }
    
    
    
    /*
    프로젝션(투영)
    - 투영은 3D 장면에서 2D 표면을 얻는 과정
    - 크게 두 가지가 있으며 Perspective는 3D / orthographic은 2D에서 많이 사용된다.
   
   
    Perspective(원근 투영) / orthographic (직교 투영)
    원근 투영: 원근감, 카메라가 보고 있다면 가까이에 있는 물체는 카메라의 앞으로 올수록
    스케일을 위아래로 늘려 원근감을 부여한다.
    
    직교 투영: 오브젝트를 원근감 없이 수직 위에서 내려다 보듯이 투영
    

	isometric
    */
    
    
    // UI카메라를 설정한다.
    protected void SetupUICamera()
    {
    	if(CSceneManager.UICamera != null)
        {
        	CSceneManager.UICamera.orthographic = true;
            CSceneManager.UICamera.orthographicSize = 
            (KDefine.SCREEN_HEIGHT / 2.0f) * KDefine.UNIT_SCALE
        }
    }
    
    
    // 메인 카메라를 설정한다.
    protected void SetupMainCamera()
    {
    	if(CSceneManager.MainCamera != null)
        {
        	float fPlaneHeight = (KDefine.SCREEN_HEIGHT / 2.0f) * KDefine.UNIT_SCALE;
            float fFieldOfView = Mathf.Atan(fPlaneHeight / m_fPlaneDistance);
            
            CSceneManager.MainCamera.orthographic = false;
            CSceneManager.MainCamera.fieldOfView = (fFieldOfView * 2.0f) * Mathf.Rad2Deg;
            //호도법 알아봐!
        }
    }
    
    
    
    //접근제어자 public, private, protected, internal
    //internal 알아보기
    
    
}
public class CSoundManager : MonoBehaviour
{




}

 

 

+) 추가로 알아볼 것

 

추상클래스

메모리 대기

메모리 구현화

'이론(면접)' 카테고리의 다른 글

LINQ  (0) 2022.07.15
Attribute  (0) 2022.07.01
SendMessage (ray)  (0) 2022.07.01
변수 표기법  (0) 2022.06.30
배열 / 정적 클래스 / 확장메서드  (0) 2022.06.29