C# 메모리 관리 – 스태틱 변수 Static Variable

C# 메모리 관리 – 스태틱 변수 Static Variable

memory management

 

스태틱 변수 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 를 사용할 수 있을까요? 물론, 플레이어의 체력을 처리하기 위해서 스태틱 변수를 사용할 수 있습니다. 사실, 스태틱 변수에 접근하는 것이 클래스 인스턴스의 멤버에 접근하는 것보다 효율적입니다.

인스턴스의 멤버에 접근하면, 컴파일러는 특정 함수를 호출해서 해당 객체가 존재하는 지 여부를 확인해야 합니다. 이 과정은 해당 객체가 존재하지 않으면 데이터를 변경하는 등의 작업을 할 수 없기 때문에 굉장히 타당한 과정이라고 할 수 있습니다.

 

내용 끝까지 읽어주셔서 감사합니다.
배너 클릭은 저에게 많은 힘이 됩니다.
감사합니다 🙂

 

RonnieJ

프리랜서 IT강사로 활동하고 있습니다. 게임 개발, C++/C#, 1인 기업에 관심이 많습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Please turn AdBlock off

Notice for AdBlock users

Please turn AdBlock off