20200701のUnityに関する記事は4件です。

[Unity] Shaderのプロパティ名を自動取得してIDに変換する

前書き

UnityでShaderを作成した後にプロパティ名とか取得するけど、間違えたりするとめんどくさいときがありまして、実行時に自動でプロパティ名を取得してくれるスクリプトを作成しました。直接プロパティ名を入力するよりはIDに変換すると早いらしいのでそちらで対応してみました。

Unityのバージョンは2019.4.1f1を使用しています。
2018ですと使用している関数が対応していないので2019のLTSを使用することをお勧めします。

ソースコード

ImageやRenderer対応にするためにスクリプト上ではStartやAwakeで書かずに使う場所で取得してもらうようにしました。(もっといい方法あると思うが)
こんな感じで作ってみました。

ShaderController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.CompilerServices;

/// <summary>
/// シェーダー管理用スクリプト
/// 使用するマテリアルがあるオブジェクトの場所につける
/// </summary>
public class ShaderController : MonoBehaviour
{
    private Material shaderMaterial = null;
    private Dictionary<string, int> shaderPropertyDic;

    /// <summary>
    /// 初期化
    /// </summary>
    public void Initialize(Renderer renderer)
    {
        if (renderer == null)
            Debug.LogError("Renderer is null");
        shaderMaterial = renderer.material;
        GetShaderProperties();
    }

    public void Initialize(Image image)
    {
        if (image == null)
            Debug.LogError("Image is null");
        shaderMaterial = image.material;
        GetShaderProperties();
    }

    private void GetShaderProperties()
    {
        shaderPropertyDic = new Dictionary<string, int>();
        //Shaderのプロパティの数を取得し、名前とIDを登録する
        for (int i = 0; i < shaderMaterial.shader.GetPropertyCount(); i++)
        {
            string name = shaderMaterial.shader.GetPropertyName(i);
            int id = shaderMaterial.shader.GetPropertyNameId(i);
            shaderPropertyDic.Add(name, id);
        }
    }

    /// <summary>
    /// シェーダーのプロパティ名が存在するかどうか
    /// 存在するならそのIDを渡し、ないなら-1を返す
    /// </summary>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    private bool CheckPropertyName(string propertyName, out int id)
    {
        //すでに登録してあるかどうか
        if (shaderPropertyDic.ContainsKey(propertyName))
        {
            id = shaderPropertyDic[propertyName];
            return true;
        }

        Debug.LogError("そのプロパティ名は存在しません。プロパティ名:" + propertyName);
        id = -1;
        return false;
    }

    #region Setter

    /// <summary>
    /// ShaderにFloat型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetFloat(string propertyName, float value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetFloat(id, value);
    }

    /// <summary>
    /// ShaderにInt型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetInt(string propertyName, int value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetInt(id, value);
    }

    /// <summary>
    /// ShaderにColor型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetColor(string propertyName, Color value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetColor(id, value);
    }

    /// <summary>
    /// ShaderにMatrix4×4型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetMatrix(string propertyName, Matrix4x4 value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetMatrix(id, value);
    }

    /// <summary>
    /// ShaderにTexture型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetTexture(string propertyName, Texture2D value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetTexture(id, value);
    }

    /// <summary>
    /// ShaderにTextureのoffsetを指定する
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetTextureOffset(string propertyName, Vector2 value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetTextureOffset(id, value);
    }

    /// <summary>
    /// ShaderにTextureのScaleを指定する
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetTextureScale(string propertyName, Vector2 value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetTextureScale(id, value);
    }

    /// <summary>
    /// ShaderにVector4型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetVector(string propertyName, Vector4 value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetVector(id, value);
    }
    #endregion

    #region Getter

    /// <summary>
    /// プロパティ名を指定し、Float型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public float GetFloat(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return 0.0f;
        return shaderMaterial.GetFloat(id);
    }

    /// <summary>
    /// プロパティ名を指定し、int型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public int GetInt(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return 0;
        return shaderMaterial.GetInt(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Color型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Color GetColor(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Color.white;
        return shaderMaterial.GetColor(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Matrix4×4型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Matrix4x4 GetMatrix(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Matrix4x4.identity;
        return shaderMaterial.GetMatrix(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Texture型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Texture GetTexture(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return null;
        return shaderMaterial.GetTexture(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Textureのoffset値を取得する
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Vector2 GetTextureOffset(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Vector2.zero;
        return shaderMaterial.GetTextureOffset(id);
    }

    /// <summary>
    /// プロパティ名を指定し、TextureのScale値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Vector2 GetTextureScale(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Vector2.zero;
        return shaderMaterial.GetTextureScale(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Vector4型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Vector4 GetVector(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Vector4.zero;
        return shaderMaterial.GetVector(id);
    }
    #endregion

    /// <summary>
    /// プロパティ名一覧をログ表示
    /// </summary>
    public void LogPropertyName()
    {
        foreach (string key in shaderPropertyDic.Keys)
            Debug.Log(key);
    }
}


Dictionaryにプロパティ名をkey、そこから取得したIDをvalueとして登録します。
一通りのGet,Setがあるのでそれを使用して値を変えてあげる。

使用方法

使用するShaderとスクリプトをを用意します。
Shaderは適当にリムライトのShaderでテストしてみます。

RimLight.shader
Shader "Unlit/RimLight"
{
    Properties
    {
        _RimPower("Rim Power",Range(0.1,5.0)) = 2
        [HDR]
        _RimColor("Rim Color",Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent"}
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal:NORMAL;
            };

            struct v2f
            {
                float3 normal:NORMAL;
                float3 worldPos:TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            float _RimPower;
            fixed4 _RimColor;

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.normal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                float3 L = normalize(i.worldPos.xyz - _WorldSpaceCameraPos.xyz);
                float d = 1 - saturate(abs(dot(i.normal, L)));
                d = pow(d, _RimPower);
                return _RimColor * d;
            }
            ENDCG
        }
    }
}

NewBehaviourScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    [SerializeField]
    private ShaderController controller = null;

    // Start is called before the first frame update
    void Start()
    {
        controller.Initialize(GetComponent<Renderer>());
        //ログ表示
        controller.LogPropertyName();

        controller.SetFloat("_RimPower", 3.0f);
        //あえて間違えてみる
        controller.SetColor("Hoge", Color.red);
    }
}

とりあえず_RimPowerを0.1としてみてみます。
before / after
コメント 2020-07-01 195336.jpg

コメント 2020-07-01 195350.jpg

プロパティ名が表示され、値も反映されています。
適当に入れたプロパティ名Hogeもそんなものないんですがと怒られています。

終わりに

そもそもマテリアルやShader欲しい、取得したいってなったら随時追加したりと改造して広げてみてください。
少しでも役立ったら幸いです。

では、またどこかで・・・。

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

[Unity] Shaderのプロパティ名を間違えないようにする

前書き

UnityでShaderを作成した後にプロパティ名とか取得するけど、間違えたりするとめんどくさいときがありまして、実行時に自動でプロパティ名を取得してくれるスクリプトを作成しました。直接プロパティ名を入力するよりはIDに変換すると早いらしいのでそちらで対応してみました。

Unityのバージョンは2019.4.1f1を使用しています。
2018ですと使用している関数が対応していないので2019のLTSを使用することをお勧めします。

ソースコード

ImageやRenderer対応にするためにスクリプト上ではStartやAwakeで書かずに使う場所で取得してもらうようにしました。(もっといい方法あると思うが)
こんな感じで作ってみました。

ShaderController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.CompilerServices;

/// <summary>
/// シェーダー管理用スクリプト
/// 使用するマテリアルがあるオブジェクトの場所につける
/// </summary>
public class ShaderController : MonoBehaviour
{
    private Material shaderMaterial = null;
    private Dictionary<string, int> shaderPropertyDic;

    /// <summary>
    /// 初期化
    /// </summary>
    public void Initialize(Renderer renderer)
    {
        if (renderer == null)
            Debug.LogError("Renderer is null");
        shaderMaterial = renderer.material;
        GetShaderProperties();
    }

    public void Initialize(Image image)
    {
        if (image == null)
            Debug.LogError("Image is null");
        shaderMaterial = image.material;
        GetShaderProperties();
    }

    private void GetShaderProperties()
    {
        shaderPropertyDic = new Dictionary<string, int>();
        //Shaderのプロパティの数を取得し、名前とIDを登録する
        for (int i = 0; i < shaderMaterial.shader.GetPropertyCount(); i++)
        {
            string name = shaderMaterial.shader.GetPropertyName(i);
            int id = shaderMaterial.shader.GetPropertyNameId(i);
            shaderPropertyDic.Add(name, id);
        }
    }

    /// <summary>
    /// シェーダーのプロパティ名が存在するかどうか
    /// 存在するならそのIDを渡し、ないなら-1を返す
    /// </summary>
    /// <param name="propertyName"></param>
    /// <returns></returns>
    private bool CheckPropertyName(string propertyName, out int id)
    {
        //すでに登録してあるかどうか
        if (shaderPropertyDic.ContainsKey(propertyName))
        {
            id = shaderPropertyDic[propertyName];
            return true;
        }

        Debug.LogError("そのプロパティ名は存在しません。プロパティ名:" + propertyName);
        id = -1;
        return false;
    }

    #region Setter

    /// <summary>
    /// ShaderにFloat型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetFloat(string propertyName, float value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetFloat(id, value);
    }

    /// <summary>
    /// ShaderにInt型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetInt(string propertyName, int value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetInt(id, value);
    }

    /// <summary>
    /// ShaderにColor型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetColor(string propertyName, Color value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetColor(id, value);
    }

    /// <summary>
    /// ShaderにMatrix4×4型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetMatrix(string propertyName, Matrix4x4 value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetMatrix(id, value);
    }

    /// <summary>
    /// ShaderにTexture型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetTexture(string propertyName, Texture2D value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetTexture(id, value);
    }

    /// <summary>
    /// ShaderにTextureのoffsetを指定する
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetTextureOffset(string propertyName, Vector2 value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetTextureOffset(id, value);
    }

    /// <summary>
    /// ShaderにTextureのScaleを指定する
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetTextureScale(string propertyName, Vector2 value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetTextureScale(id, value);
    }

    /// <summary>
    /// ShaderにVector4型の値を渡す
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <param name="value">渡す値</param>
    public void SetVector(string propertyName, Vector4 value)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return;
        shaderMaterial.SetVector(id, value);
    }
    #endregion

    #region Getter

    /// <summary>
    /// プロパティ名を指定し、Float型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public float GetFloat(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return 0.0f;
        return shaderMaterial.GetFloat(id);
    }

    /// <summary>
    /// プロパティ名を指定し、int型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public int GetInt(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return 0;
        return shaderMaterial.GetInt(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Color型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Color GetColor(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Color.white;
        return shaderMaterial.GetColor(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Matrix4×4型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Matrix4x4 GetMatrix(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Matrix4x4.identity;
        return shaderMaterial.GetMatrix(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Texture型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Texture GetTexture(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return null;
        return shaderMaterial.GetTexture(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Textureのoffset値を取得する
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Vector2 GetTextureOffset(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Vector2.zero;
        return shaderMaterial.GetTextureOffset(id);
    }

    /// <summary>
    /// プロパティ名を指定し、TextureのScale値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Vector2 GetTextureScale(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Vector2.zero;
        return shaderMaterial.GetTextureScale(id);
    }

    /// <summary>
    /// プロパティ名を指定し、Vector4型の値を取得
    /// </summary>
    /// <param name="propertyName">プロパティ名</param>
    /// <returns></returns>
    public Vector4 GetVector(string propertyName)
    {
        int id;
        if (!CheckPropertyName(propertyName, out id))
            return Vector4.zero;
        return shaderMaterial.GetVector(id);
    }
    #endregion

    /// <summary>
    /// プロパティ名一覧をログ表示
    /// </summary>
    public void LogPropertyName()
    {
        foreach (string key in shaderPropertyDic.Keys)
            Debug.Log(key);
    }
}


Dictionaryにプロパティ名をkey、そこから取得したIDをvalueとして登録します。
一通りのGet,Setがあるのでそれを使用して値を変えてあげる。

使用方法

使用するShaderとスクリプトをを用意します。
Shaderは適当にリムライトのShaderでテストしてみます。

RimLight.shader
Shader "Unlit/RimLight"
{
    Properties
    {
        _RimPower("Rim Power",Range(0.1,5.0)) = 2
        [HDR]
        _RimColor("Rim Color",Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent"}
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float3 normal:NORMAL;
            };

            struct v2f
            {
                float3 normal:NORMAL;
                float3 worldPos:TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            float _RimPower;
            fixed4 _RimColor;

            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                o.normal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                float3 L = normalize(i.worldPos.xyz - _WorldSpaceCameraPos.xyz);
                float d = 1 - saturate(abs(dot(i.normal, L)));
                d = pow(d, _RimPower);
                return _RimColor * d;
            }
            ENDCG
        }
    }
}

NewBehaviourScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    [SerializeField]
    private ShaderController controller = null;

    // Start is called before the first frame update
    void Start()
    {
        controller.Initialize(GetComponent<Renderer>());
        //ログ表示
        controller.LogPropertyName();

        controller.SetFloat("_RimPower", 3.0f);
        //あえて間違えてみる
        controller.SetColor("Hoge", Color.red);
    }
}

とりあえず_RimPowerを0.1としてみてみます。
before / after
コメント 2020-07-01 195336.jpg

コメント 2020-07-01 195350.jpg

プロパティ名が表示され、値も反映されています。
適当に入れたプロパティ名Hogeもそんなものないんですがと怒られています。

終わりに

そもそもマテリアルやShader欲しい、取得したいってなったら随時追加したりと改造して広げてみてください。
少しでも役立ったら幸いです。

では、またどこかで・・・。

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

日本語対応したDeepL APIを使用して、「STT→DeepL→TTS」の同時通訳を試作してみた

はじめに

DeepL Proが日本語に対応したということで、UnityでDeepL APIを試してみました。
せっかくなので、同時通訳っぽいものを作れたら楽しいなと思い、
STTで音声をテキスト化

DeepLにテキストを渡し、翻訳されたテキストを返してもらう

翻訳されたテキストをTTSで音声出力

の流れで組み込みました。

(作業環境…Unity 2019.3.1f)

STTとTTS

今回、STTとTTSは無料で手軽に試せるIBMのWatsonを使用しました。
2020年7月現在、Unity Asset StoreからWatson SDKは入手できなくなっているので、
https://github.com/watson-developer-cloud/unity-sdk
上記からダウンロードし、Unityプロジェクトにインポートする必要があります。

STT、TTS共にサンプルシーンがあるので、今回はそこで使用されているサンプルコードをほぼそのまま流用しました。
(IBM Cloudにログインして、STTとTTSを作成し、それぞれのAPIキーとURLを利用してください)
ただSTTについては、認識された発話が垂れ流しになるのを防ぐため、
Confidence(確信度)が0.5以上になった時を確定して、DeepLに投げるようにしました。

STTで認識したい言語は下記を、
https://cloud.ibm.com/docs/speech-to-text?topic=speech-to-text-models&locale=ja
TTSで認識したい言語は下記を参考にしてください。
https://cloud.ibm.com/docs/text-to-speech?topic=text-to-speech-voices&locale=ja

DeepL API

DeepL API ドキュメント:https://www.deepl.com/docs-api/introduction/

APIの呼び出しにはUnityWebRequestを使用しました。
(参考:https://kan-kikuchi.hatenablog.com/entry/UnityWebRequest
APIをPOSTで呼んでいます。

DeepLReceiver.cs
    [SerializeField]
    string lang;//翻訳したい言語を指定

    private IEnumerator DeepLTranslate(string text)
    {

        string base_word = text;

        WWWForm form = new WWWForm();
        form.AddField("auth_key", [KEY]);
        form.AddField("text", base_word);
        form.AddField("target_lang", lang);

        UnityWebRequest request = UnityWebRequest.Post("https://api.deepl.com/v2/translate", form);

        yield return request.SendWebRequest();

        if (request.isHttpError || request.isNetworkError)
        {

            Debug.Log(request.error);
        }
        else
        {
            readJson = request.downloadHandler.text;
            Debug.Log(request.downloadHandler.text);
            JsonRead(readJson);
        }
    }

DeepLからは下記のようなJsonが返ってくるので、

{
    "translations": [{
        "detected_source_language":"JA",
        "text":"Hallo, How are you?"
    }]
}

翻訳されたtextだけを取り出して、TTSに渡せるようにします。

DeepLReceiver.cs
    [Serializable]
    public class RESPONSEJSON
    {
        public RESPONSE[] translations;
    }
    [Serializable]
    public class RESPONSE
    {
        public string detected_source_language;
        public string text;
    }

    string ttsText;

    private void JsonRead(string json)
    {
        string inputString = json;
        RESPONSEJSON responseJson = JsonUtility.FromJson<RESPONSEJSON>(inputString);
        ttsText = responseJson.translations[0].text;
    }

実際に遊んでみた動画

即席試作といえども、画面に文字だけでは味気ないので、
弊社のオリジナルキャラクター、「ハニカ」に翻訳文を喋らせました。
(Watson TTSの声質が微妙だけど、キャラクターがいるとやっぱり見栄えが可愛い)
↓是非動画でご覧ください。クリックで再生されます。
IMAGE ALT TEXT HERE
動画内の遊んだ履歴:
日本語→英語
日本語→スペイン語
中国語→フランス語
英語→日本語
ドイツ語→英語
(楽しかったので日本語以外でも遊んでみました)

文字数にもよりますが、STTからテキストが渡って翻訳→TTSにのって音声出力、までは
体感で2秒かからないくらいですね。
実用する場合には、ここの処理時間なども正確に計測しておきたいところです。

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

Unity2D ボタン式のスイッチ実装

tl;dr

ボタン式のスイッチを実装する際にinterfaceを利用すると簡単に作れる、という話です

モチベーション

ボタンを押すと何かが動く、そんなギミックを作る事は多々あるかと思うのですが、
スイッチやボタンで検索すると「特定の動作専用のボタン」みたいなのが多く(先人に感謝)、「汎用的に使えるスイッチ」みたいな実装がなかったので書く

ひとまずよくあるスイッチを実装

20200609180816.png
※円で囲った石がスイッチなのである(手抜き)

まずはスイッチ(石)を踏むと隣にある木を飛ばす

public class SwitchObject : MonoBehaviour
{
  public GameObject EffectObject;

  private void OnCollisionEnter2D(Collision2D other)
  {
    EffectObject.GetComponent<Wood>().OnSwitch();
  }
}
public class Wood : MonoBehaviour
{
  bool Depature = false;
  private void Update()
  {
    if (Depature)
    {
      transform.Translate(Vector3.up * Time.deltaTime * 5, Space.World);
    }
  }

  public void OnSwitch()
  {
    Depature = true;
  }
}


EffectObjectにwoodを設定して確認
20200609181103.png

飛んでいく

次は左の岩も飛ばそう

まずは木からコピペ

public class Stone : MonoBehaviour
{
  bool Depature = false;
  private void Update()
  {
    if (Depature)
    {
     transform.Translate(Vector3.up * Time.deltaTime * 5, Space.World);
    }
  }

  public void OnSwitch()
  {
    Depature = true;
  }
}
// 飛ばすオブジェクトはStoneになる
EffectObject.GetComponent<Stone>().OnSwitch();

20200609180821.png

なんでも飛んでいく

汎用的にしたい

これだとSwitchをたくさん作らないといけないので大変になる。

Switchで押されるオブジェクトは共通してOnSwitch()を持っている。OnSwitchが実装されたSwitchならば共通して扱いたい。interfaceで実装していこう。

interface ISwitch {
  void OnSwitch();
}

public class SwitchObject : MonoBehaviour
{
  public GameObject EffectObject;

  private void OnCollisionEnter2D(Collision2D other)
  {
    EffectObject.GetComponent<ISwitch>().OnSwitch();
  }
}

Stone/Woodにinterfaceを持たせる

// ISwitchを持たせる
public class Wood : MonoBehaviour, ISwitch
{
  bool Depature = false;
  private void Update()
  {
    if (Depature)
    {
      transform.Translate(Vector3.up * Time.deltaTime * 5, Space.World);
    }
  }

  public void OnSwitch()
  {
    Depature = true;
  }
}

これでStoneだろうがWoodだろうがなんだろうがISwitchさえ持っていればOnSwitchを利用できる
配列にすることで同時に扱える

public class SwitchObject : MonoBehaviour
{
  public GameObject[] EffectObjects;

  private void OnCollisionEnter2D(Collision2D other)
  {
    foreach(GameObject gObj in EffectObjects){
      gObj.GetComponent<ISwitch>().OnSwitch();
    }
  }
}

おわり

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