EasyCastleUNITY

CGV 개발일지 9(잡은 물체 위치 동기화) 본문

CGV(Castle Giant Virtual) 프로젝트 일지

CGV 개발일지 9(잡은 물체 위치 동기화)

EasyCastleT 2023. 12. 13. 23:14

https://easycastleunity.tistory.com/207

 

CGV 개발일지8 (VR 플레이어 손, 머리 위치 동기화)

전에 개발일지6 번에서는 Photon Fusion을 사용하여 멀티플레이를 구현해보고자 했었습니다. 하지만, Fusion을 사용하면, VR 플레이어를 동기화 하는 구조가 너무나도 복잡해졌습니다. 그래서, 방향을

easycastleunity.tistory.com

저번 개발일지에서는 가상현실 플레이어의 손,머리 위치 동기화에 대해 다루었습니다. 

 

이번에는 OVR의 HandGrabInteractor를 통해 잡은 물체의 위치를 동기화 해보겠습니다. 

또한 이 물체는 물리적으로 던질 수도 있는 물체입니다. 

 

그러므로 OVR의 Throw Object도 하도록 해보겠습니다. 

https://easycastleunity.tistory.com/187

 

OVR 유니티 물체 던지기(Throw an Object) 탐구

https://developer.oculus.com/documentation/unity/unity-isdk-throw-object/ Throw an Object | Oculus Developers developer.oculus.com 이 글은 위 링크의 문서를 바탕으로 작성하였습니다. 또한 Oculus Integration SDK 57.0버전을 기준으

easycastleunity.tistory.com

해당 방법은 전에 작성한 포스트를 바탕으로 구현했습니다. 

 

위 방법을 통해, 기본적인 HandGrab을 구현합니다. 

그 다음에, 네트워크 위치 동기화를 하기 위해, Photon View와 Photon Rigidbody View를  부착합니다. 

 

그리고, 동기화할 오브젝트에 NetworkGrabbable 이라는 스크립트를 작성했습니다. 

using Oculus.Interaction;
using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NetworkGrabbable : MonoBehaviour
{
    public InteractableUnityEventWrapper eventWrapper;
    public PhotonView pv;
    private Rigidbody rb;
    [SerializeField] private bool isPhysics = false;
    [SerializeField] private Collider col;

    void Awake()
    {
        this.rb = GetComponent<Rigidbody>();
    }

    private void Start()
    {
        this.eventWrapper.WhenSelect.AddListener(() =>
        {
            Debug.Log("<color=lime>Grab</color>");
            this.col.enabled = false;
            this.rb.useGravity = false;
            if (isPhysics)
                this.pv.RPC("WhenSelect", RpcTarget.Others, null);
        });
        this.eventWrapper.WhenUnselect.AddListener(() =>
        {
            Debug.Log("<color=lime>UnGrab</color>");
            this.col.enabled = true;
            this.rb.useGravity = true;
            if (isPhysics)
                this.pv.RPC("WhenUnSelect", RpcTarget.Others, null);
           
        });
    }

    void OnEnable()
    {
        PhotonNetwork.AddCallbackTarget(this);
    }

    void OnDisable()
    {
        PhotonNetwork.RemoveCallbackTarget(this);
    }

    [PunRPC]
    private void WhenSelect()
    {
        this.rb.useGravity = false;
        this.col.enabled = false;
    }

    [PunRPC]
    private void WhenUnSelect()
    {
        this.rb.useGravity = true;
        this.col.enabled = true;
    }
}

이 스크립트에서 중요한 부분은 InteractableUnityEventWrapper 입니다. 

이 wrapper를 사용하면 상호작용이 가능한 물체의 상태를 받을 수 있습니다. (ex. 물체가 잡혔다, 물체를 놓았다)

 

이 wrapper를 이용하여, PunRPC를 통해 리모트 오브젝트의 상태를 바꿀 수 있습니다.

 

ovr을 통해 물체를 잡으면, 물체는 중력이 없는 것처럼 작용을 하고, 콜라이더도 isKinemetic 처럼 작동합니다. 

하지만 생성된 Remote 오브젝트는 위치 동기화는 되지만, 중력은 그대로 작용하고, 콜라이더도 그대로 작용합니다.

 

그렇기에 RPC 함수를 통해 Remote 오브젝트의 중력과 콜라이더를 꺼줍니다. 

그리고 놓으면 다시 RPC 함수를 통해 중력과 콜라이더를 활성화 합니다. 


시연영상

Pc 시점
VR 시점