여태 transform.position을 변경할 때 당연시 하던 내용이 있었습니다.
'transform.position의 x, y, z(성분, 멤버)를 수정할 수 없다.'라는 내용입니다.
다시 생각해보면 'Vector3의 x, y, z는 수정 가능한데 왜 transform.position의 x, y, z는 수정할 수 없는가?'라는 의문이 듭니다.
그렇기에 한번 살펴보았습니다.
transform.position.x를 수정할 수 없는 이유에 대해서 설명드리려면 일단 프로퍼티(속성)에 대해 아셔야 합니다. 아시고 계시다면 넘어가셔도 좋습니다.
C#에는 프로퍼티이라는 것이 존재합니다.
프로퍼티는 캡슐화의 구현 방법 중 하나입니다.
프로퍼티를 쉽게 말하면 변수에 대한 접근 지정자를 get(변수의 값을 가져올 때), set(변수의 값을 설정할 때) 설정할 수 있는 요소입니다.
단순히 get, set에 대한 접근 지정자만 설정할 수 있는 것이 아니라 코드 블록이 주어지기에 get, set할 때 무슨 동작이 일어날 지도 작성할 수 있습니다.
위의 예시 코드를 보시면 get, set할 때 코드 블록이 주어지고 특정 동작이 일어나게 작성한 것을 볼 수 있습니다.
더 자세한 내용은 문서를 살펴보시는 것이 좋습니다.
프로퍼티를 알려드린 이유는 transform.position에 프로퍼티가 사용되었기 때문입니다.
이렇게 말씀드리면 'set을 private으로 해놨나?'라고 생각하시겠지만 저희가 하지 못하는 동작은 transform.position의 수정이 아닌 transform.position의 x, y, z입니다.
그렇다면 'x, y, z의 set을 변경했을까?'라기에는 동일한 Vector3를 사용하고 있습니다.
의문을 풀기 위해선 유니티 내부 코드를 볼 필요가 있습니다.
라이더에서 볼 수 있습니다. 라이더의 디버깅을 위해 내부 코드를 볼 수 있게 해둔 거 같습니다.
새로운 Vector3를 선언하고 반환하는 것을 볼 수 있습니다.
Vector3는 구조체입니다. 구조체는 깊은 복사를 하기에 각각 독립적인 객체라고 볼 수 있습니다. ret라는 구조체를 반환한다는 것은 어느 값을 참조하기보단 새로운 객체를 반환하는 것입니다.
즉 transform.position은 복사된 값이라고 볼 수 있는 것입니다.
동작을 따라 해본 코드를 작성해 보았습니다.
Vector3의 동일하게 할당은 가능하지만 Vector3의 x를 변경할 수 없는 것을 볼 수 있습니다.
경고 문고 또한 똑같이 뜨는 것을 볼 수 있습니다.
즉 'transform.position은 복사된 임시 값을 반환하는 것이기에 구조체 멤버를 수정할 수 없다, 이는 프로퍼티의 get에서 이루어진다'라는 것입니다.
그렇다면 왜 굳이 임시 값을 반환해서 transform.position.x를 사용하지 못하게 한 걸까요?
정확히 근거가 적힌 글은 찾지 못한 거 같습니다. (추후 찾게 되면 업데이트하겠습니다)
제 추측은 transform.position의 set을 유도하기 위해서가 아닌가 싶습니다.
set을 할 때 set_position_Injected를 호출합니다.
set_position_Injected의 내부 구현까지는 보여주지 않기에 잘 모르지만 아마도 transform.position을 변경했다는 것을 기록할 수 있는 수단이 아닌가 싶기도 합니다.
transform.position이 변경되면 충돌 여부, 자식의 위치 등이 영향을 받기에 변경됨을 감지하고자 transform.position의 set을 유도한 거 같습니다.
오늘의 글에서는 transform.position.x를 사용할 수 없는 이유에 대해서 프로그래밍적인 결론은 났지만 굳이 그렇게 프로그래밍을 한 의도에 대한 결론은 나오지 않았습니다.
제가 찾아봤을 때는 공식 문서에도 의도에 대한 결론이 없었던 거 같습니다.
결국 의도는 결론이 아닌 추측으로 끝나서 아쉽지만 그래도 추측하고 정보를 찾아가는 과정 자체는 재밌었습니다.
만약 의도에 대한 정보를 가지신 분이 계시다면 댓글로 남겨주시면 감사합니다.