Integrating Machine Learning Models in Unity using NatML

There are currently lots of applications for machine learning, ranging from image analysis to self-driving cars. You might even want to use the benefits of machine learning in your games or AR applications. While you can use web services to outsource this feature to some web server on the internet, there might be cases where you would want the machine learning functionality directly integrated in your standalone application, usable on all kinds of devices.

Due to the nature of Unity, it can sometimes become a bit cumbersome to integrate certain functionalities into your application. While even mobile platforms support the use of machine learning with specialized native services like ML Kit on Android and Core ML on iOS, accessing these features might require a lot of platform dependent integration effort. Some years ago, there was a bunch of projects tackling this integration of machine learning into Unity, especially with mobile devices and their respective AR capabilities as build targets. However, when trying to use some of these with recent versions of iOS, I failed to make them work due to among others many deprecated features and issues that seemed to be caused by changes in APIs.

While searching for a decent solution, I stumbled across a thing called NatML. NatML is a very recent cross-platform machine learning runtime made especially for the Unity Engine. By using NatML, it is possible to integrate machine learning features into your Unity application using a unified API and build your application for any common Unity target platform including iOS, macOS, Android and Windows. NatML fully supports the ONNX model standard and even takes advantage of hardware machine learning accelerators across different platforms.

In this blog post, I will be showing a simple example of how to get started with NatML. Our goal will be to detect cows in single images by using the already available tiny-yolo-v3 model.

Source: Wikipedia

Installing NatML in your Unity Project

The first step to using NatML is to add and install the necessary NatML runtime dependency in your Unity project. You can either follow the instructions on the project’s GitHub page or directly add the following to your project’s Packages/manifest.json file:

{
  "scopedRegistries": [
    {
      "name": "NatSuite Framework",
      "url": "https://registry.npmjs.com",
      "scopes": ["api.natsuite"]
    }
  ],
  "dependencies": {
    "api.natsuite.natml": "1.0.5"
  }
}

The above will both specify the required NatML dependency, as well as reference an additional registry where the respective NatML dependency can be found. This is necessary, since at this point NatML seems to not be available in the Unity package registry, but rather in the official npm registry.

After adding the NatML runtime to your project, you are already set to integrate any ONNX model into your application.

Integrating a Machine Learning Model

There are currently three ways of integrating a machine learning model into your Unity project:

  • downloading the model from the NatML Hub on-the-fly during application runtime
  • loading the model from a file during runtime
  • loading the model from the streaming assets

Each approach comes with a respective method for loading the model data into memory, where it can then be used with a common API.

// Choose one of these three to load the model data
var modelData = await MLModelData.FromHub("@natsuite/tiny-yolo-v3");
var modelData = await MLModelData.FromFile("/path/to/tiny-yolo-v3.onnx");
var modelData = await MLModelData.FromStreamingAssets("tiny-yolo-v3.onnx");

// Create the actual model instance
var model = modelData.Deserialize();

About NatML Hub

NatML Hub is a website that was made to host ONNX models for you to use in your application. Given that you can download the models required by your application at any given time, you will not need to include your model data into the build of your Unity application. You can just download the models you need, when you need them.

To be able to actually use NatML Hub, an account there is required. Once you have signed up, you will not only be able to download the model data you need, but also be able to upload your own ONNX models.

Also make sure to copy your NatML Hub access key, as you will need to pass it as a parameter for authentication, when downloading a model directly from the hub. Not doing so will result in an error, even for public models.

// Pass the access key to FromHub() to authenticate
var modelData = await MLModelData.FromHub("@natsuite/tiny-yolo-v3", accessKey);

Local Models vs. Hub Models

When uploading an ONNX model to NatML Hub, there are several additional options that can be set for the model. These settings are directly linked to the model you can download from the hub at runtime and will translate to the returned MLModelData object that is returned.

In case you want to directly package your model file with your application, you can do so by using one of the two provided methods. However, the model settings that we just mentioned will not be set in the returned MLModelData object, as they are not included in the original ONNX model file itself. You will instead have to set these explicitly, if you do not wish for the default settings to be set.

As of the time I am writing this blog, the properties containing these settings are readonly, so you cannot directly set them. However, using the debugger we can find the underlying object fields and set them using reflection, when loading the model data. The following shows an example for setting the aspect mode to MLImageFeature.AspectMode.AspectFit instead of its default setting MLImageFeature.AspectMode.ScaleToFit.

var t = typeof(MLModelData);
var field = t.GetField("_aspectMode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
field.SetValue(model2Data, MLImageFeature.AspectMode.AspectFit);

Using a NatML Machine Learning Model

To actually use the model, we will now have to build a predictor from the model instance we just created. Predictors are the actual wrappers around the machine learning model that will act as a bridge between our Unity C# code and the model itself.

A predictor’s job is to:

  • translate the model input from C# types to values in memory that the model can understand and use
  • marshal the model output written to some location in memory and translate it into a usable representation for our application

For custom models, you might have to write your own predictor based on the interface of your machine learning model. We might cover the process of writing your own predictor in another blog post. For the tiny-yolo-v3 model, there already exists the TinyYOLOv3Predictor that is available on NatML Hub.

Each model on NatML Hub requires you to specify a matching predictor at the time of upload. Thus, when using a model directly from NatML Hub, you should be able to also download a working predictor from the model’s hub page. In the case of tiny-yolo-v3 just follow this link and click the Get button. This will download a .unitypackage file including the TinyYOLOv3Predictor (as well as a complete sample scene with sample usage code) for you to import to your project.

Once the import is completed, you will now be able to use the TinyYOLOv3Predictor in your code.

// Create a predictor for the model
var predictor = new TinyYOLOv3Predictor(model);

// Prepare the predictor input
var inputFeature = new MLImageFeature(someTexture2D);
(inputFeature.mean, inputFeature.std) = modelData.normalization;
inputFeature.aspectMode = modelData.aspectMode;

// Make prediction on an image
var detections = predictor.Predict(inputFeature);

By calling the Predict() method and passing the required input, the chosen model will be executed and its result returned. In the case of tiny-yolo-v3, we pass an image in form of a texture object and get an array of rectangles describing the positions of recognized objects in the image, as well as their names and confidence.

Please note that the Predict() method result and parameters will differ for each predictor, depending on the actual machine learning model that is used and its interface.

Testing your Application

To test whether or not our machine learning model can be successfully used, we will only need to pass an image of our choice to the Predict() call and check out the results.

// Create input feature
...

// Detect
var detections = predictor.Predict(inputFeature);

// Inspect results
Debug.Log($"Detected {detections.Length} objects.");
foreach(var obj in detections)
{
    Debug.Log($"Rectangle: ({obj.rect.xMin},{obj.rect.yMin},{obj.rect.xMax},{obj.rect.yMax}); Object: {obj.label}; Confidence: {obj.score}");
}

The result should look somewhat like this:

The .unitypackage that you have downloaded earlier includes a nice sample scene, displaying the detected objects in a more visually appealing way. If you would like, you can also check out that example. It is going to look somewhat like this:

Conclusion

Based on my experiences up to this point, NatML is a great runtime for building ML enabled Unity applications. The installation process is very easy and the models provided in the NatML Hub can be used right away. Even custom models can be integrated after investing some effort into the implementation of a matching predictor class.

NatML is still a very young project, so obviously some issues may arise when working with it. However, due to NatML’s ease of use and the its active development we expect to be using it a lot in future machine learning related projects.

References

Oculus Quest2開発環境構築の基本について

1. Oculusアプリの設定

OculusQuest2の開発環境を構築していきます。

まず初めにOculusのアカウントを作成する必要があります、すでに持っている場合は飛ばしても問題ありません。

アカウント作成において必要なものは以下の2つのみです

face book アカウント

Oculusアプリ(スマホ, PC)  

pc版は下記からダウンロードできます。

https://www.oculus.com/setup/

準備ができたらPCでOculusアプリを開きface book アカウントでログインします。

ログインができたらOculusとPCをケーブルでつなぎ、デバイスの設定からヘッドセットの

登録を行います。登録が終了したら設定を開き一般から提供元不明の項目を有効にします。

2. 開発者アカウントの作成

次にOculusの開発者アカウントを作成します。

下記のURLからOculus開発者ダッシュボードに飛び、新しい団体を作成します。

https://developer.oculus.com/manage/organizations/create

団体名は他とかぶらない名前で作成し、送信ボタンを押します。

問題なければ開発者アカウントの作成は完了です。

※ Face book の設定が足りない場合、設定を更新する必要があります。

3. 開発者モードの有効化

次はスマホのOculusアプリで開発者モードを有効にします。

最初にスマホとOculusをペアリングする必要があるので、「ヘッドセットをペアリング」を押しQuest2を選択しヘッドセットを探します。

※ スマホのBluetoothを有効にする必要があります。

※ 万が一ヘッドセットが見つからない場合は、
Oculus側のミラーリングを有効にすれば解決する場合があります。

ペアリングが終わると下図のような画面になるので、項目の中から 「その他の設定」を開きます。

項目の中から開発者モードを開き有効にします。

これで開発者設定は完了です。

4. Oculus Developre Hubのインストール

最後に下記リンクからOculus Developer Hubをインストールします。

https://developer.oculus.com/downloads/package/oculus-developer-hub-win/

インストールが完了したら exe ファイルを開きセットアップします。

ここまでできたらOculus Developer Hubを開きface book アカウントでログインします。

ログインができたら画面左上のOrg Managerを確認します、

先ほど作成した団体名になっていれば環境構築は終了です。

DOTweenのSequence の紹介

DOTweenは、非常にスムーズなアニメーションを素早く簡単に作成できるようにするための強力で無料の単一のアニメーションエンジンです。今回はウェイポイントを使ったアニメーションを制御する際に便利な機能について紹介します。

DOTweenにはパスを作成するために、オブジェクトまたはUI要素を特定のポイントまたはwaypointのリストに移動するための便利な機能が多数含まれています。最も便利な機能の一つはSequenceです。オブジェクトをパスに沿って移動させるだけでなく、複数のパスを次々に、またはパス内部のwaypointにもステッチすることができます。

(画像引用元:http://dotween.demigiant.com/index.php)

DOTweenを使用するには、まず適切なNamespaceを追加し、DOTweenを初期化する必要があります。

using DG.Tweening;

private void Start()
{
   DOTween.Init();
}

その後、Sequenceを作成して初期化する必要があります:

using DG.Tweening;

private Sequence mySequence;

private void Start()
{
   DOTween.Init();
   mySequence = DOTween.Sequence();
}

Sequenceが初期化すると、パラメータをAppendキーワードで与えることでTweenの挙動を簡単に追加できます。たとえば、DOMove()を使用してオブジェクトを移動したり、DOPath()を使用してオブジェクトをパスに沿って移動したりできます:

mySequence.Append(transform.DOPath(Vector3[] waypoints, float duration, PathType pathType = Linear, PathMode pathMode = Full3D, int resolution = 10, Color gizmoColor = null);

Tweensをいくつでも追加可能で、素晴らしいアニメーションを作ることを可能できます。
併せて以下のような多くの有用なパラメータを制御することができます:

  • SetLookAt()関数を使用して、Tween中に前方のオブジェクトが向いている方向を制御。
  • SetEase()関数をつかって、TweenをEaseのバリエーションを制御。
  • OnComplete()コールバック関数で終了したときにすべきことを指定。
  • OnWaypointChange()コールバック関数を使用して、(DOPath()での)各ウェイポイントまたは特定のウェイポイントの到達した後に別の挙動を指定。

OnWaypointChange()を使った例としては、Sequenceのタイムスケールを変更するだけで、実行時でも特定のウェイポイントからTweenの速度を変更することができます:

OnWaypointChange((int waypoint) =>
{
   if(waypoint == 5) { mySequence.timeScale = 0.5f; }
   if(waypoint == 8) { mySequence.timeScale = 2f; }
}) 

これらすべてのパラメータは、単純にAppendの最後に追加できます:

mySequence.Append(DOPath(...)
.SetLookAt(...)
.SetEase(...)
.OnWaypointChange((int waypoint) => { //Do something })
.OnComplete(() => { //Do Something }));

最初のSequence Tweenが作成されたら、Appendの代わりに新しいTweenに加えることもできます。
これにより、Tweenは最初にプレイした後ではなく、同時にプレイします。

たとえば、最初のTweenが位置を制御している間に回転コントロールも同時に行う場合は下記のように記述できます。:

mySequence.Append(DOMove(...));
mySequence.Join(transform.DORotate(...));

興味があり、DOTweenにあるすべてのオプションを見たい場合は、以下のリンクをたどってdocumentation を見てください。

http://dotween.demigiant.com/documentation.php

拡張子insvがInsta360 Playerでスムーズに再生できない

コンテンツを制作する際に資料映像として360°動画ファイルで頂くケースが最近増えてきました。下記にInsta360で撮影した動画がそれほど高スペックでないPCのInsta360 Player上でシークがうまく行かなかったケースでのTipsをシェアしたいとおもいます。

拡張子insvはInsta360のファイルフォーマットです。Insta360 Playerを利用してこれらの拡張子のプレビューすることができます。
公式サイトで無料でダウンロード可能ですが、サイトの構成変更でダウンロードリンクが若干わりづらくなっているようです。

下記のプロダクトのページにリンクがあります。
https://www.insta360.com/download/insta360-4k

ダウウンロードしたらアプリを起動して、360°動画ファイルをInsta360 Playerにドラッグアンドドロップして読み込んだのですが、弊社で遭遇したケースでは再生バーをシークすると、該当箇所(フレーム)の映像は表示されますが、シーク中の映像が停止した状態となりました。

どうやら撮影した映像が高解像度かつ高ビットレートだったため、再生バーをシークしても早送りや巻き戻しが見た目に反映されていないようです。

そこで、公式ページにあるInsta360 Studioを使って、映像を解像度とビットレートを圧縮することにしました。
(※先程のPlayerをダウンロードしたページの中部あたりにあります。)

Insta360 Studioを起動して、ファイルをドラッグアンドドロップして読み込みます
その後アプリケーションのタイトルバー付近の上部の黄色いボタン(➀)を押して、圧縮設定ウィンドウを表示します。

setting_window_capture

解像度を設定した後、「Bitrate」の項目のプルダウンリストからCustomizeを選択して(②)、横の文字入力ウィンドウに任意の数字を入力します。今回の場合は”18”にしました。
OKを押すとキューに追加されて、圧縮が開始されます。

今回のケースでは下記のように設定しました。
元ファイルの設定:

  • 3840px × 1920px
  • ビットレート 50Mbps

圧縮後のファイルの設定:

  • 1920px × 960px
  • ビットレート 18Mbps(カスタムを選択して手動入力)

圧縮が終わったファイルをInsta360 Playerにドラッグアンドドロップすると、シークが効くようになりました。

なお、insvフォーマットのままの圧縮はできないようです。残念です。
“Spherical pictures and videos can be played and edited by Insta360 Studio, which would export the original insv video and insp picture to MP4 and JPG format “

http://faq.insta360.com/documents/Guide_to_Play_and_Edit_Spherical_Videos/#export

以上となります。

Unity3D+シューティングゲームのオブジェクトプールのチュートリアル

Blogをいつもご覧いただきありがとうございます。

シューティングゲームを作った時に、武器の弾のシステムは様々な書き方がありますが、一番シンプルな書き方は、恐らく弾のオブジェクトをインスタンスして、敵にヒットしたら(コード側ではコライダーやポジションでどちらでも可能です。)、敵と弾一緒に消滅すると思います。

弾を生成する場合の例:

using UnityEngine;
using System.Collections;

public class BulletInstance : MonoBehaviour {
public GameObject BulletPrefab;
// Update is called once per frame
void Update () {                                                                                                            
 GameObject bullet = Instantiate(BulletPrefab, Vector3.zero, Quaternion.identity) as GameObject;   //弾をインスタンス 
}

弾と敵を消滅する場合の例:

using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour {

void OnTriggerEnter(Collider other)
 {
   if (other.tag.CompareTo("Bullet") == 0)
    {
       Destroy(other.gameObject);//弾が消される
       Destroy(this.gameObject);//敵自分が消される
    }
 }
}

この書き方は普通に動くはずですが、でも、常に弾のPrefabをインスタンスしたり、Destroyしたりしたら、メモリー上にとってあまり優しいとはいえません。正直に言うとPC用としてはまだしも、スマートフォンゲームの場合はかなりきびしいものになると思います。
オブジェクトをずっと増やし続けるとゲームのFPSが落ちたり、重くなったり、スマートフォンが熱くなったりするのもおかしくないです。

それをさける為に、考えを逆にするのはどうでしょうか?

プログラム側では、オブジェクトのInstanceやDestroyの場合にリソースを消費しているとしたら、なら、常にInstanceやDestroyしないシステムを作ればいいじゃんないか?

それでは、オブジェクトプールを勉強しましょう!

·オブジェクトプールの概念

オブジェクトプールとは、この先使えるオブジェクトを溜めておく用の倉庫のような存在で、オブジェクトが必要になったら取り出し、使い終わったら戻すことで、なるべく少数のオブジェクト使い回してオブジェクト数及び生成・消滅のコストを抑えるものです。

それでは、実際にUnity3D側で作っていきましょう。

·実装

Step1 Unityの環境作り

Step2 弾のプールシステム

ここで二つのスクリプトが必要です。

  • BulletPool.cs  このスクリプトはオブジェクトプールで、オブジェクトにドラッグドロップする必要はありません。
  • Bullets.cs     このスクリプトは弾のPrefabにドラッグドロップするスクリプトです,弾の方向やスピードをコントロールしています。
実装コード:

BulletPool.cs

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

public class BulletPool : MonoBehaviour {
    //オブジェクトのプールとしてのリストを作る
    List pools = new List();
    // start pos
    Vector3 firstPosition;
    //シングルトン
    private static BulletPool instance;
    private BulletPool() { }
    public static BulletPool GetInstance()
    {
        if (instance == null)
        {
          
            instance = new GameObject("BulletPool").AddComponent();
           
        }
        return instance;

    }
   
    //オブジェクトプールからオブジェクトを取得する
    public GameObject MyInstantiate(GameObject name)
    {
        //オブジェクトプールは空だから、インスタンスする
        if (pools.Count == 0)
        {
            return Instantiate(name, Vector3.zero, Quaternion.identity) as GameObject;
        }
        else 
        {
           
            //もしプールでは空じゃない場合は「0」を取る
            GameObject go = pools[0];
           
            go.SetActive(true);
            //オブジェクトプールから消される
            pools.Remove(go);
            return go;

        }
    }
    //オブジェクトプールを作成
    public void DelayInstantiate(GameObject name)
    {
        //オブジェクトを隠す
        name.SetActive(false);
        //オブジェクトプールに入れる
        pools.Add(name);
    }
}

Bullets.cs

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

public class Bullets : MonoBehaviour
{
    Transform target;
    private void OnEnable()
    {
        //ポジションを初期化する
        target = GameObject.Find("Hero").transform;
        transform.position = target.position;
        //二秒の後でCoroutineを実行する
        StartCoroutine(DelayObject(2f));
    }
    private void Update()
    {
        //弾の移動
        transform.Translate(Vector3.up * Time.deltaTime * 100);
    }
   
    IEnumerator DelayObject(float time)
    {
        yield return new WaitForSeconds(time);
        //弾のプールリストに入れる
        BulletPool.GetInstance().DelayInstantiate(gameObject);
    }

}

 

Step3 Playerのコントロール

弾のプールを実装完了したら、次は発砲の機能や移動の機能が入ってる”PlayerControlManager.cs”を「Hero」のオブジェクトにドラッグドロップしてください。

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

public class PlayerControlManager : MonoBehaviour {

    float _hor_Speed = 1f;    //水平移動の速度
    float _ver_Speed = 1f;  //垂直移動の速度 
    float _topMax = 300f;//Player移動制御の変数
    float _bottomMax = -300f;//Player移動制御の変数
    float _sideMax =177f;//Player移動制御の変数
    float _turnAngle = 45;//回転の角度
    GameObject bulletPrefab;
    void Awake(){
        bulletPrefab = Resources.Load("Prefabs/Bullet") as GameObject;

    }
    void Update()
    {
        Move();
        TurnBody();
        Limit();
        Fire();
    }

    void Fire()//発砲
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            BulletPool.GetInstance().MyInstantiate(bulletPrefab);
        }
    }
    
    void Limit()//移動制御
    {
        if (transform.localPosition.x > _sideMax)
        {
            transform.localPosition = new Vector2(_sideMax, transform.localPosition.y);
        }
        if (transform.localPosition.x <  -_sideMax)
        { 
            transform.localPosition = new Vector2(-_sideMax, transform.localPosition.y); 
        } 
        if (transform.localPosition.y > _topMax)
        {
            transform.localPosition = new Vector2(transform.localPosition.x, _topMax);
        }
        if (transform.localPosition.y < _bottomMax)
        {
        transform.localPosition = new Vector2(transform.localPosition.x, _bottomMax);
        }
    }

    void TurnBody()//機体を回転する
    {
        if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow))
        {
            transform.Rotate(new Vector3(0, _turnAngle, 0));
        }
        if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow))
        {
            transform.Rotate(new Vector3(0, -_turnAngle, 0));
        }
        if (Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.LeftArrow))
        {
            transform.Rotate(new Vector3(0, -_turnAngle, 0));
        }
        if (Input.GetKeyUp(KeyCode.D) || Input.GetKeyUp(KeyCode.RightArrow))
        {
            transform.Rotate(new Vector3(0, _turnAngle, 0));
        }
    }
    void Move()//Playerの移動
    {
        float ver = Input.GetAxis("Vertical");
        float hor = Input.GetAxis("Horizontal");
        transform.position +=new Vector3(hor * _hor_Speed, ver * _ver_Speed, 0);
    }

 }

   

上記の流れに沿って実装ができたら、プロジェクトをPlayしてください。

こんな感じですね

·注意点:

  • オブジェクトプールは非常に便利です。使う場面として繰り返し利用するオブジェクトを生成する場合に有効です。今回の場合は弾や敵などです。
  • 使う場合によっては逆効果が出る可能性もあります。実際にゲームのジャンルやシステム、オブジェクトの特徴などによって、どのような形式のオブジェクトプールを使うのか考える必要があると思います。
  • オブジェクトを破棄する代わりに隠す(表示しないようにする)ことで、表示的には破棄と同等の効果実現してます。そのおかげでオブジェクトをインスタンス化する際のリソースの無駄な消費を抑えられると思います。

※補足情報としてオブジェクトプールを利用することで、オブジェクトのインスタンス化をできるだけ削減しましたが、既にインスタンスされたオブジェクトはSetActive(false)になっても、まだメモリーの中に存在し、メモリーの容量を占有しています。メモリの占有が完全になくなるわけではありません。

ご覧いただきありがとうございました。

Unity_PostProcessing機能の有効化

あるシーンが、「PostProcessingのエフェクトが適用されているシーンのはずなのに自分のPCで開くと見た目が通常と変わらない。」
上記のような場合は、Unity PostProcessing Stackがインストールされているかをチェックしてみてください。

確認方法は下記のとおりです。
1.メニューバーのWindow->Package Manager をクリック。

inst_PostProcessing_Stack01_Image
inst_PostProcessing_Stack01_Image
Image_of_inst_PostProcessing_Stack02
inst_PostProcessing_Stack02_Image

2.Allのタブ(①)をクリックし、スクロールダウンしてPost Processing(②)を選択します。
3.右上のInstallボタン(③)を押してインストールします。

この手順でシーンのカメラに設定された、Post Processingの効果が確認できると思います。

Unity HubでインストールしたUnityのVuforiaプラグインをアップデートする方法

Unity Hubはとても便利で新しい機能ですが、Vuforiaをアップデートする場合、少し面倒な手順が必要になります。

最新のUnityのバージョンを既にインストールしていて、そのUnityと共にインストールされたVuforiaのバージョンよりも更に最新のVuforiaがリリースされている場合、下記の手順でVuforiaをアップデートできます。

Unityを起動するときにVuforiaは無効の状態になっています。(Image1)。

とりあえず、Vuforiaを使用するため、
File>Build Settings>Player Settigsボタン
または
Edit>Project Settings>PlayerからPlayer Settingsを開き、
(Image2)
Player settingsのVuforia Augmented Realityオプションをチェックする必要があります。

(Image3)
Vuforia Configurration Pannelの出し方
すると Vuforia Configuration Panel Vuforia Update のリンクをクリックできるようになります。(Image4)。

Image1

Image2

Image3

Image4

ここで一旦Unityを閉じてください。

ダウンロードが終わったら、

VuforiaSupportInstaller-Windowsの圧縮ファイルを解凍し、UnitySetup-Vuforia-AR-Support-for-Editorのイントラーをダブルクリックします。

UnitySetupアイコンを選択してください(Image5)。

インストールを続いて、Destination Folderのページを見えたらBrowseボタンをクリックしてください(Image6)。
ここで、Vuforiaの最新を適用したいUnityのバージョンの実行ファイルが置かれているパスを指定します。

Image5

Image6

 

Program FilesフォルダーにあるUnityフォルダーを選択してください(Image7)。(注意:Unity Hubのフォルダーではありません。Unity自体の実行ファイルがあるフォルダを指定する必要があります。

Image7

それでUnityをアップデートするバージョンを選択し、OKボタンを選択してください(Image8)。
Image8

次のウインドで選んだフォルダーを確認できます(Image9)。それでインストールを最後まで続けてください。

Image9

 

Unityを起動するとVuforiaがアップデートされていることが確認できます(Image10)。

Image10

Unity3D+IK(Inverse Kinematics)のAnima2Dチュートリアル

Blogをいつもご覧いただきありがとうございます。

前回は「Unity3D+Anima2Dチュートリアル」というテーマの記事を投稿しました。

今回はAnima2dのInverse Kinematicsについて説明したいと思います。

Inverse Kinematicsとは何ですか?

Anima2Dには、Inverse Kinematicsのコンポーネントがあります。これを使い、親関係のボーンオブジェクトの子供を動かすと、親も連動し動きます。

例を挙げると、腕と肩の関係のようなものです。(以下省略”IK”です)。

シンプルなアニメーションは、ボーンをいじるだけで充分ですが、もしアニメーションが複雑な場合はかなり時間がかかると思います。

そういう場合は「IK」が便利です。移動させたいボーンを「IK」と繋げればこのボーンのチェーンを丸ごと動かすことができとても便利です。

 

IKの種類は?

 

Anima2DのIKには,IK CCDIK Limb という2種類のIKがあります。

IL Limbは骨を2本しかコントロールできません、余弦定理ですので、今回の場合手足に利用します。

IK CCD は設定に応じて、最大コントロールできる本数がルートボーンまでの全部の骨をコントロールすることができます。今回の場合頭と尻尾に使います。

 

では、前回の引継き、IKの使い方を説明します。
IKをの使い方を説明する前に、先ずAnima2Dの効率をアップでさせる機能を紹介したいと思います。

「PoseManager」というものです。

使い方はとても簡単です。下記の画像のように、前回の「牛」のオブジェクトに「Pose Manager」を入れれば、使えるようになるはずです。

そして、「Create new pose」をクリックしたら、今のスプライトのポジションとローテーションがセーブできます。

一つの「Idle」のポーズを「Save」をクリックしてから、後はどんな調整しても、ただ「Load」ボタンをクリックしたら、最初設定のポーズに戻れます。(ちなみに、「Save」はオーバライドしますので、ご注意ください。)

「Pose Manager」の使い方はここまでです。

それでは、「IK」の使い方の説明に入りましょう。

Step 1: IKをクリエイトします

「牛」のオブジェクトの中に、もう一個の空のオブジェクトを作って、名付け「IK」です。

下記の画像のようにそのオブジェクトに右クリックして、「2D Object」→「IK Limb」をクリックしたら、「IK」が出ます。

では、「IK」のパラメータを説明しましょう。

  • Record:アニメーションモードの間,ボーンのキーフレームを記録します。
  • Target: IKが適用されるボーン。
  • Weight:​IKのポーズに対する影響度。
  • Restore Default Pose: 計算を実行する前に最初のポーズを設定します。
  • Orient Child:ターゲットの子ボーン(使用可能な場合)をIKローテーションに回転させます。
  • Num bonesIKの影響を受けるボーンの数.最大はルートボーンまで。
  • Iterations solverの反復回数。
  • Dampingソルバのステップ速度を制御する.値が小さいと変化が見やすい,大きいと変化が見にくいです。Dampingの値が大きければ、もっと自然に見えるかもしれません。

 

Step 2:「IK」をコントロールしたい関節に配置します

下記の画像のように、三つの「IK」をクリエイトして、分かりやすい名前を付けてから、それぞれにコントロールしたいところに置いてください。

上記の説明の通り、「頭」の部分には、使っているのはIK CCDです。

お気付きだとおもいますが、このグレーのリングを自分が望んでいる所に配置しても、スプライトはまだコントロールできません。

なぜかというと、下記の画像表示の通りに、右側の「Inspector」の「Target」はまだ「None」になっていますので、コントロールできるオブジェクトはまだありません。

では、「Target」に相応の「Bone」オブジェクトに入れてみてください。

設定が終了したら、グレーのリングは青のリングに変わります。

では、下記の画像の手順通りにすれば、左側のコントロールしたい「IK」のオブジェクトをクリックして、右側のリングを移動したら、「牛」全身が一緒に動きます。

注意点:偶にリングを移動しても、欲しい角度に合わせられない場合があったら、下記の画像の状態で「IK」の「Inspector」の「Filp」のチェックを入れてから、もう一度調整すれば、合わせられると思います。

適用後の図:

これで、「IK」のリングを弄れば、簡単に関節が調整できるようになりました。

複雑なボーンが入っているスプライトでは、「IK」はとても役に立ちます。

今回のインバース キネマティクス(IK)の使い方はここまでになります。

では皆さん、次回の内容をご期待ください!

Unityでのアプリ内のムービー表示方法と、常に正しい解像度と比率を維持するように設定する方法。

How to create a movie screen with unity, and to set it to keep the right resolution and ratio at all time. 

ユニティでムービー画面を作成する方法と、常に正しい解像度と比率を維持するように設定する方法。

First you will need to import a video, the list of the supported format in unity can be found here : 

最初にビデオをインポートする必要があります。サポートされているフォーマットのリストはここにあります: 

https://docs.unity3d.com/Manual/VideoSources-FileCompatibility.html

Next, to be able to render the video on screen, you will need to create a special type of texture: a Render Texture. To do that, make a right click on the Project Window, go to create and select Render Texture.  

次に、ビデオをスクリーン上でレンダリングできるようにするには、特別なタイプのテクスチャ:Render Textureを作成する必要があります。 これを行うには、Project Windowを右クリックし、作成して「Render Texture」を選択します。 

Then, to be able to display this render texture on a ui element you will need to create a Raw Image by right clicking on the Hierarchy window and select Raw Image in the UI tab.  

次に、このRender TextureをUI要素に表示するには、Raw Imageを作成する必要があります。Hierarchy windowを右クリックし、[UI]タブの[Raw Image]を選択します。 

Make the Raw Image the same size than the Canvas. And set the Anchor to stretch in all directions. 

Raw ImageをCanvasと同じサイズにします。 Anchorをすべての方向に伸ばすように設定します。 

 

You now have to put the Renderer Texture in the texture element of the raw image. 

これで、Renderer TextureをRaw Imageのテクスチャスロットに配置する必要があります。 

You also need to add a Video Player component to the Raw Image, to drag and drop the video in the Video Clip element and to set the Render Texture as the Target Texture. 

Raw ImageにVideo Playerコンポーネントを追加して、ビデオをVideo Clip要素にドラッグアンドドロップし、Render TextureをTarget Textureとして設定する必要があります。 

Then if you play the scene you will notice that the video is playing but the ratio and the quality of the video will be really bad. That’s because the size of the Render Texture doesn’t match the size of the video (the video used here is 1280×720).  

シーンを再生すると、ビデオが再生されていることがわかりますが、ビデオの比率と品質はとても悪くなります。 これは、Render Textureのサイズがビデオのサイズと一致しないためです(ここで使用されるビデオは1280×720です)。 


You need to give the Render Texture the same size than the video to make it displaying properly.

Render Textureをビデオと同じサイズにして、適切に表示させる必要があります。  

To make the video scale accuratly on different screen size (for exemple on different smartphone size), set the “UI Scale Mode” of the canvas holding the Raw Image to “Scale with screen size”, the “Reference Resolution” the same than the Render Texture, the “Screen match mode” to “match width or weight” and the “Match” to 0.5. 

さまざまな画面サイズ(例えばスマートフォンサイズ)のビデオスケールを正確に作成するには、Raw Imageを保持するキャンバスの「UI Scale Mode」を「Scale with screen size」に設定して、 「Reference Resolution」をRender Textureと同じにして、「Screen match mode」を「match width or weight」に設定して、「マッチ」を0.5に設定します。 

 

Notes: 

注釈: 

*It is also possible to play a video on a GameObject by putting a video player on this object and setting the “Render Mode” of this component to “Material Override”.(Usefull to render 360 videos for exemple). 

*GameObjectでビデオを再生することもできます。このオブジェクトにビデオプレーヤーを置き、このコンポーネントの「Render Mode」を「Material Override」に設定します。(例えば360ビデオをレンダリングするため) 

*You can set the “Audio output mode” of the video player to “Direct” if you want the sound of the video to play, or to put it to “Audio source” if you want to play a separate sound file. (the direct sound mode doesn`t work yet on android smartphones). 

ビデオのサウンドを再生する場合はvideo playerの「Audio output mode」を「Direct」に設定し、別のサウンドファイルを再生する場合は「Audio source」に設定します。 (Directサウンドモードはアンドロイドスマートフォンではまだ動作しません)。 

Unity+Myo(ジェスチャーを活用して牛乳を搾るゲームを作りました)

Blogをいつもご覧いただきありがとうございます。先日「Myo」のジェスチャーでゲームを作ってみましたので今回はここでジェスチャーの使い方を紹介しようと思います。

下記のURLはゲームの映像です。
https://www.youtube.com/watch?v=4Jz7y1n3Iec

· Myoってどんなもの?

Myoアームバンドは、腕、手首、指のジェスチャーで、デバイスをワイヤレス操作することができます。

下記のURLはMyoの公式サイトです。
https://www.myo.com

· Myoのジェスチャーの紹介

デフォルトで認識するプリセットジェスチャーは下記のとおりです。

· グー(Fist)
· パー(FingersSpread)
· ダブルタップ(DoubleTap)
· 手首で手を左に仰ぐ動作(WaveIn)
· 手首で手を右に仰ぐ動作(WaveOut)
· リラックス(Rest)

「グー」と「パー」を合わせて、モミモミすることができそうなので、私はこの二つのジェスチャーを利用して牛乳を搾るゲームを作りました。それでは、ジェスチャーの部分に入りましょう。

· sdkの導入

環境状況:
Unity2018.1.0f2
SDKバージョン:Windows SDK 0.9.0
Firmware: 1.5.1970
https://developer.thalmic.com/downloads
SDKを持っていない人は上記のサイトからダウンロードできます。

SDKをダウンロードして、Unityにインポートしましたが、エラーが三つ出ました。

エラーが発生しているスクリプト(ColorBoxByPose)をチェックしたら、レンダリングの設定の書き方が古すぎますのでUnity2018.1.0f2(恐らくUnity2017以降のバージョン)では、書き方を変える必要がありますね。

では、そこの書き方を変えましょう!

上記のように修正してエラーが消えるはずです。

次はMyoをコントロールするために、SDKが用意してくれたプリハブをシーンに入れます。

サンプルシーンの中で「Joint」というGameObjectがあります。このGameObjectに存在するスクリプト(JointOrientation)がMyoデバイスの方向を管理しています。これをプリハブにして、自分のシーンに適用します。

方向を制御するスクリプトできたので、次はジェスチャー検出のコードですね。

それでは、ジェスチャー検出用のスクリプトを作りましょう。

そのオブジェクトに自分が作った「gManager」を入れて、ジェスチャー検出のコードを全部このスクリプト内に記述することにします。

これで、SDKのプラグインの導入が完了しました。

· ジェスチャー検出

例:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pose = Thalmic.Myo.Pose;
public class GestureManager : MonoBehaviour {
Public GameObject myo;
ThalmicMyo thalmicMyo;
void Start () {
  thalmicMyo = myo.GetComponent<ThalmicMyo>();
 }
void Update () {
  Fist();
  Stroke()
}
//ジェスチャーは「グー」の時
void Fist()
 {
   if(thalmicMyo.pose == Pose.Fist)
   {
   /*この部分は「グー」の処理の内容
   (牛乳を搾る機能を埋め込みました)
   */
   }
 }
//ジェスチャーは「パー」の時
void Stroke()
 {
  if(thalmicMyo.pose != Pose.Fist || thalmicMyo.pose == Pose.FingersSpread || thalmicMyo.pose == Pose.Rest)
  {
  /*この部分は「パー」の処理の内容
  (ここで手を離す機能と牛を撫でる機能を埋め込みました)
  */
  }
 }
}

「撫でる」機能は正確に言うと「パー」かリラックスの状態で手首や腕を振るという動作です。
上記のコードの通りにvoid Stroke()関数の中にMyoのジャイロの処理を埋め込めば「撫でる」ができます。

例:

void Stroke()
{
  if (thalmicMyo.pose != Pose.Fist || thalmicMyo.pose == Pose.FingersSpread || thalmicMyo.pose ==Pose.Rest)
  {
   if (thalmicMyo.gyroscope.magnitude > 120f)
     {
       //gyroscopeのmagnitudeは120より大きい場合
      //(速く腕を振ると簡単に120を超えます。)
     }
    else if (thalmicMyo.gyroscope.magnitude < 10f)
     {
      //gyroscopeのmagnitudeは10より小さい場合
     //(腕が静止に近い場合)
     }
  }
}

ここまではもう方向変更と簡単な「グー」と「パー」の処理が実現できるようになりました。でもMyoのもう一つのスクリプト(ThalmicMyo)の内容をみていきましょう。

· ThalmicMyo

ThalmicMyoはMyoのSDKの中でコアの部分です。

下記に主要な変数名を説明します。
· ArmSynced:boolタイプの変数で、trueになったらMyoデバイスが検出できます。
·arm:左の腕と右の腕どちらかと設定できます。
·pose:Myoが検出したジェスチャを保存します。UnKnowは今のジェスチャーです。
·accelerometer:加速度の計算用のVector3タイプの変数です。約9.8 m/s^2です。
·gyroscope:今のジャイロの軸のスピードを検出できます。単位は「度/秒」
·isPaired:trueの時にMyoのデータが読み込めます。
·Vibrate:Myoが提供しているバイブレーションタイプです。三つの種類があります。

public enum VibrationType { Short, Medium, Long }

バイブレーションの書き方は下記の通りです。

例:

using VibrationType = Thalmic.Myo.VibrationType;
if(thalmicMyo.pose == Pose.Fist)
{
  thalmicMyo.Vibrate(Vibrate.Short);
}

上記の「撫でる」機能はThalmicMyoの変数を利用して実装してみました。

· 実装して気づいたこと

1.実装してみて素早いジェスチャでは認識までに若干のディレイをかんじました。デバイスの特性上仕方がない点かとおもいますが、頻繫にジェスチャーを素早くおこない操作するゲームはわりと不向きかもしれません。

2.Myo Connect(Mac/Windows上のデフォルトマネージャー)をつかってキャリブレーションを行ったほうがやはり操作感が向上します。(PC用にビルドしたアプリのみで利用可能)

3.キャリブレーションをする時にゲームをする際と同じ腕のポジションでキャリブレーションするとジェスチャの認識向上におすすめです。

4.UnityでAndoroid用のビルドをためすために、有志の方が開発したandroid+UnityのSDKのGitHubにアップされたパッケージを利用してためしました。

ただ、Myo Connectのような、マネージャーソフトがない為キャリブレーション、個人のプロファイルの設定ができないの理由で、腕の方向やコントロール精度は満足いくものにはなりませんでした。