URP下でのSteamVR PluginV2を使用したVR開発メモ。

# はじめに
これは毎回自分のPCの中をたどりながらVR開発をするのがめんどくさくなったがための開発覚書です。後々書き足す可能性有り。
-追記
タイトルにURP下でのと入れていますがコントローラーのシェーダーを変えることしかやってません、ごめんなさい
# 本題
- もろもろのアセットを入れたらCameraRigを設置する。CameraRigの子のmodelのシェーダーはURP対応ではないので手動でLitシェーダーに変える。
- SteamVR Inputからdefaultのjsonファイルを作る。コントローラーの割り当てを変えたい場合はOpen binding UI。

--- 

***自分だけのコントローラーの設定を行いたい場合***

- 自分だけのコントローラーの設定を行いたい場合SteamVR Inputで設定を作ってあげる
- そのあとOpen Binding UIからbindの設定を行う
こんな感じ（アクションポーズ、Haptic、スケルトンも下から設定する。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366802/60b3a581-a34e-1249-1586-beedba3f6c0d.png)
-  デフォルトバインドの置換を押す（必要かはわからないけど押したところで支障はない。）
- デフォルトであるコンポーネントのBehaviour_PoseのPose Actionを自分で作った設定に適用する。
- またスクリプトでコントローラーにイベントを登録する際も自分で作った設定にすること。  
**注意事項**

- Poseの設定は必須なのでアクションポーズの設定から左手未加工にPoseを割り当てる。
- Skeltonの設定は一回ミラーを外してからスケルトンの設定で割り当てる。

---

- これでPlayすると移動できないがコントローラーが見えるようになる。
- Input系列のコードを書く  
以下使用例

```c#

using Valve.VR;
//押すボタン、Inspectorから選ぶ
public SteamVR_Action_Boolean actionButton;
//handtypeはInspectorから右か左かで選ぶ
public SteamVR_Input_Sources handtype;
//判定
if(actionButton.GetStateDown(handtype)){}

//コントローラーの動きをとる場合
SteamVR_Behaviour_Pose controllerPose;
//角度、方向
Vector3 vec3 = controllerPose.GetAngularVelocity();
//振っている力
Vector3 power = controllerPose.GetVelocity();

```

## コードの例
### Teleport
```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;

public class Teleport : MonoBehaviour
{
    public SteamVR_Input_Sources handtype;
    public SteamVR_Behaviour_Pose controllerPose;
    public SteamVR_Action_Boolean teleportAction, triggerAction;

    public GameObject laserPrefab;
    private GameObject laser;
    private Transform laserTransform;
    private Vector3 hitPoint;
    public Transform cameraRigTransform;
    public GameObject teleportReticlePrefab;
    private GameObject reticle;
    private Transform teleportReticleTransform;
    public Transform headTransform;
    public Vector3 teleportReticleOffset;
    public LayerMask layerMask;
    private bool shouldTeleport;
    // Start is called before the first frame update
    void Start()
    {
        laser = Instantiate(laserPrefab);
        laserTransform = laser.transform;
        reticle = Instantiate(teleportReticlePrefab);
        teleportReticleTransform = reticle.transform;
    }

    // Update is called once per frame
    void Update()
    {
        if (teleportAction.GetState(handtype))
        {
            RaycastHit hit;

            if (Physics.Raycast(controllerPose.transform.position, transform.forward, out hit, 100, layerMask))
            {
                hitPoint = hit.point;
                ShowLaser(hit);
                reticle.SetActive(true);
                teleportReticleTransform.position = hitPoint + teleportReticleOffset;
                shouldTeleport = true;

                if (triggerAction.GetStateDown(handtype) && shouldTeleport)
                {
                    TeleportPlayer();
                }
            }
        }
        else
        {
            laser.SetActive(false);
            reticle.SetActive(false);
        }
    }

    private void ShowLaser(RaycastHit hit)
    {
        laser.SetActive(true);
        laserTransform.position = Vector3.Lerp(controllerPose.transform.position, hitPoint, 0.5f);
        laserTransform.LookAt(hitPoint);
        laserTransform.localScale = new Vector3(laserTransform.localScale.x, laserTransform.localScale.y, hit.distance);
    }

    private void TeleportPlayer()
    {
        shouldTeleport = false;
        reticle.SetActive(false);
        Vector3 difference = cameraRigTransform.position - headTransform.position;
        difference.y = 0;
        cameraRigTransform.position = hitPoint + difference;
    }
}
```

### 物をつかむGrabObject
- この場合掴みたい物に対して投げた時に力を加えたい&&FixedJointで掴むものとをくっつけたいので、Rigidbodyを付与しておく
- 掴むものにもRigidbodyを付けておく。

```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;

public class GrabObject : MonoBehaviour
{
    public SteamVR_Input_Sources handtype;
    public SteamVR_Behaviour_Pose contollerPose;
    public SteamVR_Action_Boolean grabAction;

    private GameObject collidingObject;
    private GameObject objectInHand;


    // Update is called once per frame
    void Update()
    {
        if (grabAction.GetStateDown(handtype))
        {
            if (collidingObject)
            {
                Grab();
            }
        }

        if (grabAction.GetStateUp(handtype))
        {
            if (objectInHand)
            {
                ReleaseObject();
            }
        }
    }

    void OnTriggerEnter(Collider other)
    {
        SetCollidingObject(other);
    }

    void OnTriggerStay(Collider other)
    {
        SetCollidingObject(other);
    }
    void OnTriggerExit(Collider other)
    {
        if (!collidingObject)
        {
            return;
        }
        collidingObject = null;
    }

    private void Grab()
    {
        objectInHand = collidingObject;
        collidingObject = null;
        var joint = AddFixedJoint();
        joint.connectedBody = objectInHand.GetComponent<Rigidbody>();
    }

    private void ReleaseObject()
    {
        if (GetComponent<FixedJoint>())
        {
            GetComponent<FixedJoint>().connectedBody = null;
            Destroy(GetComponent<FixedJoint>());
            objectInHand.GetComponent<Rigidbody>().velocity = contollerPose.GetVelocity();
            objectInHand.GetComponent<Rigidbody>().angularVelocity = contollerPose.GetAngularVelocity();
        }
        objectInHand = null;
    }

    private FixedJoint AddFixedJoint()
    {
        FixedJoint fixedJoint = this.gameObject.AddComponent<FixedJoint>();
        fixedJoint.breakForce = 20000;
        fixedJoint.breakTorque = 20000;
        return fixedJoint;
    }

    private void SetCollidingObject(Collider col)
    {
        if (collidingObject || !col.GetComponent<Rigidbody>())
        {
            return;
        }
        collidingObject = col.gameObject;
    }
}
```