[Unity C#] 프로그래밍 기초

내발은개발내손은개발·2025년 12월 31일

유니티 함수

Unity Script 생명주기


시작함수

void Awake()

: 가장 먼저 1번 실행되는 함수

void OnEnable()

: 오브젝트가 on될 때마다 1번 실행되는 함수

void Start()

: 1번 실행되는 함수

void OnDisable()

: 오브젝트가 off될 때마다 1번 실행되는 함수

void OnDestroy()

: 오브젝트가 파괴될때 1번 실행되는 함수

void FixedUpdate()

: 고정된 프레임마다 계속 실행

void Update()

: 컴퓨터 성능에 따라 계속 실행

void LateUpdate()

: Update 다음에 실행


physics 함수


OnCollision 이벤트

void OnCollisionEnter(Collision collision)

: 두 오브젝트가 충돌했을 때 1번 호출

void OnCollisionStay(Collision collision)

: 두 오브젝트가 충돌 상태를 유지하는 동안 호출

void OnCollisionExit(Collision collision)

: 두 오브젝트가 충돌 상태에서 벗어났을 때 호출

OnTrigger 이벤트

void OnTriggerEnter(Collider other)

: Collider 영역에 들어갔을 때 1번 호출

void OnTriggerStay(Collider other)

: Collider 영역에 들어간 상태를 유지하는 동안 호출

void OnTriggerExit(Collider other)

: Collider 영역을 벗어났을 때 1번 호출



OnCollision과 OnTrigger의 차이점

Input Event 함수

마우스 이벤트 함수

void OnMouseDown()

: 마우스로 누를 때 1번 실행

void OnMouseUp()

: 마우스로 뗄 때 1번 실행

void OnMouseEnter()

: 마우스 포인터가 진힙했을 때 1번

void OnMouseExit()

: 마우스로 포인터가 빠져나갔을 때 1번

void OnMouseOver()

: 마우스 오브젝트 위에 있을 때 계속 실행

void OnMouseDrag()

: 마우스를 누른 상태로 있을 때 계속 실행

void OnMouseUpAsButton()

: 오브젝트 범위 내에서 마우스를 뗀 경우 1번 실행

키보드 이벤트 함수(InputEvent 함수 X,프레임 상태에서 조회하는 Polling방식)

Input.Getkey(KeyCode key)

: 키를 누르고 있는 동안 계속 실행

Input.GetKeyDown(KeyCode key)

: 키를 누른 순간 1번 실행

Input.GetKeyUp(KeyCode key)

: 키를 뗀 순간 1번 실행

Input.GetAxis("Horizontal" or "Vertical")

: 입력값을 -1~1값으로 변환

Input.GetAxisRaw("Horizontal" or "Vertical")

: 보정 없는 즉기 값 변환 (-1.0.1)

Input.anyKey (if(Input.anyKey))

: 아무 키나 눌렀을 때 true

Input.anyKeyDown (if(Input.anyKeyDown))

: 아무 키나 처음 눌렀을 때 1번



조건문

: 조건의 결과를 보고 실행되는 문법

if-else 조건문

if (조건 A){
	조건 A가 true
}
else if(조건 B){
	조건 B가 true
}
else{
	그 외의 경우
}

Switch 조건문

switch (변수)
{
	case a:
    	break;
        //변수가 a일경우 실행
    case b:
    	break;
        //변수가 b일경우 실행
    case c:
    	break;
        //변수가 c일경우 실행
    default:
    	break;
        //변수의 값이 위의 값 이외의 경우 실행
}

Invoke 함수

: 호출 함수

Invoke("함수명", 지연시간)

: 지연시간 후 함수 실행

InvokeRepeating("함수명", 지연시간, 반복주기)

: 지연시간 후 함수 실행 한 후 반복주기 마다 실행
ex) InvokeRepeating("함수명",3f, 2f) -> 함수를 3초 후에 실행한 후 2초마다 반복 실행

CancelInvoke("함수명")

: 호출한 Invoke함수 취소 (Invoke,InvokeRepeating으로 예약된 호출만 취소가능)

Invoke("함수명", 지연시간);
InvokeRepeating("함수명", 처음 지연시간, 반복주기);
CancelInvoke("함수명");

반복문 함수

: 조건에 만족하면 반복해서 실행되는 문법

While 반복문

: 조건이 성립되는 동안 반복

while (조건 A){
	조건 A가 true인 경우 실행
}

do~while 반복문

: do -> while 조건 확인 -> do -> while 조건 확인 -> do ...
: 조건에 맞지 않아도 do문은 한번 실행

do
{

}
while(조건 A)

for 반복문

: 순차적으로 반복

for(변수 정의; 반복범위; 증감단위){

}

for( i = 1; i < 3 ; i++){
	Debug.Log(i);
}

foreach 반복문

: 배열이나 리스트를 하나씩 반복

foreach(데이터타입 변수 in Collection){

}

private string[] personNames = ["철수","영희","영지"];


foreach(var personName in personNames){
	Debug.Log(personName);
}
철수
영희
영지

break, return, continue

break : 반복문을 빠져나오는 기능
return : 함수를 종료
continue : continue보다 아래 기능을 실행하지 않고 다시 반복문을 실행

Random

: Random.Range(int or float a, int or float b)
: a~b까지의 랜덤 숫자 뽑기

코루틴(Coroutine)

(시작 시간과 끝나는 시간이 정해져있을때 사용, 느린판단을 할때)

yield return null; -> 1프레임 대기 Update 호출까지 대기 후 실행
yield return new WaitForFixedUpdated(); -> FixedUpdate 호출까지 대기 후 실행
yield return new WaitForSeconds(time); -> tiem 만큼 대기 후 실행
yield return new WaitForSecondsRealtime(time); -> Timescale에 영향 X, time 대기 후 실행
yield return new WaitForEndOffFrame(); -> 모든 렌더링 작업이 완료될 때까지 대기 후 실행
yield return new WaitUntill(()=>time > 10); -> 해당 조건이 true가 될때까지 대기 후 실행
yield break; -> 코루틴 종료

//함수 호출 방법
void Start(){
	StartCoroutine("Routine");
    StartCoroutine(nameof(Routine));
    StartCoroutine(Routine());
    //매개변수 한개(함수 이름으로 실행할 경우)
    StartCoroutine("Routine1",4);
    //매개변수 여러개(함수 자체로 실행)
    StartCoroutine(Rotuine2(1,2,3));
}

//코루틴 생성 방법
IEnumerator Routine(){
	Debug.Log("Hello");
    yield return new WaitForSeconds(3f);
}

IEnumerator Routine1(int a){
	Debug.Log("a");
    yield return null;
}

IEnumerator Routine2(int a, int b, int c){
	Debug.Log("a");
    Debug.Log("b");
    Debug.Log("c");
    yield return null;
}
//함수 종료 방법
private Coroutine runningCoroutine; -> 반환값 Coroutine을 담을 맴버 변수 선언
    
void Start()
{
    runningCoroutine = StartCoroutine(Running());
    Invoke("StopRoutine", 1.5f);
}

IEnumerator Running()
{
    Debug.Log("실행 1");
    yield return new WaitForSeconds(1.0f);

    Debug.Log("실행 2");
    yield return new WaitForSeconds(1.0f);

    Debug.Log("실행 3");
    yield return new WaitForSeconds(1.0f);
}

private void StopRoutine()
{
    StopCoroutine(runningCoroutine); -> StopCoroutine(Running())은 작동하지 않는다.
    Debug.Log("강제 종료");

    StopAllCoroutines(); // 클래스 내에서 실행되는 모든 Coroutine 정지
}

제너릭(Generic)

: 데이터 타입을 파라미터로 활용하는 변수

  • 코드 재사용성 용이
  • 호출시 타입 결정되기 때문에 성능 저하 X
public void Copy(int[] source, int[] target)
{
	for (int i = 0 ; i < source.Length ; i++)
    {
    	target[i] = source[i];
    }
}

public void Copy(float[] source, float[] target)
{
	for (int i = 0 ; i < source.Length ; i++)
    {
    	target[i] = source[i];
    }
}

public void Copy<T>(T[] source, T[] target) -> 일반화(모든 자료형 사용 가능->호출 시 자료형 재정의)
{
	for (int i = 0 ; i < source.Length ; i++)
    {
    	target[i] = source[i];
    }
}

//오브젝트 풀 예시 문

public class ObjectPool<T> where T : Component -> 제약 조건(T타입에 대한 조건 지정)
{
	private Queue<T> pool = new Queue<T>();
    private T prefab;
    
    public ObjectPool(T prefab, int initialCount)
    {
    	this.prefab = prefab;
        for(int i = 0; i <initialCount ; i++)
        {
        	T obj = GameObject.Instantiate(prefab);
            obj.gameObject.SetActive(false);
            pool.Enqueu(obj);
        }
    }
    
    public T Get()
    {
    	if(pool.Count > 0)
        {
        	var obj = pool.Dequeue();
            obj.gameObject.SetActive(true);
            return obj;
        }
        
        return GameObject.Instantiate(prefab);
    }
    
    public void Return(T obj)
    {
    	obj.gameObject.SetActive(false);
        pool.Enqueue(obj);
    }
}

매개변수 활용 : ref / out / params

일반 매개변수 (Call by Value)

  • 기본값이며, 값 형식인 경우 복사본 전달
  • 함수 내부에서 변경해도 원본은 변경되지 않는다.

ref (Call by Reference)

  • 초기화된 변수만 전달 가능
  • 함수 내부에서 변경 시 원본도 같이 변경
public int num = 10;

void Start()
{
        NormalParameter(num);
        RefParameter(ref num);
}

public void NormalParameter(int n)
{
        Debug.Log("호출 전 : " + n);
        n = 1;
        Debug.Log("호출 후 : " + num);
}
public void RefParameter(ref int n)
{
        Debug.Log("호출 전 : " + n);
        n = 1; 
        Debug.Log("호출 후 : " + num);
}
호출 전 : 10
호출 후 : 10 -> 원본이 변경 X

호출 전 : 10
호출 후 : 1 -> ref는 원본이 변경되었다.

Out (출력 전용 참조)

  • 함수 내부에서 반드시 초기화해야한다.
  • 초기화되지 않은 변수도 전달 가능
  • 입력값은 무시, 출력용 목적으로 사용
public class OutParameter : MonoBehaviour
{
	void Start()
    {
    	int a = Random.Range(1,100);
        int b = Random.Range(1,100);
        
        //Old 버전
        int result1 = 0;
        int result2 = 0;
       	Divide(a,b,out result1,out result2);
        
        //Out 파라미터를 메소드를 호출할 때 선언 가능
        //현재 메소드가 호출되는 블록 내부에서 선언 이후 사용 가능
        Divide(a,b,out int result1, out int result2);
        
        // var 키워드 사용 가능
        // 메소드 정의에는 var를 사용할 수 없기 때문에 메소드 정의를 참고해서 자동 설정
        Divide(a, b, out var r1, out var r2);
        
        //메소드 정의는 2개의 out 파라미터를 사용하도록 되어 있지만 필요 없는 경우도 존재 가능 '_' 사용
        Divide(a,b,out var rr1, out _);
        
        Debug.Log($"{a} / {b} = {result1}");
        Debug.Log($"{a} / {b} = {result2}");
        
        Debug.Log($"{a} / {b} = {r1}");
        Debug.Log($"{a} / {b} = {r2}");
        
        Debug.Log($"{a} / {b} = {rr1}");
    }
    
    void Divide(int num1, int num2,out int r1,out int r2)
    {
    	r1 = num1 / num2; ->몫
        r2 = num1 % num2; -> 나머지
    }
}
5 / 2 = 2
5 % 2 = 1

5 / 2 = 2
5 % 2 = 1

5 / 2 = 2

Params (가변 인자)

  • 매개변수의 개수를 가변적으로 받을 때 사용
  • 배열로 전달(개수가 정해지지 않은 자료형의 데이터를 넘기게 된다.)
  • 메서드 정의 시 마지막 인자에만 사용 가능
void Like(int x, params string[] message)
{
	foreach (string s in message)
    {
    	Debug.Log(s);
    }
}

void Start()
{
	int x = 3;
    Like(x, "맑음","나쁨","바람");
}
3
맑음
나쁨
바람
public int[] nums = {1,2,3,4,5};

void Start()
{
	ParamsParameter(1,2,3,4,5);
    ParamsParameter(10,20,30);
}

void ParmasParameter(params int[] numbers)
{
	string str = "";
    foreach (var number in numbers)
    {
    	str += num + " ";
    }
    Debug.Log(str);
}
1 2 3 4 5
10 20 30

클래스와 함수 커스텀 : Partial / Sealed

Partial

  • 분리 용도
  • 하나의 클래스, 구조체, 인터페이스를 여러파일에 나누어 구현 가능
  • 주로 Unity의 자동 생성 코드와 사용자 코드 분리, 대형 클래스 분할에 사용
  • 실행시 하나로 합쳐져서 컴파일 진행 -> 컴파일 단계
  • 네임스페이스가 동일해야 함
  • 모든 부분 정의에서 같은 접근 제한자 사용 ex) 하나의 partial 정의가 public이면 다른 정의도 public
    -> 장점 : 가독성,협업,조직화
public partial class StudyPartial : MonoBehaviour
{
	void Start()
    {
    	Debug.Log("Start method");
    }
}

public partial class StudyParital
{
	void Update()
    {
    	Debug.Log("Update mehtod");
    }
}
Start method
Update method
Update method
Update method
Update method
...
-> 2개의 파일이 컴파일 시 내용이 합쳐져서 하나의 클래스가된다.

Sealed

  • 봉인 용도
  • 클래스를 상속하지 못하도록 방지
  • 함수를 override 못하도록 막을 수 있다
  • 클래스 앞 -> 더 이상 상속 불가
  • override된 메서드 앞 -> 자식에서 override 불가
public class BaseClass : MonoBehaviour
{
	public virtual void Method()
    {
    	Debug.Log("일반 함수");
    }
}

public class MiddleClass : BaseClass
{
	public sealed override void Method()
    {
    	Debug.Log("봉인된 오버라이드 함수");
    }
}

public class LastClass : MiddleClass
{
	public override void Method() --> 함수가 봉인되었기 때문에 오류 발생(override 불가)
    {
    	Debug.Log("오버라이드 함수");
    }
}

함수를 대신 실행하는 대리자 : Delegate

Delegate

: 함수를 참조

  • 델리게이트 체인 (+= 등록, -= 제거)
접근제한자 delegate 반환타입 이름(매개변수)
public delegate void MyDelegate();
public class StudyDelegate : MonoBehaviour
{
	public delegate void MyDelegate();
    public MyDelegate onDelegate;
    
    void Start()
    {
    	//onDelegate에 함수 할당
    	onDelegate = MethodA;
        //MethodB 추가
        onDelegate += MethodB;
        //MethodC 추가
        onDelegate += MethodC;
        //MethodB 삭제
        onDelegate -= MethodB;
        
        //직접 실행
        onDelegate();
        //직접 실행과 동일한 방식
        //delegate.invoke -> 함수 즉시 호출, monobehaviour.invoke -> 지연 호출
        onDelegate.Invoke();
        //null 체크 방식
        OnDelegate?.Invoke();
    }
}

public class ParameterDelegate : MonoBehaviour
{
	public delegate void MyDelegate(int a = 10); -> 매개변수가 있는 함수 연결(default값을 10으로 설정)
    public Mydelegate onDelegate;
    
    void Start()
    {
    	onDelegate += MethodA; -> 오류 발생
        onDelegate += MethodB;
    }
    
    private void MethodA(){} -> 매개변수가 없는 함수
    private void MethodB(int b){} -> 매개변수가 있는 함수
}

event/UnityEvent/EventHandler (Delegate 기반)

event

  • 구독/발행 이벤트 패턴 용도
  • 외부 호출 방지 -> 오직 선언된 클래스 내부에서만 Invoke 가능
  • += -=로 구독 -> '='를 사용해서 외부에서 새롭게 할당 방지
  • (delegate를 외부에서 함부로 호출하거나 초기화하지 못하게 막는 캡슐화된 기능)
  • 함수 캡슐화
public class ExampleEvent : MonoBehaviour
{
	//델리게이트정의
	public delegate void InputKeyHandler();
   // public delegate void InputKeyHandler(string msg);
    //event 선언
    public event InputKeyHandler onInputKey;
    //위에 두줄 == public event Action onInputKey;
    
    public KeyCode keycode = KeyCode.Space;
    
    void start
    {
    	// 구독
    	onInputKey += OnInputKey;
    }
    void Update()
    {
    	if (Input.GetKeyDown(keycode)
        {
        	//구독자가 한명이라도 있으면 실행(즉, 0명인지 확인)
        	onInputKey?.Invoke();
            //onInputKey?.Invoke($"{keyCode}를 눌렀습니다");
        }
    }
    public void OnInputKey()
    {
    	Debug.Log("key Down");
    }
    /*public void OnInputKey(string msg)
    {
    	Debug.Log(msg);
    }
    */
}

UnityEvent

  • 인스펙터상에 표시하여 이벤트를 등록 가능
  • 외부에서 호출 가능, [SerializeField]를 활용하여 외부 접근 제한 가능
  • AddListener, RemoveListener로 구독
  • (인스펙터 창에서 이벤트를 연결할 수 있도록 만든 클래스)
using UnityEngine.Events; -> UnityEvent를 사용할려면 작성해야함

public class StudyUnityEvent : MonoBehaviour
{
	[SerializedField] private void UnityEvent onHappened -> 인스펙터 노출(외부 접근 제한)
	public UnityEvent uEvent;
    
    void Start()
    {
    	//구독
    	uEvent.AddListener(MethoA);
        uEvent.AddListener(MethoB);
        //매개변수가 있는 함수의 경우
        uEvent.AddListener(() => MethodC(10));
        
        //삭제
        uEvent.RemoveListener(MethoA);
    }
    
    void Update()
    {
    	if (Input.GetKeyDown(KeyCode.Space)
        {
        	//실행
        	uEvent?.Invoke();
        }
    }
    
    private void MethodA(){}
    private void MethodB(){}
    private void MethodC(int num){}
}

UnityHandler

  • Argument(인자)를 활용하는 Delegate
public delegate void EventHandler(object sender, EventArgs e);
//object sender -> 이벤트를 실행시키는 객체
//EventArgs e -> 이벤트 실행시 전달할 수 있는 매개변수
public class StudyEventHandler : MonoBehaviour
{
   private event EventHandler handler;
   //add, remove 이벤트 접근자
   public event EventHandler Handler //프로퍼티
   {
   		add
        {
        	Debug.Log($"{value.Method} 추가됨"); -> MethodA 추가됨
            handler += value;
        }
        remove
        {
        	Debug.Log($"{value.Method} 삭제됨"); -> MethodA 삭제됨
            handler -= value;
        }
   }
   
  //EventHandler -> void 타입의 매개변수가 2개인 델리게이트

  //delegate의 작업에서 주로 쓰이는 형태 OnEnable <-> OnDisable
  //켜져있으면 자동등록
  void OnEnable()
  {
      Handler += MethodA;
  }
  //파괴되거나 없어지면 구독해제
  void OnDisable()
  {
      Hanbdler -= MethodA;
  }

  void Update()
  {
 	  if(Input.GetKeyDown(keyCode.Space)
      	handler?.Invoke(this, EventArgs.Empty);
      	-> 매개변수를 아무것도 넣은게 없다면 (이렇게할거면 다른거를 사용하는게 좋음)
  }

	public void MethodA(object o, EventArgs e)
	{

	}
}
public class ExternalClass : MonoBehaviour
{
	public StudyEventHandler study;
    void Start()
    {
    	study?.Invoke(this, EventArgs.Empty); -> 실행불가능
    }
}
public class DataClass : EventArgs
-> Invoke를 통해 핸들러를 실행했을 때 데이터클래스의 정보를 활용하고 싶으면 DataClass에 EventArgs를 상속시키면 된다.
{
	public string dataName;
    public int dataNumer;
    public bool isData;
    
    public DataClass(string dataName, int dataNumber, bool isData)
    {
    	this.dataName = dataName;
        this.dataNumber = dataNumber;
        this.isData = isData;
    }
}
public class StudyEventHandler : MonoBehaviour
{
	public event EventHandler handler;
    -> EventHandler는 여러 데이터를 활용하는 용도로 사용
    void Start()
    {
    	handler += StartEvent;
        
        DataClass data1 = new DataClass("DataClass1",1,false);
        DataClass data1 = new DataClass("DataClass1",1,false);
        
        handler?.Invoke(this , data1); -> (data1을 Eventargs타입인 e로 자동변환 -> 업캐스팅)
        handler?.Invoke(this , data2);
    }
    
    private void StartEvent(object o, EventArgs e)
    {
    	var data = (DataClass)e; -> 형변환(e를 DataClass형태로 전환 -> 다운캐스팅)
        Debug.Log($"Data Name : {data.dataName}");
    }
}

업캐스팅, 다운캐스팅 없이 전달하기 위해서 EventHandler<'T'>를 사용

public class StudyEventHandler : MonoBehaviour
{
	public event EventHandler<DataClass> handler;
  	->  제너릭<T>를 활용
  	-> delegate void EventHandler<T>(object sender, T e)
    void Start()
    {
    	handler += StartEvent;
        
        DataClass data1 = new DataClass("DataClass1",1,false);
        DataClass data1 = new DataClass("DataClass1",1,false);
        
        handler?.Invoke(this , data1);
        handler?.Invoke(this , data2);
    }
    
    private void StartEvent(object o, DataClass e) -> 제너릭<T> 타입을 DataClass로 설정을 했기때문에 EventArgs를 넣을 필요가 없어짐
    {
    	Debug.Log($"Data Name : {e.dataName}");
  		Debug.Log($"Data Name : {e.dataNumber}");
  		Debug.Log($"Data Name : {e.isData}");
    }
}

익명함수와 람다

익명함수(Anonymous Method)

  • 이름 없는 함수
  • 한 번만 쓸건데 이름짓고 따로 만들기 귀찮은 상황 -> 간략하게 작성하자
public class StudyLamda : MonoBehaviour
{
 	public delegate void MyDelegate();
  	public MyDelegate myDelegate;
  
  	void Start()
  	{
  		//myDelegate = OnLog;
  		myDelegate = delegate -> 한번 쓰는 함수를 void OnLog(){} 쓰기 귀찮음 -> 일회용 함수 사용(함수 이름 X)
  		{
  			Debug.Log("Hello Unity");
  		}
  		myDelegate?.Invoke();
  		
  		//매개변수가 있는 익명함수
  		//myDelegate += delegate ~ 도 사용 가능
  		myDelegate = delegate (string s)
  		{
  			Debug.Log(s);
  		}
  		myDelegate?.Invoke("Hello Unity");
  	}
  	/*
  	public void OnLog()
  	{
  		Debug.Log("Hello Unity");
  	}
  	*/
}

람다

  • 익명함수를 활용
  • 함수를 생성하지 않아도 된다.
public class StudyLamda : MonoBehaviour
{
	public delegate void MyDelegate1();
  	public delegate void MyDelegate2(string s);
  	public delegate void MyDelegate3(string s);
  
  	public MyDelegate1 myDelegate1;
  	public MyDelegate2 myDelegate2;
  	public MyDelegate2 myDelegate3
  
  	void Start()
  	{
  		myDelegate1 = () => Debug.Log("Hello Unity");
  		myDelegate1?.Invoke();
  
  		myDelegate2 = (s) => Debug.Log(s);
  		myDelegate2?.Invoke("Hello Unity");
  
  		myDelegate3 = (s) =>
  		{
  			Debug.Log(s);
  			Debug.Log("Hello Unity");
  		}
  		myDelegate3?.Invoke("Hello C#");
  	}
}
Hello Unity
Hello Unity
Hello C#
Hello Unity
public class StudyLamda : MonoBehaviour
{
	public Button buttonUI;
  
  	void Start()
  	{
  		buttonUI.onClick.AddListener( () => OnLog("Hello") );
  	}
  	private void OnLog(string msg)
  	{
  		Debug.Log("Hello Unity");
  	}
}

Closure 이슈

: 외부 함수의 변수를 내부 함수가 참조할 때 발생
-> 내부 함수는 외부 함수의 실행이 끝난 후에도 외부 함수의 변수에 접근 가능

public class ExampleClosure : MonoBehaviour
{
 	public Button[] buttonUIs;
  	
  	void Start()
  	{
  		for (int i = 0 ; i < 5 ; i++) -> 외부함수의 영역
        {
            int temp = i; -> Closure 이슈 방지, temp는 매 for문 바퀴마다 새로 생성               
        	buttonUIs[i].onClick.AddListener(() => SetButton(temp)); ->(()=>Setbutton(temp))가 내부함수      
        }
  	}
}

Func / Predicate / Action / UnityAction

Func

: 여러 개의 매개변수를 넣을 수 있고 반환타입이 있는 Delegate
-> 마지막에 적은 타입이 반환타입

  • 델리게이트 체인이 있을경우 가장 마지막에 실행된 메서드의 반환값만 남게 된다.
접근제한자 Func<매개변수1, 매개변수2, 반환타입> 변수명;
public Func<int, int, int -> 반환타입> myFunc;
public class StudyFunc : MonoBehaviour
{
	public Func<int,int,int> myFunc; -> int 반환타입
    public Func<string, string, bool> myFunc2; -> bool 반환타입
    
    void Start()
    {
    	myFunc = AddMethod;
        int result = myFunc?.Invoke(10,7);
        Debug.Log($"최종 결과 : {result}");
        
        myFunc2 = CompareText
        bool result =2 myFunc2?.Invoke("hello", "unity");
        Debug.Log(result2);
    }
    
    private int AddMethod(int num1, int num2)
    {
    	return num1 + num2;
    }
    
    public bool CompareText(string msg1, string msg2)
    {
    	if (a==b)
        	return true;
        
        return false;
    }
}

여러 개의 Func를 추가한 List

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

public class StudyFunc : MonoBehaviour
{
    private List<Func<int, int>> funcList = new List<Func<int, int>>();

    void Start()
    {
        funcList.Add(AddMethod);
        funcList.Add(MinusMethod);
        funcList.Add(MultiplyMethod);
        
        -> 람다식으로 줄일 수 있음 (addmethod,minusmethod,multiplymethod가 필요없어짐)
        funcList.Add(n => n + 1);
        funcList.Add(n => n - 3);
        funcList.Add(n => n * 2);

        int result = 0;
        foreach (var func in funcList) -> 함수 순서대로 동작 
            result += func(5);

        Debug.Log($"최종 결과: {result}");
    }
	
    private int AddMethod(int n)
    {
        return n + 1;
    }
    
    private int MinusMethod(int n)
    {
        return n - 3;
    }
    
    private int MultiplyMethod(int n)
    {
        return n * 2;
    }
}
18 (addmethod return : 6 + minusmethod return : 2 + multiplymethod return : 10)

Predicate

: 반환값이 boolean인 Delegate

접근제한자 Predicate<매개변수> 변수명;
public Preicate<int> myPredicate;
public class StudyPreicate : MonoBehaviour
{
	public Predicate<int> myPredicate;
    public int myLevel = 10;
    
    void Start()
    {
    	myPredicate = n => n <= 10; (n <= 10) -> true 값이 n으로 반환
        string msg = myPredicate(myLevel) ? "초보자 사냥터 이용 가능" : ":초보자 사냥터 이용 불가능"; -> 반환값에 따라 ? 이용 가능(true) : 이용 불가능(false)
        Debug.Log(msg);
    }
}

Action

: 반환 타입이 없는 Delegate

접근제한자 Action 변수명;
접근제한자 Action<매개변수(여러개도 가능)> 변수명;
public class StudyAction : MonoBehaviour
{
	//매개변수 없는
	public Action myAction;
    //매개변수가 있는
    public Action<string> myAction2;
    
    void Start()
    {
    	myAction = () => Debug.Log("Hello Unity");
        myAction?.Invoke();
        
        myAction2 = (s) => Debug.Log(s);
        myAction2?.Invoke("Hello Unity");        
    }
}

Action은 함수만 static

public class ExampleAction : MonoBehaviour
{
    public static Action myAction; -> myActiong만 static
    //public static event Action myAction; -> 캡슐화 작업을 통해 외부 작업 방지
	// Property는 변수 캡슐화 작업
    void Start()
    {
        myAction += AddMethod;
    }

    private void AddMethod()
    {
        Debug.Log("더하는 기능");
    }
}

public class ExampleClass : MonoBehaviour
{
    void Start()
    {
        ExampleAction.myAction += OtherMethod; -> 외부에서 실행할때, 굳이 싱글턴 또는 변수만들어서 할 필요없이 static된 myAction만 접근가능
        
        ExampleAction.myAction?.Invoke();
    }
    
    public void OtherMethod()
    {
        Debug.Log("기능");
    }
}

UnityAction

: Unity에서 제공하는 Action Delegate

  • delegate -> +=, -=, ?.Invoke
  • UnityEvent -> AddListener, RemoveListener, ?.Invoke
public class StudyUnityAction : MonoBehaviour
{
	public Button buttonUI;
    public UnityAction uAction;
    
    void Start()
    {
    	uAction += MethodA;
        uAction += MethodB;
        uAction += MethodC;
        
        buttonUI.onClick.AddListener(uAction);
    }
    
    private void MethodA(){};
    private void MethodB(){};
    private void MethodC(){};
    
    
}

0개의 댓글