20200919のUnityに関する記事は5件です。

【Unity&Hololens2】Azure Speech Servicesを日本語音声に対応させる

Azure Speech ServicesをUnityで日本語で使いたい!

Unity&Hololens2 超初心者の自分用のメモ書きです。
公式チュートリアルでAzure Speech Servicesを導入することはできたのだが
日本語でしゃべってもローマ字になってしまう...
image.png

これは当たり前で初期設定では英語に設定されているから。
ということでどこから変えるかというと、
image.png
Lunarcomの
image.png
LunarcomSpeechRecognizerというコンポーネントから変更できます。
開いてみると

using UnityEngine;
using Microsoft.CognitiveServices.Speech;

public class LunarcomSpeechRecognizer : MonoBehaviour
{
    private string recognizedString = "Select a mode to begin.";
    private object threadLocker = new object();

    private SpeechRecognizer recognizer;

    private bool micPermissionGranted = false;
    ///private bool scanning = false;

    private string fromLanguage = "en-US";

    private LunarcomController lunarcomController;
~~~~~~~~~~~~~~(以下略

fromLanguageとかいうあからさまに言語を変換できそうな変数があるのでここを日本語に変更してあげるだけで完了します。
利用できる言語一覧
日本語はja-JPなのでそのまま入れてあげれば日本語に対応してくれます。

private string fromLanguage = "ja-JP";

変更してからしゃべると
image.png
日本語になってくれました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【開発効率アップ】初めてのタスク管理「Trello」を使ってみよう!

今回はゲーム開発を含め、様々なシーンで用いられている「Trello」というサービスを紹介します。
これは私もよく利用しているサービスで「タスク管理って何?」という方はぜひ読んでみてくださいね。

ブログ本文はこちらです。
https://tedenglish.site/dev-howto-trello/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C#】シンプルな有限ステートマシンの実装。

久しぶりの投稿になります.

実装

有限ステートマシンの実装になります.

StateMachine.cs
/// <summary>
/// 有限ステートマシン(FSM), where T : class
/// </summary>
public class StateMachine<T> 
    where T : class
{
    private T m_Owner;
    private State<T> m_CurrentState;
    public State<T> currentState { get {return m_CurrentState;} set{ m_CurrentState = value;} }
    private State<T> m_PreviousState;
    public State<T> previousState { get {return m_PreviousState;} set{ m_PreviousState = value;} }
    private State<T> m_GlobalState;
    public State<T> globalState { get {return m_GlobalState;} set{ m_GlobalState = value;} }
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public StateMachine(T owner){
        m_Owner = owner;
        m_CurrentState = new NullState<T>();
        m_PreviousState = new NullState<T>();
        m_GlobalState = new NullState<T>();
    }
    /// <summary>
    /// 現在の状態を実行する
    /// </summary>
    public void Update(){
        m_GlobalState.Execute(m_Owner);
        m_CurrentState.Execute(m_Owner);
    }
    /// <summary>
    /// 現在のStateを変更する
    /// </summary>
    public void ChangeState(State<T> newState){
        // Assert(newState != null);
        m_PreviousState = m_CurrentState;
        m_CurrentState.Exit(m_Owner);
        m_CurrentState = newState;
        m_CurrentState.Enter(m_Owner);
    }

    /// <summary>
    /// 前のStateに変更する
    /// </summary>
    public void RevertToPreviousState(){
        ChangeState(m_PreviousState);
    }
}

ステートの実装になります.

State.cs
public interface State<T>
    where T : class
{
    /// <summary>
    /// このStateになった時に呼ばれる
    /// </summary>
    void Enter(T t);
    /// <summary>
    /// このState中はずっと呼ばれる
    /// </summary>
    void Execute(T t);
    /// <summary>
    /// このStateから変わる時に呼ばれる
    /// </summary>
    void Exit(T t);
}

ヌルステートの実装になります.

NullState.cs
/// <summary>
/// null避けのためのクラス
/// </summary>
public class NullState<T>: State<T> 
    where T : class
{
    public void Enter(T t){}
    public void Execute(T t){}
    public void Exit(T t){}
}

使用方法

Main.cs
void main(){
    // 遷移を管理するクラス
    MyClass myClass = new MyClass();
    // ステートマシンの宣言
    StateMachine<MyClass> stateMachine = new StateMachine<MyClass>(myClass);
    // stateインターフェースを実装したクラス
    State<MyClass> myState = new MyState();
    // 現在の状態を変更
    stateMachine.ChangeState(myState);
    // 現在のステートを実行
    stateMachine.Update();
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

NrealSDK1.3.0のInput-ControllerInfoシーンを観察してみる(Inputシーン編1/3)

はじめに

NrealSDK 1.3.0にあるInput-ControllerInfoシーンを観察していきます。
Inputのサンプルシーンは3つあるので、本記事は(1/3)としています
もし間違いがあれば、指摘いただければ幸いです。

Input-ControllerInfoシーンについて

Nrealの各Inputパラメータを確認できるシーン
NRSDK>Domos>Inputに配置されている

シーン構成

シーン構成
NRCameraRig
NRInput
Cube
ControllerInfoDisplayUI

NRCameraRig、NRInput

Nrealに対応したカメラ、入力システム
別のサンプルシーンで観察してます。
NrealSDK1.3.0のHelloMRシーンを観察してみる

Cube

Ray判定などに使うただのCube。
デフォルトとの違いを強いて言うなら子にDirectional Lightがあるくらい

ControllerInfoDisplayUI

スクリプト名 役割
ControllerInfoDisplayUI Nrealコントローラーから入力を受け取り、Canvasへ反映させる重要なスクリプト。Updateメソッドで処理しているため、毎フレーム呼び、更新している。

mainInfoTxt
入力に関係するパラメータを表示するテキスト
extraInfoTxt
ボタンのログを表示するテキスト

入力

名前
controller count 現在接続されている利用可能なコントローラの数
type 現在のコントローラのタイプ(EDITOR、UNKNOWN、NREALLIGHT、PHONE、FINCHSHIFT)
current debug hand コントローラが左右どちらか。デフォルトは右
position available コントローラーのポジションが利用可能か
rotation available コントローラーのローテーションが利用可能か
gyro available コントローラのジャイロセンサーが利用可能か
accel available コントローラの加速度センサーが利用可能か
mag available コントローラの地磁気センサーが利用可能か
battery available コントローラのバッテリーが利用可能か
vibration available コントローラのバイブレーションが利用可能か
rotation コントローラーのローテーション(Quaternion)
position コントローラーのポジション(Vector3)
touch タッチしたコントローラー上の座標(Vector2)(UnityEdiorでは、カーソルキーで移動可)
trigger button touchpadButtonクリック(UnityEdiorでは、左クリック)
home button homeButtonクリック(UnityEdiorでは、スクロールクリック)
app button appButtonクリック(UnityEdiorでは、右クリック)
grip button gripButtonクリック
touchpad button touchpadButtonクリック
gyro コントローラーの角速度(Vector3)
accel コントローラーの加速度(Vector3)
mag コントローラーの地磁気(Vector3)
battery コントローラーのバッテリー(int)

まとめ

Nrealで取得できるパラメータを理解するために使うシーンでした。
UnityEditor上で動作するのは嬉しいです(NREmulatorController.cs)
NRSDKでHandTrackingは実装されていないみたい。

さいごに

NRInputクラスから各パラメータを取得するメソッドがあることも確認できたので、楽に使えそうですね。
これからもNrealについての記事を書いていきます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity(C#)】画像データと一緒に関連するデータを紐づけて保存する

はじめに

【Unity(C#)】テクスチャを画像データに変換して端末に保存、読み込み
↑前回の続きです。

今回は保存した画像データに文字列の情報も付与して保存したいと思います。

考え方

画像と文字列を1つの塊として構造体を定義します。
その構造体をJson形式として保存します。
読み込み時にはその構造体をデシリアライズします。

構造体.png

コード

コードの構成は下記です。
①構造体
②Json変換Utilityクラス
③構造体を保存、読み込みするクラス


構造体

まずは構造体を定義します。
画像のバイナリデータはFile.WriteAllBytesで書き込むので
構造体に持たせるデータは画像データの保存先のパスとしました。

using System;

/// <summary>
/// 画像データの構造体
/// </summary>
[Serializable]
public struct ImageData
{
    /// <summary>
    /// 画像の保存先パス
    /// </summary>
    public string ImageSavePath;

    /// <summary>
    /// 画像の名前
    /// </summary>
    public string ImageName;

    /// <summary>
    /// コンストラクタ
    /// </summary>
    /// <param name="imageSavePath">保存先のパス</param>
    /// <param name="imageName">保存名</param>
    public ImageData(string imageSavePath,string imageName)
    {
        this.ImageSavePath = imageSavePath;
        this.ImageName = imageName;
    }
}

Json変換Utilityクラス

次に構造体をJson形式に変換するクラスを定義します。
【参考リンク】:【Unity(C#)】JsonUtilityを使ったセーブ、ロードの実装

using System;
using System.IO;
using UnityEngine;

/// <summary>
/// Save、Load機能の実装
/// </summary>
public static class JsonDataUtility
{
    /// <summary>
    /// 書き込み機能
    /// </summary>
    /// <param name="imageData">シリアライズするデータ</param>
    public static void Save(ImageData imageData,string path)
    {
        //シリアライズ実行
        string jsonSerializedData = JsonUtility.ToJson(imageData);
        Debug.Log(jsonSerializedData);

        //実際にファイル作って書き込む
        using (var sw = new StreamWriter (path, false)) 
        {
            try
            {
                //ファイルに書き込む
                sw.Write (jsonSerializedData);
            }
            catch (Exception e) //失敗した時の処理
            {
                Debug.Log (e);
            }
        }
    }

    /// <summary>
    /// 読み込み機能
    /// </summary>
    /// <returns>デシリアライズした構造体</returns>
    public static ImageData Load(string path)
    {
        ImageData jsonDeserializedData = new ImageData();

        try 
        {
            //ファイルを読み込む
            using (FileStream fs = new FileStream (path, FileMode.Open))
            using (StreamReader sr = new StreamReader (fs)) 
            {
                string result = sr.ReadToEnd ();
                Debug.Log(result);

                //読み込んだJsonを構造体に入れる
                jsonDeserializedData = JsonUtility.FromJson<ImageData>(result);
            }
        }
        catch (Exception e) //失敗した時の処理
        {
            Debug.Log (e);
        }

        //デシリアライズした構造体を返す
        return jsonDeserializedData;
    }
}

構造体を保存、読み込みするクラス

構造体を保存、読み込みするクラスです。
他にもいろいろやってますが、サンプルなので良しとします。

using System.IO;
using UniRx;
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 構造体を保存、読み込み
/// </summary>
public class UseStructData : MonoBehaviour
{
    [SerializeField] private Button _saveButton;
    [SerializeField] private Button _loadButton;
    [SerializeField] private Button _resetButton;
    [SerializeField] private InputField _inputField;
    [SerializeField] private Text _inputText;
    [SerializeField] private Text _loadText;
    [SerializeField] private Image _paintImage;
    [SerializeField] private Image _loadImage;
    [SerializeField] private Painter _painter;

    private const string IMAGE_SAVE_FOLDER = "Image";
    private const string IMAGE_DATA_SAVE_FOLDER = "ImageData";
    private const string PNG = ".png";
    private const string JSON = ".json";

    ///  /// <summary>
    /// 保存先のパス取得
    /// </summary>
    /// <param name="folderName">区切りのフォルダ名</param>
    /// <returns>保存先のパス</returns>
    private string GetSavePath(string folderName,string fileName,string type)
    {
        string directoryPath = Application.persistentDataPath + "/" + folderName + "/";

        if (!Directory.Exists(directoryPath))
        {
            //まだ存在してなかったら作成
            Directory.CreateDirectory(directoryPath);
            return directoryPath + fileName + type;
        }

        return directoryPath + fileName + type;
    }

    private void Start()
    {
        //セーブボタン
        _saveButton.OnPointerClickAsObservable().Subscribe(_ =>
            {
                SaveImageData("SoftCream");

                //リセット
                _painter.ResetTexture();
                _inputField.text = "";
            })
            .AddTo(this);
        //ロードボタン
        _loadButton.OnPointerClickAsObservable().Subscribe(_ => LoadImageData("SoftCream")).AddTo(this);
        //リセットボタン
        _resetButton.OnPointerClickAsObservable().Subscribe(_ => _painter.ResetTexture()).AddTo(this);;
    }

    /// <summary>
    /// 構造体をシリアライズ
    /// </summary>
    private void SaveImageData(string fileName)
    {
        string pngPath = GetSavePath(IMAGE_SAVE_FOLDER, fileName, PNG);
        string jsonPath = GetSavePath(IMAGE_DATA_SAVE_FOLDER, fileName, JSON);

        //構造体にパス、名前を入れる これでひとつの塊
        ImageData imageData =new ImageData(pngPath,_inputText.text);
        //Pngに変換
        byte[] bytes = _paintImage.sprite.texture.EncodeToPNG();
        //保存
        File.WriteAllBytes(pngPath, bytes);
        //構造体をJsonに変換
        JsonDataUtility.Save(imageData,jsonPath);
    }

    /// <summary>
    /// テクスチャに変換&読み込み
    /// </summary>
    private void LoadImageData(string fileName)
    {
        string jsonPath = GetSavePath(IMAGE_DATA_SAVE_FOLDER, fileName, JSON);
        ImageData imageData = JsonDataUtility.Load(jsonPath);
        //読み込み
        byte[] bytes = File.ReadAllBytes(imageData.ImageSavePath);
        //画像をテクスチャに変換
        Texture2D loadTexture = new Texture2D(2, 2);
        loadTexture.LoadImage(bytes);
        //テクスチャをスプライトに変換
        _loadImage.sprite = Sprite.Create(loadTexture, new Rect(0, 0, loadTexture.width, loadTexture.height), Vector2.zero);
        //画像の名前を表示
        _loadText.text = imageData.ImageName;
    }
}

Directory.Exists

新しくディレクトリを作って保存先のパスとして利用する方法が地味に詰まりました。
Directory.Existsでディレクトリが存在しているか確認して
分岐処理を用意しないとエラーが出ました。

        if (!Directory.Exists(directoryPath))
        {
            //まだ存在してなかったら作成
            Directory.CreateDirectory(directoryPath);
            return directoryPath + fileName + type;
        }

デモ

上品なイラストとそのイラストの名前として入力した文字列を保存し、
読み込むことに成功しました。

Qiita画像保存2.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む