[Unity] SetParent 하지 않고 부모 따라가는 오브젝트 만들기 (FollowObject / Move object without parenting)
본문 바로가기
프로그래밍/Unity

[Unity] SetParent 하지 않고 부모 따라가는 오브젝트 만들기 (FollowObject / Move object without parenting)

by [아마군] 2023. 4. 19.
반응형

 

게임을 개발하다보면 런타임에서 SetParent 를 통해 특정 오브젝트의 부모를 다른 오브젝트로 바꿔야 하는 경우가 자주 발생한다.

 

예를 들어 손에 장착하는 검이 있다고 했을 때 원래는 이 검은 독립된 하나의 Prefab 일 뿐이지만 유저가 검을 선택하면 Instantiate 한 후 오른손 Bone 또는 적당한 위치의 더미 노드에 SetParent 를 해서 그 뼈의 transform을 이어받게 해줘야 한다.

 

그런데 요즘 유행하는 메타버스 처럼 아바타의 커스터마이징이 자유롭고 다양한 악세사리나 사물을 착용하되 특성상 Scale 은 부모를 따라가지 않고 고유의 크기를 유지해야 하는 등의 특수한 경우가 간혹 있다.

 

즉, SetParent 는 하지 않고 부모 노드의 위치 및 회전값 등 특정 정보만을 이어받고 싶은 경우 계층 구조로 연결하지 않고 LateUpdate() 에서 부모 노드의 Transform 을 가져와 업데이트 시켜주면 되는데 이때 오브젝트가 바로 부모 노드에 부착되는 게 아니라 고유한 Offset 을 가지는 경우 추가적인 계산이 필요하다.

 

특히 이 Offset 을 런타임에서 수정할 수 있다면 더욱 신경을 써야 한다.

 

public class FollowObject : MonoBehaviour
{
	public Transform Parent;//Remember to assign the parent transform
	private Vector3 pos, fw, up;
    
    //Specifies the parent node to follow
	public void SetParent(Transform parent)
	{
		Parent = parent;
		SetDefaultValue();
	}
    
    //If Offset is changed, Transform is calculated again.
	public void SetDefaultValue()
	{
		pos = Parent.transform.InverseTransformPoint(transform.position);
		fw = Parent.transform.InverseTransformDirection(transform.forward);
		up = Parent.transform.InverseTransformDirection(transform.up);
	}
    
	void LateUpdate()
	{
		var newpos = Parent.transform.TransformPoint(pos);
		var newfw = Parent.transform.TransformDirection(fw);
		var newup = Parent.transform.TransformDirection(up);
		var newrot = Quaternion.LookRotation(newfw, newup);
		transform.position = newpos;
		transform.rotation = newrot;
	}
}

이 컴포넌트를 부착하기를 희망하는 오브젝트에 추가 해준다.

 

간단하게 설명하자면, 처음에 부착될 때 SetParent() 함수로 부착할 부모 노드를 지정해 준다.

 

그리고 부착된 오브젝트의 Offset 이 런타임에 변경된다면, 부모 노드로부터의 위치를 다시 계산해 줘야 하므로 Offset 이 변경된 순간 SetDefaultValue() 함수를 호출해 줘야 한다.

 

마지막으로 LateUpdate() 에서 매 프레임 부모 노드의 Transform 에서 저장된 Offset 만큼 이동한 position 과 rotation 을 계산해서 적용한다.

 

반응형

댓글