IT/공부 정리

[UNITY/C#] C#고급 프로그래밍

rinix_x 2023. 3. 9. 03:30
유니티 이벤트

- 이벤트 끼리 엮이지 않음

- Invoke("함수명", 지연시간f); || 지연시간 만큼 흐른뒤에 함수가 호출 됨

 

예제1)

using UnityEngine.Envents; 으로 라이브러리 추가해주고,

public UnityEvent TestEvent; 선언

TestEvent.Invoke()로 호출.

 inspector에서 스크립트 추가된 것 중 연쇄적으로 같이 발동 될 함수들을 등록 시켜 주면 됨.

--> 스크립트에서 각자 스크립트를 선언해서 호출해주는 것이 아닌, 임의로 지정, 넣어줘서 호출 가능.

(한줄로 가능해서 깔끔해 짐)

 

델리게이트(delegate)

- C#에서 제공하는 이벤트

- 어떠한 기능을 목록에 추가하면 대신 발생시켜줌.

- 유언대리인, 비서 해야할 리스트를 넘겨주면 쭉 대행해주는 것.

- 델리게이트 형을 먼저 선언,

- 포인터를 갖고 사용(발동)

 

예제2)

delegate float Cal(float a, float b); 타입 명시

Cal onCal; 선언

onCal  = 함수//Sum  // 명부, 리스트에 등록

onCal(1,10); 하면 자동으로 함수Sum()이 실행됨

 

onCal +=sub 하면 Sum과 sub둘다 함수 호출, -로 빼기도 가능

return하게 되면, 마지막으로 추가된 함수의 결과값만 갖고 옴.

 

 


두 오브젝트의 엮인 부분(커플링,결합도)을 줄이기 위해 이벤트를 사용.

publisher : 이벤트 발생자

subcriber : 이벤트 감지자

 

아래와 같은 방식을 쓰면, Charater스크립트가 간결해진다.

//캐릭터의 내부적 요소,HP ST를 관리한다 할때, 

//예제3)

public class Charater : MonoBehavior{

	public delegate void Boost(charater target);

	public Boost playerBoost;

	public string playerName = "yerin"

	public float hp =100;

	public float st =100;



	void Start(){

		playerBoost(this);

	}

}

//Boost에 대한 내용이 담긴 스크립트에서
Character player = FindObjectOfType<Character>();
player.playerBoost += HealBoost; // HealBoost같은 경우는
			 // Booster.cs에서 작성된 함수이름이다.

위와 같은 경우 delegate event 로 하게 되면, 덮어씌우기가 안됨,

 + 이벤트가 아닌 기능으로 사용되는 것을 막아줌.(실수 막아줌)

 

 

 


액션은 C#에서 제공하는 미리 사용하기 쉽게 만들어진 델리게이트.

람다 함수는 오브젝트를 탄생하듯, 이름이 없는 함수를 만들고, 여기저기 부여 가능.

 

1. Action

더보기

delegate void Work();

Work work;

void Move(){}

void Jump(){}

 

Start(){

work+=Move;

work+=Jump

}

위 접은 글을 아래 처럼 바꿔 사용이 가능하다.

using System;

Action work;

void Move(){}

void Jump(){}



Start(){

work+=Move;

work+=Jump

}

 

2.람다

더보기

public delegate void Send(string reciever);

 

Send onSend;

 

void SendMail(string reciever){}

void SendMoney(string reciever){}

 

void Start(){

onSend +=SendMail

onSend+=SendMoney

}

이 접은 글을 말고 즉석으로 새로 함수를 만들어 사용 가능하게 해줌

public delegate void Send(string reciever);
Send onSend;

void SendMail(string reciever){}
void SendMoney(string reciever){}

void Start(){
onSend += SendMail
onSend += SendMoney
onSend += man => 함수내용;  //함수이름은 없지만 함수내용으로 사용 가능 (값으로 사용 가능)
}

+ 람다 타입을 사용할 때 해당 타입이 무엇인지 임시적으로 지정할 필요가 없음.

원래 사용은 onSend += (string man)  => {sum=1; on=2;}; 이런식으로 축약 안된 버전이고, 두 줄 이상도 가능

더보기

다른 코드 예시들

private int health = 0;

public void RestoreHealth(int amount) {
	health += amount;
}

public bool IsDead() {
	return (health <= 0);
}

--------------------------

private int health = 0;
public void RestoreHealth(int amount) => health += amount;
public bool IsDead() => (health <= 0);

 

프로 퍼티에서도 다음과 같이 표현 가능

private int health = 0;

public int Health {
	get { return health; }
	set { health = value; }
}

public bool IsDead {
	get { return (health <= 0); }
}

------------------------------

private int health = 0;

public int Health {
	get => health;
	set => health = value;
}

public bool IsDead => (health <= 0);

다음 상황에서는 클린 코드를 구현하기 위해 람다 식을 적극 활용하는 것을 추천한다.

  • 한 두줄로 이루어진 메서드 또는 프로퍼피
  • 특히 한줄로 이루어진 get 프로퍼티가 존재하는 경우

 


제네릭이란, 보통 클래스나 인터페이스, 메서드를 사용할 때, 동일한 기능을 수행하지만, 입력하는 데이터 형식만 틀린 경우가 있을 때, 매개변수를 일일히 넣어서 클래스나 인터페이스, 메서드를 만들지 않고, 제네릭 타입(Generic Type)을 사용하여 만들 수 있다.

public void Print<T> (T input){
Debug.Log(input);
}

와 같은 느낌으로 타입을 맞춰 발동 시킬때 사용하며 클래스에 맞게도 사용가능

 

public class util : MonoBehaviour{
    void Start(){
        Container container = new Container();
        container.messages = new stirng[3];

        container.messages[0] = "Hello"; //숫자나 형태가 달라져도 자동 대응 가능
        container.messages[1] = "HI";

    }
}

public void Container<T>{
	public T[] message;
}


 

 

 

반응형