C# 메모리 관리 – 스태틱 변수 Static Variable
C# 메모리 관리 – 스태틱 변수 Static Variable
스태틱 변수 Static Variable
초보자 분들 중에 많은 분들이 아래와 같은 실수를 합니다:
public static int health; void Start() { health = 100; }
그리고 다른 스크립트에서 아래 예제와 같이 사용하는 것을 찾을 수 있습니다.
void OnCollisionEnter(Collision other) { if (other.gameObject.tag == “Enemy”) { EnemyScript.health -= 10; if(EnemyScript.health <= 0) Destroy(other); } }
적군이 하나인 게임에서 적을 물리치는 데 성공했습니다. 그 다음 더 많은 적군을 추가했지만 적군이 갑자기 죽기 때문에 의아해 합니다.
왜 그럴까요? 이유는 간단합니다. Enemy 클래스 타입의 여러 인스턴스들이 있지만, 모든 인스턴스들이 하나의 health 인스턴스를 공유하기 때문입니다. 따라서 적군을 하나 죽이면 모든 적군이 죽게됩니다.
사실, 클래스 내에 선언된 스태틱 변수는 그 객체에 포함되어 있지 않고 클래스 자신에 포함됩니다. 그렇기 때문에 스태틱 변수에 접근할 때 인스턴스 이름이 아닌 클래스 이름을 이용해서 접근하는 것입니다.
따라서 위의 예제는 Enemy의 체력으로서의 역할을 하지 못합니다. 모든 적군은 자기 자신의 체력 값이 필요하기 때문이지요.
스태틱 변수는 스태틱 클래스가 선언된 뒤 처음 호출됐을 때 인스턴스가 생성되는 것과 유사합니다. 스태틱 변수 역시 처음 접근할 때 생성됩니다. 다시 말해서, 게임 내에 클래스 인스턴스가 없다 하더라도 스태틱 변수에 접근을 했다면 변수가 존재할 수 있다는 말입니다.
게임에서 적군의 수를 추적하기 위해서, 적군 수를 세는 counter가 있다고 가정해보겠습니다.
static var counter; public void CreateEnemy() { GameObject obj = Instantiate( enemyPrefab, new Vector3(0,0,0). Quaternion.identity ); if(obj) counter++; } public void DestroyEnemy() { Destroy(gameObject); counter--; }
이 스크립트는 Enemy에 각각 추가되었습니다. 이렇게 구성된 Enemy들은 서로 다른 스크립트를 가지고 있지만, 모두 같은 counter 변수를 공유합니다.
이 함수를 사용해서 적군의 수를 추적하는 것이 가능해졌습니다. 여기서 주의할 점이 있습니다. 적군을 생성하는 과정에서 객체 생성을 성공하지 못하는 경우가 생길 수 있습니다(heap fragmentation 등의 이유로). 이 경우, null 참조 null reference 를 반환하게 됩니다. 확인 과정 없이 단순히 counter 값을 증가시키게 되면, 어떤 이유로 인스턴스 생성에 실패했을 때, counter 값에 문제가 생기게 됩니다. 이 때 다음과 같이 레벨을 끝내고 새 레벨을 로딩하기 위해서 counter 값을 확인해보면:
if(counter <= 0) Application.LoadLevel(nextLevel);
모든 적군을 다 죽인 뒤의 counter 값은 1이 되고, 게임은 버그를 갖게 됩니다. 따라서 객체를 생성한 뒤의 인스턴스 생성이 실패하지 않았는 지 확인해야합니다.
게임의 플레이어는 어떨까요? 스태틱 health 를 사용할 수 있을까요? 물론, 플레이어의 체력을 처리하기 위해서 스태틱 변수를 사용할 수 있습니다. 사실, 스태틱 변수에 접근하는 것이 클래스 인스턴스의 멤버에 접근하는 것보다 효율적입니다.
인스턴스의 멤버에 접근하면, 컴파일러는 특정 함수를 호출해서 해당 객체가 존재하는 지 여부를 확인해야 합니다. 이 과정은 해당 객체가 존재하지 않으면 데이터를 변경하는 등의 작업을 할 수 없기 때문에 굉장히 타당한 과정이라고 할 수 있습니다.
내용 끝까지 읽어주셔서 감사합니다.
배너 클릭은 저에게 많은 힘이 됩니다.
감사합니다 🙂