bool 변수를 이용한 상태이상 관리
게임에서 플레이어를 비롯한 생명체들은 패널티를 갖는 디버프, 또는 이로운 효과의 버프를 얻게 되는 경우가 많습니다.
이러한 기능을 구현하기 위해서 보통 bool 타입의 변수를 통해 true인지 false인지 체크합니다.
하지만 상태가 한두개가 아닌 여러개가 되면 그만큼의 bool 타입 변수들을 계속 생성해야 합니다.
예를들어 플레이어가 걸릴 수 있는 상태이상이 8개가 있다고 가정해보겠습니다.
독, 기절, 화상, 빙결, 침묵, 출혈, 혼란, 매혹이란 상태가 있고 각 상태들이 어떤지 체크하기 위해서 8개의 bool 타입 변수를 생성하게 될 것입니다.
상태가 더 추가될수록 더 많은 bool 타입 변수를 만들어야하고 bool 타입은 1바이트이기 때문에 계속해서 1바이트의 메모리가 사용되는 것입니다.
bool isPoisoned;
bool isStunned;
bool isBurning;
bool isFrozen;
bool isSilenced;
bool isBleeding;
bool isConfused;
bool isCharmed;
이번엔 Enum을 이용하여 위와 같은 상태들을 관리해보겠습니다.
public enum PlayerState
{
None, //기본
Poisoned, //독
Stunned, //기절
Burning, //화상
Frozen, //빙결
Silenced, //침묵
Bleeding, //출혈
Confused, //혼란
Charmed //매혹
}
PlayerState 를 통해 원하는 상태이상을 바꾸어주면 되지만 한 가지 문제가 생기게됩니다.
보통 게임에선 여러 상태이상이 동시에 걸릴 수 있습니다.그러나 이러한 방법으론 최대 하나의 상태이상만 적용될 수 있습니다.
PlayerState state = PlayerState.None;
state = PlayerState.Silenced;
state = PlayerState.Burning;
[System.Flags] 속성을 통해 Enum 타입을 플래그로 바꾸어준다면 더 적은 메모리를 통해 각각의 상태이상을 관리할 수 있습니다.
[System.Flags]
[System.Flags]는 C#에서 Enum을 비트 플래그 용도로 사용하기 위해 표시하는 속성입니다.
Enum 자체는 정수형 값의 집합이지만 [Flags]를 붙이게 되면 각 멤버가 비트 조합을 의미하는 enum이라고 명시할 수 있습니다.
또한 비트 연산을 통해 여러 값을 가질 수 있습니다.
먼저 예시를 통해 각 코드를 설명해보도록 하겠습니다.
[System.Flags] 라는 속성을 선언해 PlayerState가 비트 플래그의 속성을 띄도록 하였습니다.또한 Enum의 기본값은 int이기에 이름 옆에 : byte 를 통해 해당 Enum의 크기를 byte로 선언했습니다.
PlayerState의 각 멤버 옆에 있는 = 1 << n 은 ' << ' 라는 비트 왼쪽 시프트 연산자를 이용해 1을 왼쪽으로 n칸 밀라는 뜻입니다.8비트인 byte를 기준으로 0000 0000의 값이 있으면Poisoned는 0000 0001Stunned는 0000 0010Confused는 0100 0000이 되는 것입니다.
[System.Flags]
public enum PlayerState : byte //1byte 크기의 PlayerState 열거형 졍의
{
None = 0, //기본
Poisoned = 1 << 0, //독
Stunned = 1 << 1, //기절
Burning = 1 << 2, //화상
Frozen = 1 << 3, //빙결
Silenced = 1 << 4, //침묵
Bleeding = 1 << 5, //출혈
Confused = 1 << 6, //혼란
Charmed = 1 << 7, //매혹
}
이제 위와 같이 선언한 비트 플래그에 상태를 추가하거나 해제해야하지만
그 전에 비트 연산에 대해서 먼저 알아보겠습니다.
비트 연산
비트 연산이란 말 그대로 한개, 또는 여러개의 비트 단위 데이터를 가지고 연산을 진행해 원하는 결괏값을 도출해내는 방법입니다.
논리 연산자에 대해 아신다면 금방 이해하실 수 있습니다.
● And 연산 ( & )
두 비트 데이터의 각 자릿수를 비교해서 둘 다 1인 경우 1, 아닌 경우 0을 반환
| 데이터 1 | 1 | 1 | 0 | 0 |
| 데이터 2 | 1 | 0 | 1 | 0 |
| 결과 | 1 | 0 | 0 | 0 |
● or 연산 ( | )
두 비트 데이터의 각 자릿수를 비교해서 하나라도 1인 경우 1, 둘 다 0인 경우 0 반환
| 데이터 1 | 1 | 1 | 0 | 0 |
| 데이터 2 | 1 | 0 | 1 | 0 |
| 결과 | 1 | 1 | 1 | 0 |
● xor 연산 ( ^ )
두 비트 데이터의 각 자릿수를 비교해서 서로 다른 경우 1, 같은 경우 0을 반환
| 데이터 1 | 1 | 1 | 0 | 0 |
| 데이터 2 | 1 | 0 | 1 | 0 |
| 결과 | 0 | 1 | 1 | 0 |
● not연산 ( ~ )
각 자릿수가 1이라면 0으로, 0이라면 1로 뒤집음, 비트 반전
| 데이터 | 1 | 0 | 1 | 0 |
| 결과 | 0 | 1 | 0 | 0 |
● 왼쪽 시프트 연산 ( << )
비트를 왼쪽으로 이동
| 데이터 | 0 | 0 | 1 | 0 |
| 결과 | 0 | 1 | 0 | 0 |
● 오른쪽 시프트 연산 ( >> )
각 자릿수가 1이라면 0으로, 0이라면 1로 뒤집음, 비트 반전
| 데이터 | 1 | 0 | 0 | 0 |
| 결과 | 0 | 1 | 0 | 0 |
이제 해당 비트 연산을 이용하여 상태를 추가하거나 해제해보겠습니다.
먼저 PlayerState 타입 변수를 생성하겠습니다.
PlayerState currentPlayerState = PlayerState.None;
선언한 플레이어 상태 변수에 상태를 추가하려면 아래와 같이 플래그 값을 추가하면 됩니다.
//독 상태 추가
currentPlayerState |= PlayerState.Poisoned;
이렇게 여러 상태를 동시에 추가할 수도 있습니다.
//여러 상태 동시에 추가
currentPlayerState = PlayerState.Burning | PlayerState.Stunned | PlayerState.Bleeding
반대로 상태를 해제하고 싶다면 아래와 같이 해제하면 됩니다.
//독 상태 해제
currentPlayerState &= PlayerState.Poisoned;
함수를 이용하면 더 간편하게 상태를 추가하고 해제할 수 있습니다.
//플레이어 상태이상을 추가
private void AddPlayerState(PlayerState addState)
{
currentPlayerState |= addState;
}
//플레이어 상태이상 해제
private void RemovePlayerState(PlayerState removeState)
{
currentPlayerState &= ~removeState;
}
이렇게 플래그를 이용하여 상태이상을 관리하는 방법에 대해 알아보았습니다.
상태가 걸렸을 때 풀리는 시간, 디버프 때 부여할 능력치 패널티 등을 적용하는 등의 추가적인 기능을 위해서 각 상태를 Scriptable Object를 통해 관리하면 더 멋진 상태이상 기능을 만들 수 있을 것 입니다.
'개발, IT > 유니티' 카테고리의 다른 글
| [Unity] 오브젝트(Object), 컴포넌트(Component)와 프리팹(Prefab) (0) | 2025.10.15 |
|---|---|
| [Unity] 유니티 생명주기 (0) | 2025.10.14 |
| [Unity] ?. / ?? / ??= 연산자 (0) | 2025.09.09 |
| [Unity] DoTween을 이용한 애니메이션 만들기 (0) | 2025.09.07 |
| [Unity] NewtonSoft Json (0) | 2025.09.04 |