Unity一覧

WallpaperEngineの壁紙をUnityのWebGLで作るためのメモ

WallpaperEngineの壁紙をUnityで作成する場合、Windowsの実行形式(.exe)で出力すれば手軽に作成することができます。
しかし、Web形式(HTML)以外ではWallpaperEngineで壁紙を設定する際のプロパティを作成者で任意に作成できないため、ユーザにパラメータ変更を委ねたいときに面倒です。
UnityにはWebGLで出力する機能もあり、そちらをWallpaperEngineに使用する方法を調べたのですが、まとまった情報がなかったのでメモしておきます。

以下はUnity Ver 2017.1 で確認した内容です。

WebGLテンプレート

WallpaperEngineで表示した時に表示を最大化し、必要なJavascript外部ファイルを読み込むためHTMLのテンプレートを設定します。

参考: Unity – Manual: Using WebGL Templates

配置 : Assets > WebGLTemplates > (任意の名前) > index.html

<!DOCTYPE html>
<html lang="en-us">

  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Unity WebGL Player | %UNITY_WEB_NAME%</title>
    <script src="PropertyScript.js"></script>
    <script src="%UNITY_WEBGL_LOADER_URL%"></script>
    <script>
      var gameInstance = UnityLoader.instantiate("gameContainer", "%UNITY_WEBGL_BUILD_URL%");
    </script>
    <style>
      body {
        overflow: hidden;
        margin: 0;
        padding: 0;
        background-color: black;
      }
    </style>
  </head>
  <body>
    <div id="gameContainer" style="width: 100%; height: 100%; position: absolute;"></div>
  </body>
</html>

Edit > Project Settings > Playerから追加したテンプレートを選択しておくこと。

WallpaperEngineで読み込むプロジェクトファイル

プロパティの値が定義されています。
プロパティ部分は、WallpaperEngineの作成ガイドにあるテンプレと同様です。

参考: Advanced: Web user customization

配置 : ビルド先 > project.json

{
    "file" : "index.html",
    "preview" : "prev.png",
    "general" : 
    {
        "properties" : 
        {
            "customcolor" : 
            {
                "text" : "User accent",
                "type" : "color",
                "value" : "0.2 0.8 1"
            },
            "schemecolor" : 
            {
                "text" : "Scheme color",
                "type" : "color",
                "value" : "0.7 0.2 0.1"
            },
            "custombool" : 
            {
                "text" : "User bool",
                "type" : "bool",
                "value" : false
            },
            "customint" :
            {
                "text" : "User slider",
                "type" : "slider",
                "value" : 50,
                "min" : 0,
                "max" : 100
            },
            "customcombo" :
            {
                "text" : "User combo",
                "type" : "combo",
                "value" : 1,
                "options" :
                [
                    {
                        "value" : 1,
                        "label" : "First"
                    },
                    {
                        "value" : 2,
                        "label" : "Second"
                    },
                    {
                        "value" : 3,
                        "label" : "Third"
                    }
                ]
            }
        }
    },
    "title" : "WebGL Template",
    "type" : "web"
}

プロパティを受け取るスクリプト

WallpaperEngineのプロパティはブラウザ?のJavascriptに用意した特定の関数が呼び出されることで受け渡しをするため、Unityのエディタとは別にスクリプトを用意します。
後述する「Javascript->C#」間の値の受け渡しの都合から、格納する値をINT型にしています。

参考: Advanced: Web user customization

配置 : ビルド先 > PropertyScript.js

var WALLPAPER_ENGIN_PROPERTY = WALLPAPER_ENGIN_PROPERTY || {};
window.wallpaperPropertyListener = {
    applyUserProperties: function(properties) {
        // Read scheme color
        if (properties.schemecolor) {
            WALLPAPER_ENGIN_PROPERTY.schemecolor = PropertyColorToInt(properties.schemecolor.value);
        }

        // Read custom color
        if (properties.customcolor) {
            WALLPAPER_ENGIN_PROPERTY.customcolor = PropertyColorToInt(properties.customcolor.value);
        }

        // Read custom boolean
        if (properties.custombool) {
            WALLPAPER_ENGIN_PROPERTY.custombool = PropertyBoolToInt(properties.custombool.value);
        }

        // Read custom slider
        if (properties.customint) {
            WALLPAPER_ENGIN_PROPERTY.customint = properties.customint.value;
        }

        // Read custom combo box
        if (properties.customcombo) {
            WALLPAPER_ENGIN_PROPERTY.customcombo = properties.customcombo.value;
        }

        function PropertyColorToInt(colorValue){
            var Colors = colorValue.split(' ');
            colorInt = Math.ceil(Colors[0] * 255) * 1000 * 1000;
            colorInt += Math.ceil(Colors[1] * 255) * 1000;
            colorInt += Math.ceil(Colors[2] * 255);
            return colorInt;
        }

        function PropertyBoolToInt(boolValue){
            return Number(boolValue);
        }
    }
};

WebGLからブラウザのJavascript関数を呼び出すプラグイン

WebGLからブラウザのJavascriptの関数を呼び出せるよう、プラグインとしてスクリプトファイルを作成します。

参考: Unity – マニュアル: WebGL: ブラウザのスクリプトと通信を行う

配置 : Assets > Plugins > WebGL > PropertyPlugin.jslib

var PropertyPlugin = {
    GetSchemeColor: function()
    {
        return WALLPAPER_ENGIN_PROPERTY.schemecolor;
    },
    GetCustomColor: function()
    {
        return WALLPAPER_ENGIN_PROPERTY.customcolor;
    },
    GetCustomBool: function()
    {
        return WALLPAPER_ENGIN_PROPERTY.custombool;
    },
    GetCustomInt: function()
    {
        return WALLPAPER_ENGIN_PROPERTY.customint;
    },
    GetCustomCombo: function()
    {
        return WALLPAPER_ENGIN_PROPERTY.customcombo;
    }
};

mergeInto(LibraryManager.library, PropertyPlugin);

WebGLからブラウザのJavascript関数を呼び出すスクリプト

Asset内の任意の場所に保存し、適当なオブジェクトでコンポーネントとして呼び出し。
マニュアルにINT型とString型を呼び出す方法しかなかったため、全てINTでやり取りしています。
以下の例ではUI>Textオブジェクトにプロパティで取得した値を反映しています。

参考: Unity – マニュアル: WebGL: ブラウザのスクリプトと通信を行う

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using System;

public class PropertyTestScript : MonoBehaviour {
    public Text[] TextObj;

    [DllImport("__Internal")]
    private static extern int GetSchemeColor();

    [DllImport("__Internal")]
    private static extern int GetCustomColor();

    [DllImport("__Internal")]
    private static extern int GetCustomBool();

    [DllImport("__Internal")]
    private static extern int GetCustomInt();

    [DllImport("__Internal")]
    private static extern int GetCustomCombo();

    private static Color SchemecolorIntToColor(int schemecolorInt)
    {
        int red = schemecolorInt / 1000 / 1000;
        int green = schemecolorInt / 1000 % 1000;
        int blue = schemecolorInt % 1000;
        return rgb(red, green, blue);
    }

    private static Color rgb(int red, int green, int blue)
    {
        return new Color(red / 255f, green / 255f, blue / 255f);
    }

    private static bool SchemeboolIntToBool(int schemeboolInt)
    {
        return Convert.ToBoolean(schemeboolInt);
    }

    void Start () {
    }

    void Update () {
        TextObj[0].color = SchemecolorIntToColor(GetSchemeColor());
        TextObj[1].color = SchemecolorIntToColor(GetCustomColor());
        TextObj[2].text = "GetCustomBool : " + SchemeboolIntToBool(GetCustomBool()).ToString();
        TextObj[3].text = "GetCustomInt : " + GetCustomInt().ToString();
        TextObj[4].text = "GetCustomCombo : " + GetCustomCombo().ToString();
    }
}


UnityのSteamVRでGripMove的に位置移動するスクリプト

Unityに読み込んだキャラモデルをSteamVRでいやらしく眺めるためにGripMoveっぽい事ができるスクリプトを結構前に作った。
しばらくしてからもっといいのがないか探したけど上手く見つからないので、前のをなくさないようメモしておく。
Viveしか持ってないのでそれのみ動作確認。
SteamVR Pluginのバージョンは1.2.2。

使い方

コントローラにスクリプトをアタッチし、InspectorからObjCameraRig変数にCameraRigかそれの入っているオブジェクトを指定する。
このサンプルではViveコントローラのグリップボタン(にぎりの所のボタン)で移動する。


using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.VR; public class GripMove : MonoBehaviour { // CameraRigもしくはそれを入れたオブジェクトを指定する public GameObject ObjCameraRig; //1フレーム前と差を比較するために前回のコントローラ位置・回転を格納する変数 private Vector3 beforeControllerPosition; private Quaternion beforeControllerRotation; void Update () { SteamVR_TrackedObject trackedObject = GetComponent<SteamVR_TrackedObject>(); var device = SteamVR_Controller.Input((int)trackedObject.index); //現在(移動後)のコントローラの位置・回転を格納 Vector3 afterControllerPosition = this.gameObject.transform.position; Quaternion afterControllerRotation = this.gameObject.transform.rotation; //"Grip"Moveなのでグリップボタンを入力したときに移動処理を実行 if (device.GetPress(SteamVR_Controller.ButtonMask.Grip)) { //1フレーム前と比較したコントローラの移動距離を算出 Vector3 distanceDifference = beforeControllerPosition - afterControllerPosition; //1フレーム前と比較したコントローラのY軸回転を算出 float rotationDifferenceY = Mathf.DeltaAngle(beforeControllerRotation.eulerAngles.y, afterControllerRotation.eulerAngles.y); //コントローラが移動した距離分、CameraRigを移動 ObjCameraRig.transform.position += distanceDifference; //コントローラのY軸が回転した分、コントローラ位置を軸としてCameraRigを回転移動 ObjCameraRig.transform.RotateAround(afterControllerPosition, Vector3.down, rotationDifferenceY); } //現在のコントローラの位置・回転を次回に移動前として使うために格納 beforeControllerPosition = afterControllerPosition; beforeControllerRotation = afterControllerRotation; } }

ワールド座標でルームスケールする位置を移動するので、部屋ごと移動してるような不思議感覚。


UnityのSteamVRでViveタッチパッドの入力を4分割して取得

やりたかったこと

UnityでViveをいじって遊んでいる途中で、下の図みたいなバッテン型に分割して入力したくなった。

たいした内容じゃないけど、マニュアルで上手く見つけられなかったからメモしておきます。
実際にはコントローラに視覚的な目印を表示することも必要だと思う。

コード

コンポーネントとして「Controller (left)」または「Controller (right)」に追加して使用。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchPadPress : MonoBehaviour {

    void Start () {

    }

    void Update()
    {
        SteamVR_TrackedObject trackedObject = GetComponent<SteamVR_TrackedObject>();
        var device = SteamVR_Controller.Input((int)trackedObject.index);

        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad))
        {
            Vector2 touchPosition = device.GetAxis();
            if (touchPosition.y / touchPosition.x > 1 || touchPosition.y / touchPosition.x < -1)
            {
                if (touchPosition.y > 0)
                {
                    //タッチパッド上をクリックした場合の処理
                    Debug.Log("Press UP");
                }
                else
                {
                    //タッチパッド下をクリックした場合の処理
                    Debug.Log("Press DOWN");
                }
            }
            else
            {
                if (touchPosition.x > 0)
                {
                    //タッチパッド右をクリックした場合の処理
                    Debug.Log("Press RIGHT");
                }
                else
                {
                    //タッチパッド左をクリックした場合の処理
                    Debug.Log("Press LEFT");
                }
            }
        }
    }
}