미디어 콘텐츠 스터디

Part09. 암벽 오르기(Climbing) 본문

가상현실(Virtual Reality)/가상현실 기초 다루기

Part09. 암벽 오르기(Climbing)

danmujicat 2022. 8. 13. 14:45

1. 암벽  모델 만들기

 

① 하이러키 창에 Climbing Wall 모델을 추가하고 Transform 재설정한다.
       Position(-0.95, -0.06, -2.12), Rotation(-89.98, 0, -180), 
       Scale(61.393, 61.393, 61.393)

② Climbing Wall 모델의 암벽에 머티리얼 설정한다.

 

2.  지면 이동하기

① 하이러키 창에서 XR Origin을 선택하고 인스펙터 창에서 [Add Component]버튼을 클릭하여 새로운 ContinuousMovement.cs 를 추가하여 코드를 작성하고 Input Source에 Left Hand를, Ground Layer에 Ground를 설정한다.

(만약 Layer에 Gound가 등록되어 있지 않으면 GameObject에서 Plane을 추가하여 Gound을 등록한다)

 

ContinuousMovement.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.Interaction.Toolkit;
using Unity.XR.CoreUtils;

public class ContinuousMovement : MonoBehaviour
{
    public float speed = 1;
    public XRNode inputSource;
    public float gravity = -9.81f;
    public LayerMask groundLayer;
    public float additionalHeight = 0.2f;

    private float fallingSpeed;
    private XROrigin rig;
    private Vector2 inputAxis;
    private CharacterController character;

    // Start is called before the first frame update
    void Start()
    {
        character = GetComponent<CharacterController>();
        rig = GetComponent<XROrigin>();
    }

    // Update is called once per frame
    void Update()
    {
        InputDevice device = InputDevices.GetDeviceAtXRNode(inputSource);
        device.TryGetFeatureValue(CommonUsages.primary2DAxis, out inputAxis);
    }

    private void FixedUpdate()
    {
        CapsuleFollowHeadset();

        Quaternion headYaw = Quaternion.Euler(0, rig.Camera.transform.eulerAngles.y, 0);
        Vector3 direction = headYaw * new Vector3(inputAxis.x, 0, inputAxis.y);

        character.Move(direction * Time.fixedDeltaTime * speed);

        //gravity
        bool isGrounded = CheckIfGrounded();
        if (isGrounded)
            fallingSpeed = 0;
        else
            fallingSpeed += gravity * Time.fixedDeltaTime;

        character.Move(Vector3.up * fallingSpeed * Time.fixedDeltaTime);
    }

    void CapsuleFollowHeadset()
    {
        character.height = rig.CameraInOriginSpaceHeight + additionalHeight;
        Vector3 capsuleCenter = transform.InverseTransformPoint(rig.Camera.transform.position);
        character.center = new Vector3(capsuleCenter.x, character.height / 2 + character.skinWidth, capsuleCenter.z);
    }

    bool CheckIfGrounded()
    {
        //tells us if on ground
        Vector3 rayStart = transform.TransformPoint(character.center);
        float rayLength = character.center.y + 0.01f;
        bool hasHit = Physics.SphereCast(rayStart, character.radius, Vector3.down, out RaycastHit hitInfo, rayLength, groundLayer);
        return hasHit;
    }
}

 


 하이러키 창에서 XR Origin을 선택하고 인스펙터 창에서 [Add Component]버튼을 클릭하여 Character Controller 컴포넌트 추가하고  다음과 같이 설정한다.

 

③실행하기

 

3.   손으로 암벽 잡기

  하이러키 창에 Right Hand Controller를 선택하고 인스펙터 창에서 XR Direct Interactor에서 Select Action Trigger를 State Change(또는 State)로 변경하여 설정, Interaction Layer Mask는 EveryThing 설정한다. Sphere Collider를 추가하고 Is Trigger를 체크하고 Radius는 0.1로 설정한다.

 하이러키 창에 Left Hand Controller를 선택하고 Right Hand Controller과 동일하게 설정한다.

 

4.   암벽 오르기

① 하이러키 창에 Climbing Wall 하위의 모든 객체를 선택하고 인스펙터 창에서 [Add Component] 버튼을 클릭하여 새로운 ClimbInteractable.cs 스크립트 추가하고 코드 작성한다.

ClimbInteractable.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class ClimbInteractable : XRBaseInteractable
{
    [System.Obsolete]
    protected override void OnSelectEntered(XRBaseInteractor interactor)
    {
        base.OnSelectEntered(interactor);
       // Debug.Log("SELECT ENTER");

        if (interactor is XRDirectInteractor)
            Climber.climbingHand = interactor.GetComponent<XRController>();
       
    }
    [System.Obsolete]
    protected override void OnSelectExited(XRBaseInteractor interactor)
    {
        base.OnSelectExited(interactor);
       // Debug.Log("SELECT EXIT");

         if (interactor is XRDirectInteractor)
         {
             if (Climber.climbingHand && Climber.climbingHand.name == interactor.name)
             {
                 Climber.climbingHand = null;
             }
         }
       
    }
}

② 하이러키 창에 Climbing Wall 하위의 모든 객체를 선택하고 인스펙터 창에서 [Add Component] 버튼을 클릭하여 Sphere Collider 컴포넌트 추가하고 Rigidbody 컴포넌트 추가하며 Is Kinematic  체크하고, Interaction Manager는 XR Interaction Manager 를 설정한다.
③ 하이러키 창에 Climbing Wall 하위의 모든 객체를 선택하고 인스펙터 창에서 Layer를 Grab Ignore Ray 설정한다(광선을 사용할 경우).

 

5.   지면에서 오르기

① 하이러키 창에서 XR Origin을 선택하고 인스펙터 창에서 [Add Component]버튼을 클릭하여 새로운 Climber.cs를 추가한다.

Climber.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;
using UnityEngine.XR.Interaction.Toolkit;

public class Climber : MonoBehaviour
{
    private CharacterController character;
    public static XRController climbingHand;
    private ContinuousMovement continuousMovement;

    // Start is called before the first frame update
    void Start()
    {
        character = GetComponent<CharacterController>();
        continuousMovement = GetComponent<ContinuousMovement>();
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if (climbingHand)
        {
            continuousMovement.enabled = false;
            Climb();
        }
        else
        {
            continuousMovement.enabled = true;
        }
    }

    //Climbing Computations
    void Climb()
    {
        InputDevices.GetDeviceAtXRNode(climbingHand.controllerNode).TryGetFeatureValue(CommonUsages.deviceVelocity, out Vector3 velocity);

        character.Move( -velocity * Time.fixedDeltaTime);
    }
}

 

② 암벽 오를때 방향 회전하도록 Climber.cs 코드 수정하기

Climber.cs

...

public class Climber : MonoBehaviour
{
   ....
    //Climbing Computations
    void Climb()
    {
        InputDevices.GetDeviceAtXRNode(climbingHand.controllerNode).TryGetFeatureValue(CommonUsages.deviceVelocity, out Vector3 velocity);

        character.Move(transform.rotation * -velocity * Time.fixedDeltaTime);
        
    }
}

③ 실행하기

 

Comments