using UnityEngine;
// T는 MonoBehaviour를 상속한 클래스만 사용가능
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
// null이면 해당 타입을 가진 오브젝트를 찾고, 없다면 새로 생성
public static T Instance
{
get
{
if (instance == null)
{
// 해당 컴포넌트를 가지고 있는 게임 오브젝트 반환
instance = (T)FindAnyObjectByType(typeof(T));
if (instance == null)
{
// 새로운 게임 오브젝트 생성 및 컴포넌트 추가
GameObject obj = new GameObject(typeof(T).Name, typeof(T));
// 새로운 오브젝트의 컴포넌트 인스턴스에 지정
instance = obj.GetComponent<T>();
}
}
return instance;
}
}
private void Awake()
{
// 인스턴스가 없을 때 해당 오브젝트로 설정
if (instance == null)
{
instance = this as T;
DontDestroyOnLoad(this.gameObject);
}
// 인스턴스가 존재한다면 현재 오브젝트 파괴
else if (instance != null)
Destroy(gameObject);
}
}
public class GameManager : Singleton<GameManager>
{
public int score;
public void AddScore(int value)
{
score += value;
}
}
// 다른 클래스에서
GameManager.Instance.AddScore(10);
제네릭 기반 클래스를 통해 공통된 로직을 정의하여 다른 곳에서 코드를 복붙하지 않아도 된다.
-> 타입에 따라 달라지는 부분만 따로 구현
-> 공통적인 로직은 한 번만 정의하여 코드 중복 없이 재사용 가능
public void AddTen(ref int number)
{
number += 10;
}
int num = 5;
AddTen(ref num);
Console.WriteLine(num);
>>> 15
ref 매개변수는 메서드 호출 전 반드시 초기화되어 있어야한다.
public void GetValues(out int a, out int b)
{
a = 10;
b = 20;
}
int x, y;
GetValues(out x, out y);
Console.WriteLine($"{x}, {y}");
>>> 10, 20
| 키워드 | 특징 | 호출 전 초기화 | 메서드 내 값 할당 필수 | 용도 |
|---|---|---|---|---|
ref | 참조 전달 | 필요 | 선택 | 기존 값을 수정하고 싶을 때 |
out | 출력 전용 | 불필요 | 필수 | 메서드에서 여러 값을 반환할 때 |
out, ref 모두 메서드에서 매개변수를 전달할 때 사용하고 값의 반환이 아닌, 매개변수를 이용하여 값을 전달 할 수있다.
하지만, 너무 많이 사용하게 되면 가독성이 떨어진다.