• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

앞선 강의에서 Instance와 연관 지어서

21.04.28 04:09 작성 조회수 124

0

해당 강의에서 

참조 당하는 실제 데이터는 힙에 존재하고 있고 메모리 관리자가 계속해서 확인하면서 참조 당하는지를 본다고 하셨잖아요?

여기서 playerScript의 실제 데이터를 언급하셨는데

만약에 제가 두개의 플레이어 Instance를 게임에서 만들었으면

당연히 두개의 playerScript의 실제 데이터가 다른 주소의 힙 영역에 존재하게 되고, 스택에 있는 참조 변수(?)는 그 자체에 맞는 실제 데이터를 참조하게 되는거죠?

답변 3

·

답변을 작성해보세요.

0

다시 위의 예제에서 테스트스크립트를 멤버변수로 선언했다면 이야기가 또 다릅니다. 

스타트가 실행되어 스택은 생겨나더라도 변수자체는 스택에 생기지 않습니다.

멤벼변수에 값을 대입했기에 아래 그림처럼 구조가 생겨납니다. 

public class TestScript : Monobehaviour{

    PlayerScript playerScript ; // 멤버변수

    void Start(){

        playerScript = GetComponent<PlayerScript>(); 

    }

}

0

위의 상태에서 함수 안에서 스택 변수를 생각해보면  다음과 같습니다. 

자기 자신의 플레이어 스크립트를 참조한다고 생각하면 조금 이상하므로 테스트스크립트를 하나 넣어서 확인해봐야 할것 같습니다. 

구조가 아래와 같습니다. 플레이어1만 남겨두고 그 안에 PlayerScript와 TestScript 를 넣었습니다. 

이상태를 메모리 구조를 보면 다음과 같습니다. 

이제 테스트스크립트가 있고 "스타트 함수" 안에서 playerScript 가 있습니다. 이 변수는 스타트함수의 스택에 있습니다. 그래서 playerScript 의 변수도 함수가 끝나면 없어지게 됩니다. 그래도 이것도 레퍼런스 변수이기 때문에 실체에 있는 PlayerScript 의 인스턴스를 참조하게 될 것입니다. 

public class TestScript : Monobehaviour{

    void Start(){

        PlayerScript playerScript = GetComponent<PlayerScript>(); 

    }

}

그림으로 보면 다음과 같습니다. 함수 안에서 스택이 생겨납니다. 

실제로 노란색의 사각형이 스택이고 Start 함수가 끝나면 스택과 함께 변수가 사라집니다

그래도 현재 이순간 이 플레이어 스크립트의 레퍼런스변수가 다음과 같이 실제의 PlayerScript 인스턴스를 가르킵니다.  

위의 그림과 아래의 그림을 잘 확인해보세요.(제일오른쪽의 화살표가 playerScript 의 스택변수(레퍼런스)가 실제 플레이어스크립트의 인스턴스를 가르킵니다.) 

그래서 스타트 함수 안에서 playerScript.hp = 10; 과 같은 작업을 진행할 수 있는 것입니다. 

Hyobin Kim님의 프로필

Hyobin Kim

질문자

2021.05.04

playerScript.hp = 10 이 부분에서 조금 더 확장해 나가면,

제가 만약 게임이 시작할 때 딱 한번만 HP 를 10으로 설정을 하고 싶습니다

그럼 위의 댓글 대로 해도 playerScript의 hp 변수에는 10이라는 값이 그대로 남아있는거죠?

저 경우에, PlayerScript playerscript로 선언된 Start() 내부의 참조변수는 start()가 끝나면 사라지겠지만, 어쨋거나 저 참조변수를 통해서 playerScript라는 실제 데이터(인스턴스)에 접근해서 hp라는 heap 에 존재하는 변수에 10이라는 값을 넣어준 거니까요

0

질문이 올라온 것을 몰라서 답변이 늦었습니다.

거의 맞는 것 같은데요 스택하고 멤버변수가 조금 혼돈 스러운건 아니신지 하는 생각이 듭니다. 

예를 한번 들어보겠습니다. 

플레이어1과 플레이어2의 오브젝트가 있고 각각 플레이어스크립트가 있다고 해보겠습니다. 

이경우 메모리가 다음과 같습니다. 

여기에서는 스택이 없습니다. 함수가 있고 실행되는 곳이 있을때 스택이 생겨납니다. 

또한 "플레이어1의 게임오브젝트의 변수"와 "플레이어2의 게임오브젝트의 변수" 라는 것도 사실 저희 눈에는 보이지 않습니다. 하지만 이것도 클래스이므로 레퍼런스변수이며  내부적으로 있고 유니티의 계층뷰에서 이것을 관리할 것입니다.  "실제 데이터는 플레이어1의 게임오브젝트"의 사각형입니다. 

또한 "플레이어2의 게임오브젝트라는 변수"도 레퍼런스 변수이고 유니티의 계층뷰에서 관리합니다. 실제 데이터는 "플레이어2의 게임오브젝트" 라는 사각형입니다. 

그리고 마찬가지로 각각의 게임오브젝트안에 있는 playerScript 라는 것도 이것은 레퍼런스 변수입니다.

1번변수인 playerScript 는 변수이지만 저희가 볼수 없고 이것이 레퍼런스변수 입니다. (컴포넌트로 관리되고 있죠 게임오브젝트에 부착되어 있고 이것도 클래스이므로 레퍼런스가 있고 실제 인스턴스가 있습니다.) 

1번 변수의 인스턴스는2번 사각형입니다.

마찬가지로 3번도 플레이어2에서 관리하는 컴포넌트로 되어 있으며 내부적으로 playerScript 라는 변수가 내부적으로 있을 것입니다. 실제 데이터는 4번 사각형입니다. 

그러므로 여기에 있는 파란색의 사각형 전부 다 인스턴스가 됩니다. 가비지 컬렉터가 힙으로 관리를 하겠죠.

Hyobin Kim님의 프로필

Hyobin Kim

질문자

2021.05.04

컴포넌트랑 참조변수

이렇게 표현해도 좋을까요?

게임오브젝트에 스크립트를 부착하면, 이 스크립트, 즉 이 클래스는 컴포넌트라는 인스턴스로 관리된다