BlenderとUnityで作ったものをVR(Meta Quest/Oculus Link)で動かします

VRで焚き火する #12 薪オブジェクトを大量に生成する【Unity】

 
 
いま使っているUnityプロジェクトでは、Scene上に配置されている薪オブジェクトは20本程度。
ですが、焚き火する時は何本も予備が必要になります。
UnityをPlay時に、林エリアに薪オブジェクトをランダム生成してそれを拾ってくることも考えましたが、若干めんどうです。
 
今回は、コントローラーのトリガーを押すと薪を生成するよう実装してみます。これで焚き火し放題です!



開発環境

・Unity 2020.3.13f1(High Definition RP 10.5.0)
・グラボ:ASUS ROG-STRIX-RTX2060S-O8G-GAMING
・Meta Quest 2(Oculus Link利用)
・炎アセット:Ignis – Interactive Fire
 

(1) 薪オブジェクトを生成する

薪オブジェクトをイチから作るのは大変ですので、あらかじめ作成しておいたオブジェクトを複製する方法でやってみます。
 

複製元の薪オブジェクトを準備する

まずは、複製元になる薪オブジェクトを準備します。
と言っても、複製したいオブジェクトを適当に決めて、複製元にふさわしい設定をするだけ。
例えば、複製した時点では自動的に火がつく必要はありませんので「Set This On Fire On Startのチェックは外す」などですね。
 
あとは、Scene上に見えていると、複製元オブジェクトも焚き火に使ってしまいそうですので、非アクティブ状態にしておきます。
複製する時にアクティブにするので問題ありません。
 

スクリプトに追加する

以前の記事でやったのと同じく、複製元オブジェクトをスクリプトから呼びやすくするために、「OVRCameraRig にアタッチしているスクリプト」に以下の処理を追加します。いまのUnityプロジェクトでは TransformMover.cs でしたね。
 
[TransformMover.cs]
[SerializeField]
private Transform OriginalWood;     // オリジナル薪
 

Inspectorでオブジェクトを割り当てる

最後に、複製元オブジェクトを先ほどスクリプトに追加した変数に登録します。
変数定義時に [SerializeField] を指定したことで Inspector上に項目が増えてますので、そこに追加します。
 


(2) 薪オブジェクトを複製する

これで基本的な設定ができました。
ここからは、トリガーを押した時に薪オブジェクトを複製する処理を実装をしていきます。実装先は、LateUpdateメソッドです。
 

左ハンドトリガーを押している時の処理

まずは、トリガーを押した時の実装です。
Instantiateメソッドでオブジェクトを複製し、大きさや位置を調整していますよ。
 
// 左ハンドトリガーを押した時
if (OVRInput.GetDown(OVRInput.Button.PrimaryHandTrigger, OVRInput.Controller.Touch))
{
    // 薪を複製する
    Transform wood = Instantiate(OriginalWood);
    wood.position = LeftHandAnchor.position;
    wood.rotation = LeftHandAnchor.rotation;

    // 大きさをランダム変更
    float adjust = (Random.Range(-30f, 30f)) / 100f;
    wood.localScale += new Vector3(adjust, adjust, adjust);

    // コントローラで掴む
    wood.parent = LeftHandAnchor.transform;
    wood.GetComponent<Rigidbody>().useGravity = false;
    wood.GetComponent<Rigidbody>().isKinematic = true;

    // 掴む位置を調整
    wood.localPosition = new Vector3(0.075f, -0.16f, -0.01f);
    wood.localRotation = Quaternion.Euler(18.8f, 9.56f, -11.4f);

    wood.gameObject.SetActive(true);
}
 
2行目で、左コントローラーの「ハンドトリガー」が押されたことを検知。OVRInput.Get でなく OVRInput.GetDown を使っているので、トリガーを押しっぱなしではなく、一回押した時だけに反応します。
 
5行目で、Instantiateメソッドによって、オブジェクトが複製されます。
6,7行目で、複製した薪オブジェクトの座標を左コントローラの座標と同じにします。
 
10,11行目で、複製したオブジェクトの大きさをランダムで変更します。実世界の薪は大きさが異なりますので、それを表現してみました。±30%くらいの幅ですね。
 
14~16行目で、薪オブジェクトの親を「コントローラ」に設定することで「つかんだ状態」にしています。useGravity と isKinematic を設定するのも以前の記事と同じです。
 
19,20行目で、薪オブジェクトをつかむ座標と回転角を調整します。
 
22行目で、薪オブジェクトをアクティブにします。これで「コントローラー内に薪オブジェクトが生成された」ように見えます。
 

(参考)薪オブジェクトの位置調整

参考までに、19,20行目で座標と回転角を調整する前後の画像です。
 
まずは調整前です。
薪オブジェクトの根本部分を持ってます。少しバランスが悪いですね。
 
持つ位置を少し上にして、薪も持ちやすく見えるよう回転してみました。
 
これで良いですね。
 
設定時には、localPosition と localRotation を使っていますので、親オブジェクト(左コントローラ)からの相対値になります。便利ですね。
 

左ハンドトリガーを離した時の処理

次に、トリガーを離した時の実装です。
つかんだ物を離すだけですので、以前の記事とほぼ同じ処理です。
 
// 左ハンドトリガーを離した時
if (OVRInput.GetUp(OVRInput.Button.PrimaryHandTrigger, OVRInput.Controller.Touch))
{
    // 掴んでいる物を離す
    for (int i = 0; i < LeftHandAnchor.transform.childCount; i++)
    {
        var child = LeftHandAnchor.transform.GetChild(i);
        if (child.CompareTag("Grab"))
        {
            child.parent = null;
            child.GetComponent<Rigidbody>().useGravity = true;
            child.GetComponent<Rigidbody>().isKinematic = false;
        }
    }
}
 
10行目で、parent に null を代入することで、オブジェクトの親子関係を無くしています。
11,12行目で、重力と物理演算の影響をオンに戻してます。
 
これで完了です。
 

(3) 動画で確認してみる

VRモード(Oculus Link)で操作してみました。
 

薪オブジェクトを大量に複製する

動画で確認してみます。
 
薪オブジェクトを大量に複製することができました。コントローラーから無限に薪が出てくるのが魔法みたいで面白い
 


まとめ 

コントローラから薪オブジェクトを大量に複製してみました。
 
これで焚き火し放題になりましたよ。
 
次回は、薪オブジェクトが燃えた後の処理を調整します。いまは、薪オブジェクトが燃え尽きると「ぱっと消えてしまう」ので、じわじわ小さくなるよう実装してみます。
 
スポンサーリンク

コメント

  • トラックバックは利用できません。

  • コメント (0)

  1. この記事へのコメントはありません。

VRで焚き火する #11 コントローラーからレーザーを出して薪をつかむ【Unity】

VRで焚き火する #13 薪を燃やして時間経過でじわじわ小さくする【Unity】


最近のコメント

だーしゅ
IT関係のお仕事してます。
3Dモデルの女の子は「ブログノ・スージー」。VRは楽しいですね。

[当ブログについて]