しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

HoloLens 用 Toolkit で注視した対象を半透明のフォーカス状態にする

※ これは 2016/08/05 Unity HoloLens Technical Preview ver.5.4.0f3(Windows版) 時点の情報です

最新版では動作が異なる可能性がありますのでご注意ください

前回 は HoloToolkit で注視位置を表すカーソルを表示してみました

今回はさらに注視されていてカーソルが当たっているときに、フォーカスしていることがわかりやすいように対象を半透明にする実装を試してみたいと思います

まずは準備として Project の Assets フォルダ直下から [Create]-[Folder] のコンテキストメニューを選び、3つのフォルダを追加します

フォルダ名はそれぞれ 「Materials」「Scenes」「Scripts」という名前*1にしておきます

f:id:matatabi_ux:20160821171343p:plain

現状のシーン状態を保存するため、[File]-[Save Scene as...] のメニューを開き、Assets/Scenes に「Main」という名前でシーンファイルを保存します

f:id:matatabi_ux:20160821183657p:plain

このシーンファイルを作っておかないと、Unity Editor を終了した時に作業状態が保存されないのでご注意

次に Project の Assets/Materials フォルダ直下で [Create]-[Material] のコンテキストメニューを開き、「Panel」という名前でマテリアルを追加します

このマテリアルは GameObject に色や柄をつけるために表面に貼り付けるようなものになります、

f:id:matatabi_ux:20160821172804p:plain

作ったマテリアルは Rendering Mode を「Fade」にし、Main Maps の Albedo の色として #99CC66FF の緑色を指定しておきます

Rendering Mode を「Fade」にしないとこの後の手順通りにしても半透明にならないのでお忘れなく

f:id:matatabi_ux:20160821163831p:plain

マテリアルの設定が終わったらこれを Hierarchy 上の Panel に向けてドラッグドロップしてアタッチします

これで Panel の見た目が緑色になりました

f:id:matatabi_ux:20160821171443p:plain

ここまで終わったら注視された際の動作を記述するためスクリプトを追加します

Project の Assets/Scripts フォルダ直下に [Create]-[C# Script] のコンテキストメニューを開き、「TargetPanel」という名前で cs ファイルを追加します

f:id:matatabi_ux:20160821172804p:plain

スクリプトファイルを作ったらこれも Hierarchy 上の Panel に向けてドラッグドロップしてアタッチしておきます

f:id:matatabi_ux:20160821184930p:plain

コードの中身はこんな感じ

using UnityEngine;

/// <summary>
/// 注視対象となるパネル(Quad)
/// </summary>
[RequireComponent(typeof(Renderer))]
[RequireComponent(typeof(Material))]
public class TargetPanel : MonoBehaviour
{
    /// <summary>
    /// パネルのレンダラー
    /// </summary>
    private Renderer meshRenderer = null;

    /// <summary>
    /// パネルのマテリアル
    /// </summary>
    private Material defaultMaterial = null;

    /// <summary>
    /// 初期処理
    /// </summary>
    public void Awake()
    {
        this.meshRenderer = this.GetComponent<Renderer>();
        this.defaultMaterial = this.meshRenderer.material;
    }

    /// <summary>
    /// 注視(フォーカスイン)イベントハンドラ
    /// </summary>
    /// <remarks>
    /// インタフェースや抽象型の継承として記述しない理由は、パフォーマンスのオーバーヘッドを軽減するためらしい
    /// </remarks>
    public void OnGazeEnter()
    {
        var color = this.meshRenderer.material.color;
        this.meshRenderer.material.color = new Color(color.r, color.g, color.b, 0.6f);
    }

    /// <summary>
    /// 注視はずれ(フォーカスアウト)イベントハンドラ
    /// </summary>
    /// <remarks>
    /// インタフェースや抽象型の継承として記述しない理由は、パフォーマンスのオーバーヘッドを軽減するためらしい
    /// </remarks>
    public void OnGazeLeave()
    {
        var color = this.meshRenderer.material.color;
        this.meshRenderer.material.color = new Color(color.r, color.g, color.b, 1f);
    }
}

Awake() メソッドは Unity の暗黙的な最初に呼び出される初期化用メソッドで、OnGazeEnter()、OnGazeLeave() メソッドは HoloToolkit の暗黙的なイベントハンドラです

こういったメソッド名しばりの暗黙的なルールは間違うと機能しなくなるので危ういのですが、Unity 的にはパフォーマンスのオーバーヘッドを軽減するという理由でインタフェースや抽象型などの明示的な規約化をとっていないようです

やっていることは Panel オブジェクトの Renderer から Material をとってきて色を半透明にしたり、不透明に戻したりしているだけです

とにもかくにもビルドしてお試し実行

f:id:matatabi_ux:20160821191120g:plain

ちゃんと注視しているときだけ半透明になりました!

*1:Unity ではファイルの種類ごとに ~s というフォルダを Assets 直下に作り整理する習慣があるようです