C언어의 사용자 정의 자료형에는 구조체 struct, 공용체 union, 열겨형 enum이 있지만
C#에선 셋중 공용체가 없어서 구조체 struct와 열거형 enum만 있다.
물론 공용체를 쓰고 싶으면 아래의 글에서 편법으로 쓸 수 있다고 한다. ↓
오늘은 구조체만 한번 다뤄보자
#1 구조체 struct
구조체란 하나 이상의 변수들을 묶어서 그룹으로 만드는 사용자 정의 자료형이다.
사용 목적 자체는 변수들을 그룹화하고 값형식이라 값으로써 사용하기 위한거다.
게임을 만들 때 플레이어의 스탯을 그룹으로 만든다면 참조하여 쓰기 편리하다.
이제 구조체를 정의해볼건데 구조체 정의한다는건 구조체 이름, 구조체 멤버 변수를 만든다는 뜻이다.
//* 접근제한자 struct 구조체 이름
public struct Player
{
public int Health {get; set;} //* 프로퍼티 get set
public float Mana; //* 멤버 변수
public void Dead() //* 멤버 메서드(함수)
{
if(Health <= 0)
{
bool isDead = true;
}
}
}
접근제한자 뒤에 struct 키워드를 쓰고 구조체 이름을 쓰면 된다.
구조체 안에는 생성자, 프로퍼티, 멤버 변수, 멤버 메서드(함수), 이벤트가 올 수 있다.
이렇게 정의한 구조체의 사용 방법은 간단하다.
private void Start()
{
Player player;
player.Health = 0;
player.Mana = 0;
player.Dead();
}
클래스 내에 함수에서 구조체를 선언해서 사용하면 되는데 실제로 위에처럼 하면 에러가 뜰 것이다.
이유는 Dead()와 Health가 각각 메서드(함수)와 프로퍼티인데 이것들이 할당을 안했다고 에러가 계속 뜬다.
이럴 때 구조체 고유의 인스턴스를 만들고 다시 할당하면 된다. 즉 재할당을 해주면 된다.
private void Start()
{
Player player;
player = new Player(); //인스턴스 생성
player.Health = 0;
player.Mana = 0;
player.Dead();
}
이런식으로 하면 된다.
위에서 메서드와 프로퍼티만 에러 뜬다고 했는데 값형식 다 인스턴스 생성해 재할당 해줘야한다.
멤버 변수는 변수가 참조타입(클래스)같은거만 아니라면 꼭 재할당 안해도 되는거같다.
근데 Player player을 Start함수가 아닌 더 위에서 선언하면 에러가 안뜨던데 왜그런진 모르겠다.
그리고 위에서 말한거처럼 구조체안에는 이벤트도 올 수 있다.
//* 접근제한자 struct 구조체 이름
public struct Player
{
public int Health {get; set;} //* 프로퍼티 get set
public float Mana; //* 멤버 변수
public void Dead() //* 멤버 메서드(함수)
{
if(Health <= 0)
{
bool isDead = true;
}
}
public event EventHandler OnEvent; //* 이벤트 핸들러
public void InvokeEvent() //* 이벤트 실행을 위한 멤버 메서드(함수)
{
if (OnEvent != null)
{
OnEvent(this, EventArgs.Empty);
}
}
}
void Start()
{
Player player = new Player(); //* 인스턴스 생성
customEventStruct.OnEvent += CustomEventHandler; //* 이벤트 구독
customEventStruct.InvokeEvent(); //* 이벤트 실행 메서드 호출
}
구조체안의 이벤트는 어디다 써야할지 감이 안온다.
아무튼 구조체는 상속이 불가능한데 Interface 구현은 가능하다.
그럼에도 구조체를 사용하는 이유는 위에서 말한 것처럼
일반적으로 클래스보다 가볍고 속도가 빠르고 데이터를 저장하고 전달하는데 효과적이기 때문이다.
그 이유는 아래 사진에서 스택 부분에 저장되기 때문이다.
구조체는 값 형식이기 때문에 스택 영역에 저장되어 메모리 할당과 해제가 간단하고 빠르다.
또한 구조체는 스택 메모리에 저장되므로 클래스와는 달리
힙 메모리를 사용하지 않아 가비지 컬렉션 부하가 발생하지 않는다.
근데 이게 오히려 독이 될 수도 있는데
구조체의 크기가 너무 커지거나 구조체 인스턴스를 불필요하게 많이 생성하면
스택 메모리가 과도하게 사용될 수 있는데 그러면 스택 오버플로 발생할 수 있다.
그냥 적당하게 상황에 따라서 최대한 적게 쓰면 될듯하다.
위에서 구조체는 값 형식이라고 했는데 그러면 클래스는 무슨 형식일까?
클래스는 참조형식으로써 데이터의 실제 값이 메모리 공간을 가지지 않는다.
참조 형식의 인스턴스(클래스)는 힙 메모리에 저장된 데이터를 참조만한다.
때문에 메모리 할당과 해제가 복잡하고 가비지 컬렉션에 의해 메모리 관리가 이루어진다.
그리고 구조체와 다르게 상속, 다형성 등을 지원한다.
아무튼 구조체를 알아보는 김에 클래스도 다시 알게 된 것 같다.
구조체도 상황에 따라서 유연하게 쓰도록 하자
#2 구조체 struct 배웠으니까 활용법도
이제 유니티에서 구조체를 사용할만한 예시를 몇가지 보자
1. 색 구조체
우선 색 구조체 하나를 만들어보자 ↓
public struct Color {
public float r, g, b, a;
public Color(float r, float g, float b, float a) {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
}
그 다음 나만의 색을 저장할 구조체를 선언하자 ↓
Color red = new Color(1, 0, 0, 1);
Color green = new Color(0, 1, 0, 1);
위에서 구조체를 설명할 때 값 형식이라고 했기 때문에 이런식으로 값 저장식으로 활용하면 좋다.
개인적으로 저렇게 저장해둔 컬러 값처럼 카메라 필터 값을 저장해 필요한 상황에 쓰는것도 좋겠다고 생각함
2. 캐릭터 스탯 구조체
struct CharacterAttributes
{
int health;
int attackPower;
int defensePower;
}
CharacterAttributes myCharacterAttributes = new CharacterAttributes();
myCharacterAttributes.health = 100;
myCharacterAttributes.attackPower = 50;
myCharacterAttributes.defensePower = 20;
일반적으로 캐릭터 스탯을 이렇게 저장하는듯하다.
번외) ChatGPT가 알려준 애니메이션 정보 저장 구조체
struct AnimationInfo
{
string animationName;
float speed;
bool loop;
}
AnimationInfo myAnimationInfo = new AnimationInfo();
myAnimationInfo.animationName = "Run";
myAnimationInfo.speed = 1.5f;
myAnimationInfo.loop = true;
이렇게 말고도 활용할 부분은 굉장히 많을듯하다.
구조체..생각보다 강한거같다
'유니티 > 유니티 관련 지식' 카테고리의 다른 글
유니티 제네릭<T> 간단하게 정리 (0) | 2023.03.29 |
---|---|
유니티 Canvas의 World Space 렌더 모드로 UI 만들기 (0) | 2023.03.19 |
유니티 오브젝트를 카메라 바라보게 만들기 (0) | 2023.03.12 |
유니티 TextMeshPro 머티리얼(Material) 오류 해결하기 (0) | 2023.03.05 |