"새의 피에는 슬퍼하지만, 물고기의 피에는 슬퍼하지 않는다. 목소리 있는 자는 행복하여라." – 齊藤綠雨(사이토 료쿠)

2018/09/05

가족 관계가 아닌 오브젝트 간의 변형 정보 상속

런타임중 애니메이션을 재생 하는 모델에 특정 오브젝트를 붙이기 위해 처음에는 부모를 변경하는 방식을 사용하였으나 붙인 자식 오브젝트를 계속해서 접근하고 있는 와중에 바뀐 부모가 파괴될 경우 따로 자식 목록을 관리해서 파괴 전에 다시 의절을 시켜야 하는데 이게 순서가 꼬이면서 복잡해지는 경우가 있어(왜 이렇게 하고 있었는지는 물어보지 마세요, 부끄러우니까….) 그냥 간단하게 부모 관계는 아니나 해당 오브젝트를 부모처럼 동작하게 하는 방식으로 바꾸었습니다.

위에서 뭐라고 하고 있는지 저도 모르겠는데 그냥 간단히 말해서 오브젝트를 자식으로 안 넣고 자식처럼 이동, 회전 영향을 받는 걸 만들었습니다.

aaa(아래), bbb(중간), ccc(위) 큐브가 있고 aaa와 bbb는 가족 관계이며 ccc는 남입니다. 이 상태에서 aaa를 움직이면 당연하게 bbb만 움직이게 됩니다. 이제 ccc에 스크립트를 추가해서 bbb를 양부모로 지정을 하고 다시 aaa를 움직이면 bbb와 ccc까지 움직입니다. 코드는 아래와 같습니다.

using UnityEngine;

public class Test : MonoBehaviour {
    void Start()
    {
        _cachedTransform = transform;
    }

    void Update()
    {
        if ( null == _parent ) {
            return;
        }

        if ( !_isSet ) {
            _isSet = true;

            _localMatrix = _parent.worldToLocalMatrix * _cachedTransform.localToWorldMatrix;
        }

        Matrix4x4 matrix = _parent.localToWorldMatrix * _localMatrix;

        _cachedTransform.position = matrix.GetColumn( 3 );
        _cachedTransform.rotation = Quaternion.LookRotation( matrix.GetColumn( 2 ), matrix.GetColumn( 1 ) );
    }

    public Transform _parent = null;

    private Transform _cachedTransform = null;
    private Matrix4x4 _localMatrix = Matrix4x4.identity;
    private bool _isSet = false;
}

(크기 변형은 고려하지 않았습니다. 이 상태에서 크기까지 변형하게 되면 실제 결과물과는 다르게 변형이 됩니다. 크기까지 원하시는 분은 아래에 참고 링크를 확인해 주세요.)

먼저 양자로 지정할 오브젝트와 양부모로 지정할 오브젝트 간의 차이 행렬(_localMatrix)을 저장해 둡니다. 다음으로 프레임마다 양부모의 월드 행렬과 앞에서 저장한 차이 행렬을 곱해서 현재 행렬을 만듭니다. 여기에 추가로 변형을 하시려면 행렬을 만드셔서 뒤에 곱하거나 차이 행렬을 직접 수정해 주시면 되겠습니다.

이렇게 만든 행렬에서 네 번째 열을 뽑아서 위치로 지정하고 세 번째와 두 번째 열을 뽑아 바라보게 해서 회전을 지정합니다. 이제 양부모나 조부모, 조상들을 조작을 해보시면 양자로 지정된 오브젝트도 함께 움직이는 것을 보실 수 있습니다.


참조

http://lab.gamecodi.com/board/zboard.php?id=GAMECODILAB_Lecture&no=506&z=0

댓글 남기기 | cat > 타닥타닥 | tag > ,

댓글 남기기

* 표시된 곳은 반드시 입력해주세요