KeiStory

728x90
반응형

Unity 물체 잡기 (Grab Object)

 

게임상에서 아이템을 주워야 하는 경우가 있습니다.

그러기 위해서는 물체를 잡고 그 물체가 제 마우스를 따라서 움직여야합니다.

물체를 잡도록 처리하는 방법에 대해서 알아보겠습니다.

우선 잡을 물체에 Rigidbody 와 Collider 가 있어야 합니다.

잡을 물체의 Layer 에 Weapon 을 추가하여 Weapon 으로 설정합니다.

Layer 로 설정하는 이유는 Weapon 으로 설정된 오브젝트들은 잡을수 있도록 처리하기 위함입니다.

이제 Player 오브젝트에 아래의 스크립트를 추가합니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HandGrab : MonoBehaviour
{
    // 물체를 잡고 있는지 여부
    bool isGrabbing = false;
    // 잡고 있는 물체
    GameObject grabedObject;
    // 잡을 물체 레이어
    public LayerMask grabbedLayer;
    // 잡을 거리
    public float grabRange = 3f;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (isGrabbing == false)
        {
            TryGrab();
        }
        else
        {
            TryUngrab();
        }
    }

    void TryGrab()
    {
        // 잡기 버튼을 누르면 일정 영역 안에 있는 무기를 잡음
        if (XRInput.GetDown(XRInput.Button.Thumbstick, XRInput.Controller.RTouch))
        {
            // 일정 영역 안에 있는 Weapon Layer 오브젝트들을 가져옵니다.
            Collider[] hitObjects = Physics.OverlapSphere(XRInput.RHandPosition, grabRange, grabbedLayer);
            
            // 가장 가까운 무기 인덱스
            int closest = 0;

            // 아래의 코드는 가장 가까운 오브젝트를 찾습니다.
            for (int i = 1; i < hitObjects.Length; i++)
            {
                Vector3 closestPos = hitObjects[closest].transform.position;

                float closestDistance = Vector3.Distance(closestPos, XRInput.RHandPosition);

                Vector3 nextPos = hitObjects[i].transform.position;

                float nextDistance = Vector3.Distance(nextPos, XRInput.RHandPosition);

                if (nextDistance < closestDistance)
                {
                    closest = i;
                }
            }

            // 영역안에 들어온 오브젝트가 있다면
            if (hitObjects.Length > 0)
            {
                isGrabbing = true;
                grabedObject = hitObjects[closest].gameObject;

                // 물체의 부모를 손(마우스오른쪽버튼)으로 등록
                grabedObject.transform.parent = XRInput.RHand;
                
                // 물리기능 정지
                grabedObject.GetComponent<Rigidbody>().isKinematic = true;
            }
        }
    }

    void TryUngrab()
    {
        // 우클릭 마우스를 땐경우 오브젝트를 놓습니다.
        if (XRInput.GetUp(XRInput.Button.Thumbstick, XRInput.Controller.RTouch))
        {
            isGrabbing = false;
            grabedObject.GetComponent<Rigidbody>().isKinematic = false;
            // 부모를 제거하여 부모(마우스)를 따라다니지 않게 합니다.
            grabedObject.transform.parent = null;

            grabedObject = null;

            print("UnGrab!!");
        }
    }
}

위 스크립트를 보면 알수 있듯이 물체를 잡는건 마우스우클릭을 부모로 만들어 따라다니게 하면 됩니다.

그리고 우클릭을 놓는 순간 다시 부모를 제거하여 따라다니지 않게 하면됩니다.

위 스크립트의 public 필드 grabbedLayer 에 Weapon 으로 설정합니다.

결과

미사일을 잡으면 잡은 순간부터 마우스를 따라다닙니다.

놓으면 중력의 영향을 받도록 했기 때문에 미사일이 아래로 떨어집니다.

728x90
반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band