Unity Chapter 8-3. C# 프로그래밍 [고급] : 이벤트
카테고리: Unity Lesson 1
태그: C Sharp Unity Game Engine
인프런에 있는 이제민님의 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리한 필기입니다. 😀
🌜 [레트로의 유니티 C# 게임 프로그래밍 에센스] 강의 들으러 가기!
Chapter 8. C# 프로그래밍 : 고급
🔔 이벤트
- 이전 포스트에서 공부했던
유니티 이벤트
는 C#에서 제공하는delegate
와Event
기능을 쉽게 사용할 수 있게끔 유니티에서 제공하는 기능이었다.
커플링
커플링
: 두 오브젝트가 잘 알고 지내고 하드하게 연결되어 있는 정도를 뜻한다.
- 코드를 간결하게 하려면 커플링을 줄여야 한다.
- A 와 B 사이에 커플링이 심하다는 말은 A 와 B 가 서로 엮여있는 정도가 높기 때문에 A 가 없어지면 B 의 코드를 수정하기가 쉽지 않다는 의미다.
- 커플링을 줄이면 A 와 B 가 서로 모르는 사이가 되기 때문에 둘 중 하나가 없어져도 코드를 수정하기 수월해지거나 수정할 필요가 없게 된다.
이벤트를 사용하는 이유
커플링을 줄여 주기 때문.
- A 클래스의 Dead() 함수가 실행될 때 B 클래스의 함수와 C 클래스의 함수가 실행될다고 할 때
- 이벤트를 사용하지 않은 경우
- A 클래스는 B, C 클래스를 알고 있어야 한다.
- 따라서 B, C 클래스 참조 변수를 선언하고 슬롯에 B, C 스크립트가 붙은 오브젝트를 넣어주는 작업이 필요하다.
- 커플링이 증가한다.
- 따라서 B, C 클래스가 없어지면 A 클래스를 수정해야 하는 부분이 많이 생긴다.
- A 클래스는 B, C 클래스를 알고 있어야 한다.
- 이벤트를 사용한 경우
- A 클래스는 B, C 클래스에 대해 몰라도 된다.
- A 클래스의 OnDead 이벤트에 B, C 클래스의 함수를 등록만 해두면 OnDead 이벤트가 실행되었을 때 알아서 B, C 클래스의 함수들이 실행되기 때문이다.
- 커플링이 없다.
- B, C 클래스가 없어져도 A 클래스 코드엔 영향이 없다.
- A 클래스는 B, C 클래스에 대해 몰라도 된다.
- 이벤트를 사용하지 않은 경우
이벤트 용어
- 이벤트를 발동 시키는 측 👉 Publisher
- 이벤트에 자기 자신의 기능을 등록시켜 놓고 대기하는 측 👉 Subcriber
이벤트를 사용하지 않은 경우
📜Booster.cs
- 📜Character의 hp, defense, damage를 증가시켜 준다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Booster : MonoBehaviour
{
public void HealthBoost(Character target)
{
Debug.Log(target.playerName + "의 체력을 강화했다!");
target.hp += 10;
}
public void ShieldBoost(Character target)
{
Debug.Log(target.playerName + "의 방어력을 강화했다!");
target.defense += 10;
}
public void DamageBoost(Character target)
{
Debug.Log(target.playerName + "의 공격력을 강화했다!");
target.damage += 10;
}
}
📜Character.cs
- 📜Booster.cs 정보를 알고 있어야 한다.
- 📜Booster.cs의 세 함수를 써야 📜Character의 hp, defense, damage를 증가시킬 수 있으므로.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Character : MonoBehaviour
{
public Booster booster;
public string playerName = "anso";
public float hp = 100;
public float defense = 50;
public float damage = 30;
void Awake()
{
booster.HealthBoost(this);
booster.DamageBoost(this);
booster.ShieldBoost(this);
}
}
- booter의 유니티 슬롯에 📜Booster.cs 가 붙은 오브젝트를 붙여주어야 한다.
booster.HealthBoost(this);, booster.DamageBoost(this);, booster.ShieldBoost(this); 이렇게 일일이 나열할 필요 없이
Event
를 사용하여 Boost라는 이벤트에 HealthBoost, DamageBoost, ShieldBoost를 등록해 놓고 Boost라는 이벤트만 발생시키면 코드가 훨씬 간결해질 수 있다.
이벤트 사용한 경우
- 사용 방법 👉
delegate
와 일맥상통한다.delegate
로 이벤트를 만들 수 있다.
- 📜Character.cs 가 📜Booster.cs를 알 필요가 없다.
📜Booster.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Booster : MonoBehaviour
{
public void HealthBoost(Character target)
{
Debug.Log(target.playerName + "의 체력을 강화했다!");
target.hp += 10;
}
public void ShieldBoost(Character target)
{
Debug.Log(target.playerName + "의 방어력을 강화했다!");
target.defense += 10;
}
public void DamageBoost(Character target)
{
Debug.Log(target.playerName + "의 공격력을 강화했다!");
target.damage += 10;
}
void Awake()
{
Character player = FindObjectOfType<Character>();
player.playerBoost += HealthBoost;
player.playerBoost += ShieldBoost;
player.playerBoost += DamageBoost;
}
}
- void Awake
- 📜Booster에서
playerBoost
델리게이트에 📜Booster의 함수들을 등록해준다. - 📜Character에서
playerBoost
델리게이트를 void Start() 에서 실행할 것이라서 델리게이트 등록은 미리 void Awake에서 해주었다. - Character player = FindObjectOfType<Character>();
- 📜Character.cs 가 붙은 player 오브젝트를 가져온 후
- 델리게이트와 마찬가지로
+
와-
연산을 이용하여 델리게이트를 등록해준다.
- 📜Booster에서
📜Character.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Character : MonoBehaviour
{
// public Booster booster; 알 필요가 없다.
public delegate void Boost(Character target);
public Boost playerBoost;
public string playerName = "anso";
public float hp = 100;
public float defense = 50;
public float damage = 30;
void Start()
{
playerBoost(this);
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
playerBoost(this);
}
}
}
- public delegate void
Boost
(Character target);Boost
라는 델리게이트를 선언- 리턴은 없으며 Character타입의 인수를 1개 받는 함수만 등록할 수 있다.
- public Boost
playerBoost
;- 위에서 선언한
Boost
델리게이트 타입인playerBoost
를 정의했다. Boost
로playerBoost
을 찍어냄.
- 위에서 선언한
- playerBoost(this)
playerBoost
에 등록된 모든 함수들을 실행시킨다.- 📜Character.cs가 붙은 오브젝트인 자기 자신을 인수로 넘긴다.
delegate
와 event
키워드 차이
delegate
로 이벤트를 만들 수 있는데 C#엔 왜event
키워드가 있을까?
delegate
생성시event
를 앞에 붙여주면 델리게이트가 이벤트가 아닌 방향으로 사용되는 것을 엄격히 제한한다.
📜Character.cs
public delegate void Boost(Character target);
public event Boost playerBoost; // event 키워드를 붙여 줌
playerBoost
델리게이트 생성시event
를 다음과 같이 써주면 함수를 이벤트에 등록할 때 덮어씌워지는 것을 방지해준다.
📜Booster.cs
player.playerBoost += HealthBoost;
player.playerBoost += ShieldBoost;
player.playerBoost = DamageBoost; // 덮어씌우기 방지. 에러💥
+
연산을 하지 않고 실수로=
만 해버리면 이벤트에 그대로 DamageBoost 함수 한개만 덮어씌워져playerBoost
실행시 DamageBoost 함수만 실행된다.- 이러면 이벤트를 사용하는 의미가 작아진다.
event
를 붙여주면 이렇게 덮어씌워지는 것을 방지해준다. 에러가 난다.event
를 사용하면 이벤드 등록시=
는 안되고+
,-
만 가능하다.
📜Booster.cs
player.playerBoost += HealthBoost;
player.playerBoost += ShieldBoost;
player.playerBoost(player); // 밖에서 실행 방지. 에러💥
event
를 사용하면 밖에서 이벤트를 발동시킬 수 없다.- 이곳 저곳에서 멋대로 이벤트를 발동시키는 것을 방지.
- 📜Character.cs 에서만 델리게이트를 발동시킬 수 있고 📜Character.cs 밖인 📜Booster.cs에선 발동시킬 수 없다.
📜Booster.cs
player.playerBoost += HealthBoost;
player.playerBoost += ShieldBoost;
player.playerBoost += DamageBoost;
- 👆
event
사용시 올바른 등록 방법
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기