たこやき部屋

SteamVRを使って、Unityでゲームを開発したい

VRボンバーマンを作りたい その7(コントローラの振動)

VRTK Ver2.2.1の記事です。
Ver3になって使い方が色々と変わっています。ついでに名前も「SteamVR Unity Toolkit」から「Virtual Reality Toolkit」へ変わっています。
使い方はこちらの記事を参照してください。
takoyakiroom.hatenablog.com(以上、2017/02/04 追記)


はぎゃああああ!
前回アップロードしたゲーム「何でそこ間違って作ってんだ」ってとこがちょいちょいあるーー!
やっぱ最低限の動作確認はしとくべきたったのか?

とにかく気を取り直して、今回の作業のまとめ~

マップ中のブロックをちゃんと作ってみました(だが綺麗に作れたというわけではない!)
まず、雨にも関わらず部屋の外に出て壁を撮影、アレやコレや何だかんだと画像を加工してブロックのテクスチャ完成。

壊れないヤツ
f:id:takoyakiroom:20160924205915j:plain

壊れるヤツ
f:id:takoyakiroom:20160924205916j:plain
・・・なんか微妙だ、もうちょっと苔とか汚れとか付けた方がいいな
ま、細かいとろこは修正するとして、

テクスチャの作り方をWebで検索しまくっている中、ノーマルマップとかいう代物を使えばもっと良く見せる事ができるらしいことを発見。
更にノーマルマップの作り方を検索しまくって、そして色々試しに試しまくって「NormalMap Online」のサイトで変換したのを使うことに決定。Webブラウザだけでノーマルマップとか作成できる便利なサイトです。
変換元画像として使えるのはHeightMapか上下左右から光を当てた画像、変換したい画像を「クリック OR ドラッグ&ドロップ」。
これはHeightMapを変換したところ。
f:id:takoyakiroom:20160924210255j:plain

こっちは試してないけど上下左右から光を当てた画像を揃えて変換したところ。
f:id:takoyakiroom:20160924214456j:plain
ほんで「Download」を押せば、変換した結果が出てきます。らくちん!
どんな画像を使えば良いかの詳細については「?」と「!」のところをクリックです。

光を当てた画像は作るのが大変なので、元画像をグレースケールに変換してHeightMapとして使うという、3Dモデル作っている人が見たら首根っこ捕まえて振り回された挙句、剣山に叩きつけられそうなやり方で変換を実施。

そして、出来上がった画像でMaterialを作成デス。
壊れないヤツ
f:id:takoyakiroom:20160924212808j:plain

壊れるヤツ
f:id:takoyakiroom:20160924212809j:plain

動かしてみる~~~
f:id:takoyakiroom:20160924214858j:plain
うん、それっぽい、なんとなくそれっぽい。

続いて、爆弾が爆発した時にコントローラを振動させてみよう。
これは「SteamVR Unity Toolkit」の「VRTK_ControllerActions」で可能なので、このスクリプトをコントローラに追加します。
f:id:takoyakiroom:20160924231706j:plain
右コントローラも同じように追加。

「TriggerHapticPulse」のメソッドを呼び出せば振動します。

引数
ushort strength 強さ(0~3999)
float duration ブルブルしている秒数
float pulseInterval ブルる間隔。短いほど細かい、長いほど荒いブルブルになる。0.01f~0.03fあたりが程よい

引数2・3を省略するとほんのちょっとだけブルってなります。
ブルブルした時はコントローラの振動でも確認できるけど、コントローラのLEDが白っぽく光ります。

早速「CtrlListener.cs」に追加してみました。

【CtrlListener.cs】

// コントローラ振動
public void DoHapticPulse(ushort strength, float duration, float pulseInterval)
{
    VRTK_ControllerActions cntl = GetComponent<VRTK_ControllerActions>();
    if (cntl != null)           // 一応nullチェック
    {
        if (cntl.isActiveAndEnabled == true)    // コントローラの電源が入っていない場合、ここに引っかかる
        {
            cntl.TriggerHapticPulse(strength, duration, pulseInterval);
        }
    }
}

public void DoHapticPulse(ushort strength)
{
    VRTK_ControllerActions cntl = GetComponent<VRTK_ControllerActions>();
    if (cntl != null)
    {
        GetComponent<VRTK_ControllerActions>().TriggerHapticPulse(strength);
        if (cntl.isActiveAndEnabled == true)
        {
            cntl.TriggerHapticPulse(strength);
        }
    }
}

これを機にプレイヤーを管理クラス「Player」を作って、コントローラ振動用のメソッドを呼ぶ。
振動の強さが調整できるので、爆心から近いほど振動を強くしてます。

【Player.cs】

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {
    public CtrlListener left_hand;
    public CtrlListener right_hand;

    private int fire_power;             // 火力
    public int Fire_power
    {
        get { return fire_power; }
        set { fire_power = value; }
    }

    private int max_bomb;               // 爆弾置ける数
    public int Max_bomb
    {
        get { return max_bomb; }
        set { max_bomb = value; }
    }

    void Start () {
        // まだ固定値
        fire_power = 3;
        max_bomb = 5;
    }

    // 爆発
    public void Bomber(GameObject obj)
    {
        // 距離によって強さを変える
        float dist = Vector3.Distance(obj.transform.position, transform.position);
        if(dist > 12.0f)
        {
            // 12m以上離れていたら振動させない
            return;
        }
        float strong = 4000-300*dist;
        Debug.Log("dist = "+dist+", strong = "+(ushort)strong);

        // 左右のコントローラを振動
        left_hand.DoHapticPulse((ushort)strong, 0.8f, 0.02f);
        right_hand.DoHapticPulse((ushort)strong, 0.8f, 0.02f);
    }
}

作ったスクリプトは「CameraRig」にAdd。爆弾が爆発した時にこのメソッドを呼んでブルブル完成。
f:id:takoyakiroom:20160924235436j:plain


さてさて「SteamVR Unity Toolkit」ですが、新しいバージョンでは「DashTeleport」なるものが出来るようになっていました。
今まで使っていた「BasicTeleport」は、移動の時一瞬画面が暗くなって目的地へジャンプするのだが、「DashTeleport」では目的地へ滑るように移動。
これは酔いそうかと思いきや、自分は全く酔わなかったです。

使い方は、「BasicTeleport」の代わりに「DashTeleport」を使えば動きます。なお「Blink Transition Speed」は移動中に画面が暗くなる速度なので、小さい値("0"だと暗くならないので"0"でOK)を入れておかないと画面が暗くなっている途中で移動が終わり、「結局BasicTeleportと変わらねーじゃねーか!」ってなっちゃいます。
f:id:takoyakiroom:20160925220719j:plain

「BasicTeleport」についてはこの記事を参照です。
takoyakiroom.hatenablog.com


今回の最後、爆弾を置く時にどのマスに置くのか分かりにくかったので、トリガーを弾いた時に半透明の爆弾を表示、トリガーを離した時に実体化して爆発するように修正してます。
これで多少は分かりやすくなったかな。
f:id:takoyakiroom:20160925220721j:plain

ここまで出来たプログラムを置いておきますので、遊んでみてください。
https://drive.google.com/open?id=0Byq2RIkylpCQTVNqTmZKcGJCaTg