NO ENGINEER NO CRY

泣かないエンジニアはいない

【Unity】Leap Motion で INPUT AXIS NOT SET UP.というエラーが出たときの対処法

Leap Motionの物体をつかむための公式デモを実行しようとすると
INPUT AXIS NOT SET UP. Go to your Input Manager and add a definition for LeftVRTriggerAxis on the 9th Joystick Axis.
というようなエラーが毎フレーム出てくる場合がある。

因みにエラーメッセージは出てても一応動作はちゃんとする。
ただこのままだとデバッグメッセージが流れて行って不便なので解消したい。
調べてみたところどうやらInput ManagerでLeftVRTriggerAxis , RightVRTriggerAxisが定義されていないときに出るエラーのようだ。

Edit > Project Setting > Input より Axesのサイズを2増やす。
その後、追加された項目の名前をそれぞれLeftVRTriggerAxis , RightVRTriggerAxisにする。
TypeをJoystick Axisにして、AxisはLeftを9th axis (Joysticks)、Rightを10th axisにする。
これでエラーは消える。

f:id:imln20:20200824175035p:plain
一番下の項目はデフォルトのまんまでも大丈夫です。

Docker for Windows で Cannot enable hyper-v service になる場合の対処法

コントロールパネルからHyper-Vを有効化してもDocker Desktopが起動できない場合の対処法。

BIOSから仮想化機能をONにすると解決しました。

BIOSのAdvanced Settingから CPU Configurationへ。
Intel製のCPUを使用している場合は Intel(R) Virtualization Technology を Enableに。
AMD系の製品の場合はSVM modeをEnalbeに。

【NAIST生活記】2019年 (M1) 振り返り

たまには普通の日記でも。

2019年も残り24時間を切りましたね。
思えばこの1年色んな事がありました。2019年は自分の人生に色んな変化をもたらしたようなそうでもないような、そんな1年でした。というわけで、NAISTでの文化・生活様式にも触れながら今年の振り返りポエムを書いていこうと思います。
タイトルにNAIST生活記をつけたのは、「NAIST気になってるけどよくわからない><」という人が検索で来てくれたらうれしいなあというお気持ちからで特に深い意味はありません。実際自分も入学前はそういう記事を求めて電子の海を彷徨っていたのですが、今となっては結構似たような記事を書いている人は多いのでアレがアレでアレですが(どれ)(みそら)←ペンタトニックスケール

続きを読む

【Unity】Magic Leap でコントローラーからのボタン入力を取得する

環境構築などはこちらを参考に
実機が無くてもシミュレータで動かせます

qiita.com

ボタンの説明

f:id:imln20:20191111153229j:plain

分かりにくいですが、こんな感じのコントローラーになっています

f:id:imln20:20191111153610j:plain

ボタンは全部で4つあり、TouchPad,Bumper,Triggerボタンがあります
完全に書き忘れなのですが、touchpadの手前にある丸っこいのがHomeTapボタンです

ボタンの取得

以下のスクリプトをキューブにアタッチすると、ボタンの入力に応じてキューブが動きます

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.MagicLeap;

public class cubeScript : MonoBehaviour
{
    public enum ButtonStates
    {
        Normal,
        Pressed,
        JustReleased
    };
    
    public ButtonStates BtnState;
    public bool isPressHome=false;
    private MLInputController _controller;

    // Start is called before the first frame update
    void Start()
    {
        // Start input
        MLInput.Start(); //入力取得開始
        MLInput.OnControllerButtonDown += HandleOnButtonDown; //ボタン押下に任意の関数を適用
        MLInput.OnControllerButtonUp += HandleOnButtonUp;  //ボタンから手を離したときに任意の関数を適用
        _controller = MLInput.GetController(MLInput.Hand.Left); //コントローラーを選択
    }

    // Update is called once per frame
    void Update()
    {
        if(BtnState == ButtonStates.Pressed)
        {
            this.transform.Translate(0.0f,0.1f,0.0f,Space.World);
        }
        
        TriggerButton();
        TouchPad();
    }

    void HandleOnButtonUp(byte controller_id, MLInputControllerButton button)
    {
        // Callback - Button Up
        if (button == MLInputControllerButton.Bumper)
        {
            BtnState = ButtonStates.JustReleased;
        }


        if (button == MLInputControllerButton.HomeTap)
        {
            isPressHome = false;
        }
    }

    void HandleOnButtonDown(byte controller_id, MLInputControllerButton button)
    {
        // Callback - Button Down
        if (button == MLInputControllerButton.Bumper)
        {
            BtnState = ButtonStates.Pressed;
        }

        if (button == MLInputControllerButton.HomeTap)
        {
            isPressHome = true;
            Debug.Log("test:" + isPressHome);
            this.transform.Translate(0.0f, 0.1f, 0.0f, Space.World);
        }
    }

    void TriggerButton()
    {
        if (_controller.TriggerValue >= 1.0f) //トリガーボタンの入力取得
        {
            this.transform.Translate(0.1f,0.0f,0.0f,Space.World);
        }
    }

    void TouchPad()
    {
        if (_controller.Touch1PosAndForce.z > 0.0f){ //押している間だけ
            float X = _controller.Touch1PosAndForce.x; //タッチパッドの位置取得
            this.transform.Translate(X, 0.0f, 0.0f, Space.World);
        }
    }
}

解説

見ての通りなのですが、まず起動時にInput.Startやコントローラの宣言を行っておく必要があるほか、ボタン押下時、押下終了時に関数を適用させるために MLInput.OnControllerButtonDown += HandleOnButtonDown; というようなコードを書く必要があります。
HandleOnButtonDown(...) では、押下されたボタンによって処理を変えることができます。
ただし、この関数で取得できるボタンは Bumper , HomeTap のみとなっており、残りの2つのボタンに関しては違う受け取り方をする必要があります。

TriggerButton() では、Triggerボタンの入力を取得しています。
ボタンの押し込み具合を0.0~1.0までの値で受け取ることができます。
ここでは
if (_controller.TriggerValue >= 1.0f)
という風にすることで、完全に押し込んだ時のみキューブが移動するようにしてあります。

TouchPad()では、TouchPadの入力を取得しています。
if (_controller.Touch1PosAndForce.z > 0.0f)
という条件は、「指がタッチパッドに触れている間」ということを意味します。この条件をなくすと、一度タッチパッドに触れると、指を離しても入力され続けてしまいます。
また、 _controller.Touch1PosAndForce.x により、触れているタッチパッドの位置を取得することができます。同じくy座標も取得できます。
このコードにより、真ん中より右側を触るとキューブが右側に、左側を触ると左側に移動するようになっています。

【Unity】キズナアイでブレンドシェイプを試してみる

ただの備忘録です



モデルのインポートについてはこちらを参考にしました

qiita.com


ブレンドシェイプとは?

ボーンを使わずにメッシュの頂点を動かしてアニメーションする技術です
表情の制御なんかによく使われるようです

パラメータの場所

Skinned Mesh Renderer コンポーネントを探す必要があります
これはツリー構造の下層にあり、今回は U_Char/U_Char_1 にアタッチされているものを使用します

f:id:imln20:20190923014535p:plain

インスペクターを確認するとコンポーネントの一番上に BlendShapes という項目があるので開くとパラメータ群が現れます

f:id:imln20:20190923014545p:plain

ここのパラメータを0~100でいじることで、アニメーションさせることができます

f:id:imln20:20190923014917p:plain

スクリプトから呼び出す

U_Char_1 にスクリプトをアタッチします
以下は毎フレームだんだんウインクしていくスクリプトです

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

public class bsScript : MonoBehaviour {

    private SkinnedMeshRenderer blendshape;
    float value = 0;

    // Use this for initialization
    void Start () {
        blendshape = this.GetComponent<SkinnedMeshRenderer>();
    }
	
	// Update is called once per frame
	void Update () {
        blendshape.SetBlendShapeWeight(2, value); //(ブレンドシェイプの番号,セットする値)
        value += 1;
    }
}


(gifでアップしたかったけど圧縮大変だったから苦渋の選択でtwitter)(1時間くらい格闘した)

無理矢理動かしているだけなのであまり自然な動きではありません
三角関数とかをうまく使えばもう少し自然な動きにできそうですね


参考:
【3Dモデルの表情や形を自由自在に変えられる】Blenderでシェイプキーを作りUnityのブレンドシェイプで動かす方法 | Macアプリ開発ラボ