😽

[Unity x MetaQuest2]VRでスパイーダーマン風に移動する

2022/09/24に公開約2,500字

概要

Oculus Integrationの標準の移動方法(ジョイスティック、テレポートでの移動)以外に、何か面白い移動方法を作れないかなと思い、某スパイターマンっぽく、ビルの合間を颯爽と駆け抜ける移動方法を実装してみました。

イメージ
※今後追加予定

実装方針

通常の3Dオブジェクトに、OVRCameraRigをつける

これ結構重要でした。
OVRControllerを使いたくなりますが、今回は物理演算を使うので、通常の3Dオブジェクトを使った方が制御がしやすいです

Rayを当てる

飛び移るボックスを当てる

ボタンを押したら、バネ移動をする

スパイダーマンっぽく移動するために、弧を描くように移動したいですね
これは、SpringJointを使って、実現させます

https://docs.unity3d.com/ja/2021.3/Manual/class-SpringJoint.html

実装

オブジェクトの設定

まずは必要なオブジェクトを、Unityで設定していきます

プレイヤーオブジェクト

  1. 適当なオブジェクトを用意し、Rigidbodyをアタッチします
  2. ConstraintsのFreeze Rotationに全てチェックします
    ※これを設定しないと、大変なことになります!?試してみてください
  3. 子オブジェクトにOVRCameraRigを置きます
  4. LineRendererと、作成するRayControllerをアタッチします

糸を引っ掛けるBlockオブジェクト

  1. オブジェクトはなんでも良いですが、ここではCubeを置いていきます
  2. TagをBlockに変更します
    これにより、糸を引っ掛けることができるオブジェクトかを見分けます

Ray

ここからはScript部分です。
Rayを当てて、ボタンを押したときに、対象オブジェクトかを判断し、対象であれば次のSpringJointを繋げる関数を呼ぶ

void Update()
{
	RaycastHit hit;
	// Rayを設定 原点, 方角
	Ray ray = new Ray(anchor.position, anchor.forward);
	// lineの始点
	lineRenderer.SetPosition(0, ray.origin);
	
	if(Physics.Raycast(ray, out hit, maxDistance))
        {
            // lineの終点
            lineRenderer.SetPosition(1, hit.point);
            GameObject target = hit.collider.gameObject;
 
            // 人差し指を押した場合
            if(OVRInput.GetDown(indexTrigger))
            {
                if(target.CompareTag("Block"))
                {
                    LaunchWire(target, lineRenderer);
                }
            }
        }
        else
        {
            // 初期状態に戻す
            lineRenderer.SetPosition(1, ray.origin + (ray.direction * maxDistance));
            lineRenderer.startColor = normarColor;
            lineRenderer.endColor = normarColor;
        }
}

SpringJoint

Rayが当たっているオブジェクトとプレイヤーオブジェクトに、SpringJointを接続します
関数を用意して、トリガーがあったら呼び出してあげるだけです

void ConnectWireCoroutine(GameObject target)
{
	// プレイヤーと、対象オブジェクトをSpringJointで接続する
	springJoint = player.AddComponent<SpringJoint>();
	springJoint.connectedBody = target.GetComponent<Rigidbody>();
	springJoint.autoConfigureConnectedAnchor = false;
	springJoint.anchor = new Vector3(0f, 1f, 0f);
	springJoint.connectedAnchor = new Vector3(0f, -0.5f, 0f);
	springJoint.spring = 20f;
	springJoint.damper = 0.5f;
}

SpringJointを解除するには、ComponentをDestroyするだけです

void DestroyWireCoroutine()
{
	if(springJoint != null)
	{
	    Destroy(springJoint);
	}
}

調整

バネを利用した動きは、物理演算で動いています
イメージと違う動きになる場合は、以下を調整すると良いです
Player RigidbodyのMass, Drag, Angular Drag
Spring Jointのspring, damper

参考

Discussion

ログインするとコメントできます