20191219のUnityに関する記事は13件です。

UnityでMonaparty(その2)

2019年のまとめ(その2)です。

はじめに

UnityでMonaparty(その1)ではMonapartyのAPIを使って様々なデータを取得、加工して遊んでみました。

前述したとおりAPIを使ってトークンの送金、発行も可能です。今回は「送金」について書いてみます。ちなみにこの送金が出来るまでに自分は3か月くらいかかったのですが記念にその期間のことも最後に書いてみます。

また「送金」周りはシビアですので各自で検証をお願いします。

NBitcoinを使う(1)

「モナコインなのに?」

送金をするには署名をするわけですが、その「署名」をするのに使用します。

NBitcoinとはBitcoinをC#で扱うためにNicolas Dorierさんが開発されたライブラリです。

また、そのNBitcoinでアルトコインを使用するため、各コインのdeveloperさん達によりコードが追加されております。そこにはなんとモナコインもあり、developerさんにとても感謝です。(下記リンクよりどなたか確認してみましょう)

NBitcoin
NBitcoin.Altcoins

この2つをVisual Studio等から何というかその、、、"NuGet"します。

NBitcoinを使う(2)

その次にNBitcoinをコンパイル?します。
詳しくはこちら

git clone https://github.com/MetacoSA/NBitcoin/
cd NBitcoin/NBitcoin
dotnet publish -c Release -f netstandard2.0
Remove-Item -Force -Recurse .\bin\Release\netstandard2.0\publish\runtimes\

すると「netstandard2.0」というファイルが出来たかと思います。

そしてここがポイントなのですが、その中のファイルから
・「NBitcoin」
・「NBitcoin.Altcoins」
・「System.Buffers」
・「Newtonsoft.Json」
・「Microsoft.Extensions.Logging.Abstractions」

だけを残し、Unityの「Assets」の中へ放り込みます。
エラーが出る場合は色々試してみてください。(たぶんJson周りで出るかも?)

使い方

下記よりNBitcoinの使い方が学べますので、とりあえずBitcoinのTestnet環境で試してみましょう。
Programming The Blockchain in C# 日本語

ただここで1つ落とし穴があり、自分はここで沼にハマり長い間浸かっていました。と言うのもNBitcoinではQBitNinjaという"Transactionの中身を良い感じに整理してくれるもの"を使っており、モナコインでは工夫が必要です。

結果的に署名前までのTransactionを組み上げてくれる「create_send」というAPIを使うのですが、そこに至るまでの余談は話がずれるので最後に書きます。

コード

未署名Txのリクエスト.cs
using NBitcoin;
using NBitcoin.Altcoins; //予測変換にMonacoinが出るようになります。

    private string unSignTxHex;  //取得した未署名Txを入れる
    private string signedTxHex;  //署名済みTxを入れる

    //Jsonの組み立て
    [Serializable]
    class MonapaApi
    {
        public Params1 @params;
        public int id = 0;
        public string jsonrpc = "2.0";
        public string method = "proxy_to_counterpartyd";
    }

    [Serializable]
    public class Params1
    {
        public string method = "create_send";
        public Params2 @params;
    }

    [Serializable]
    public class Params2
    {
        public bool allow_unconfirmed_inputs = false;
        public bool use_enhanced_send = true;
        public string encoding = "auto";
        public string pubkey = "公開鍵";
        public string source = "送り先";
        public string destination = "自分のアドレス";
        public string asset = "トークン名";
        public string memo = "メモ"
        public string memo_is_hex = "メモの16進数"
        public int quantity = 数量;
        public int fee_per_kb = 手数料;
        //public bool extended_tx_info = true; //何故かエラーになります
    }

    // 未署名Txの格納
    public class UnSignTxData
    {
        public string result;
    } 

    //未署名Txのリクエスト
    private void GetUnSignTxHex()
    {
        string url = "リクエスト先APIサーバー";

        MonapaApi monapaApi = new MonapaApi();
        string monapaJson = JsonUtility.ToJson(monapaApi);

        StartCoroutine(ReqUnSignTxHex(url , monapaJson));

        IEnumerator ReqUnSignTxHex(string url, string bodyJsonString)
        {
            UnityWebRequest postRequest = new UnityWebRequest(url, "POST");
            byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
            postRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw);
            postRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
            postRequest.SetRequestHeader("Content-Type", "application/json");

            yield return postRequest.SendWebRequest();

            UnSignTxData unSignTxData = new UnSignTxData();
            unSignTxData = JsonUtility.FromJson<UnSignTxData>(postRequest.downloadHandler.text);
            unSignTxHex = unSignTxData.result;

            if (postRequest.isHttpError || postRequest.isNetworkError)
            {
                Debug.Log(postRequest.error);
            }
            else
            {
                Debug.Log(postRequest.downloadHandler.text);
            }
    }
取得した未署名Txに署名する.cs
//上記の続きです。
private void SignRawTx()
    {
        //MonacoinのMainnetに接続
        NBitcoin.Network network = NBitcoin.Altcoins.Monacoin.Instance.Mainnet;

        //秘密鍵の読み込み
        var bitcoinPrivateKey = new BitcoinSecret("秘密鍵");
        network = bitcoinPrivateKey.Network;

        var transaction = Transaction.Create(network);
        transaction = Transaction.Parse(unSignTxHex, network);

        //署名する
        transaction.Sign(bitcoinPrivateKey, false);
        signedTxHex = transaction.ToHex();
    }

あとは signedTxHex を今までの要領で 「method = "broadcast_tx"」 を使いブロードキャストすればOK。返ってきたTxidをmpchain等で確認してみましょう。

なにか間違ってたらごめんなさい。

完成物

(その1)と同様です。

『monanosu』
https://monanosu.kotaroo.work/
※スマホの方は中央の"OK"を押して下さい。WiFi環境で遊びましょう。

「限定モナカード」が手に入る「宝箱探しゲーム」も先日追加しました。
https://twitter.com/7101kerokero/status/1204315335978958848?s=20

参考にしたもの

・『Counterpartyでアプリを簡単に作ろう!』
https://qiita.com/MissMonacoin/items/fedbf77f8b7aaefc037f

・『monacoind 不要の faucet を作ってみた (骨格だけ)』
https://qiita.com/cryptcoin-junkey/items/fc6d62c22d4444d98c45

・TwitterでアドバイスをくれるPさんありがとうございます。

おわりに

初めて作ったプログラムとの言い訳をしつつ、あらためて自分のコードを見るといろいろと突っ込みどころが多そうです。(アドバイス頂けたらうれしいです。)

記事の最初に「送金が出来るまでに自分は3か月くらいかかった」と書き後述する、と言いましたが疲れたのでその際に調べたことも含めて後日記事にします(たぶん)

それでは

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

[Unity]砂のように消えるShaderをつくる

この記事は近畿大学 Advent Calendar 2019 19日目の記事です。

はじめに

Shaderを勉強し始めてから早一週間, そろそろ何か作ってみなければと思い, Unityで砂のように消えるShaderを作りました.

Shaderとは

簡単に言うと,「描画方法に関するプログラム」です. Unityでは, デフォルトで一般的な描画処理をするShaderが用意されているのでUnity触ったことあるけど, Shader知らないという人もいると思います.

ShaderLab言語の簡単な説明

ShaderLab言語はUnityでShaderを記述する言語です.
Unityを起動して, Project->Create->Shader->Standard Surface Shaderで新規のShaderを作成します. 以下が作成した直後のコードです.

Shader "Custom/NewSurfaceShader"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

簡単に解説すると,

  • Properties
    • Inspectorウィンドウでパラメータの値を変更できるようにする.
    • 変数名("表示名",データ形式)= 初期値 で記述する(データ形式と変数の型は必ずしも一致しない).
  • Tags
    • レンダリングするタイミングや方法を指定する.
  • CGPROGRAM-ENDCG
    • この中で具体的な処理を書きます.
  • #pragma
    • システム固有機能の使用.
  • Input構造体
    • ここで宣言した変数をsurface関数で使用できます.
    • 詳しくは公式マニュアル参照.
  • surface関数
    • 具体的な描画処理を記述する.
    • 今回はo.Alpha(透明度)を操作することで砂のように消える機能を実装する.
    • Alphaが小さいほど透明になり, 0から1の値をとる.

準備

透明なシェーダを作るために以下のようにコードを書き換える.

Shader "Custom/NewSurfaceShader"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "Queue"="Transparent" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard alpha:fade
        #pragma target 3.0

        struct Input
        {
        };

        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            o.Albedo = _Color;
            o.Alpha = 1.0;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

奥を先に描画させるために描画順を遅くし, 半透明に描画するためにalpha:fadeの追加し, 今回使わないパラメータを削除した.

実装

Alphaをランダムに0から1の値をとるようにして, 粒の表現を実装する.
乱数生成用にInput構造体にfloat3 worldPos;を追加した. Adjustを変化させることでAlphaを調節することができる.

...
Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _Adjust ("Adjust", Range(-1,1))=0
    }
    SubShader
    {
        ...    
        float _Adjust;
        fixed4 _Color;

        float rand(float3 co)
        {
            return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 56.787))) * 43758.5453);
        }

        struct Input
        {
            float3 worldPos;
        };

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            o.Albedo = _Color;
            o.Alpha = clamp(rand(IN.worldPos)-_Adjust,0,1);
        }
...

実行してみると、
sand.gif
これだけだとすこし物足りないので,x軸とy軸の大きいほうからグラデーションのように消えていく機能と輪郭をぼやかす機能を増やして最終的なコードは以下のようにしました.
それぞれの機能のバランスをWeight1,2で調節できます.

...
Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _Adjust ("Adjust", Range(-1,1))=0
        _Weight1("Weight1",Range(0,1)) = 0.5
        _Weight2("Weight2",Range(0,1)) = 0.5
    }
    SubShader
    {
        ... 
        float _Adjust;
        fixed4 _Color;
        float _Weight1;
        float _Weight2;

        float rand(float3 co)
        {
            return frac(sin(dot(co.xyz, float3(12.9898, 78.233, 56.787))) * 43758.5453);
        }

        struct Input
        {
            float3 worldPos;
            float3 worldNormal;
            float3 viewDir;
        };

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            o.Albedo = _Color;
            float3 localPos = IN.worldPos - mul(unity_ObjectToWorld, float4(0,0,0,1)).xyz;
       //xyはxとyの和が大きいほど1に近づく
            float xy = 1/(1+exp((localPos.x+localPos.y)));
            //borderは視線ベクトルと法線ベクトルの内積の絶対値で, 垂直に交わる場合は0、平行に交わる場合には1になる.
            float border =  (abs(dot(IN.viewDir, IN.worldNormal)));
            o.Alpha = clamp(border*_Weight2+(1-_Weight2)*((xy*_Weight1+rand(localPos)*(1-_Weight1)))-_Adjust,0,1);
        }
...

結果

end.gif

(´・ω・`)
(´・ω:;.:…
(´:;….::;.:. :::;.. …..
end2.gif
これがやりたかっただけ

参考

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

CRI ADX2 LEのオーサリングツールAtomCraftがMacにも対応した話

CRIADXLEのオーサリングツール、AtomCraftとAtomViewerは長らくWindowsオンリーでしたが、今年に入ってついにMac版がリリースされました。
iOS向けにアプリを作っている方などは、Macしか持っていない方もおられると思いますが、これでデータの編集や確認が可能になりますね。
なお、商用のCRI ADX2でも同じくMac版がリリースされています。

CRI ADX2 LEとは

株式会社CRI・ミドルウェアから提供されている、オーディオミドルウェアです。
こちらからダウンロード可能です。
なお、利用については規約・利用契約内容をよくご確認ください。

インストール

DLしたものを解凍すると、tools/criatomex/macにインストーラーが入っています。こちらをダブルクリックでインストール。
アプリケーション/CRIWARE/CRI ADX2LE/Tools Ver.3.?にCriAtomCraft.appとCriAtomViewer.appが確認できます。
CriAtomCraftを開いてみましょう。

プロジェクトとデータを作る

「プロジェクトの新規作成」から任意のプロジェクトを作ります。
「マテリアルツリー」に入れたい音素材(wav)をドロップしましょう。
スクリーンショット 2019-12-19 18.24.02.png

キューを作成

今回は、1キューで3つのBGMが時間で切り替わる物を作ります。
ワークユニットツリー内でキューを作成し、トラックに入れた音素材を入れます。
適当なタイミングで、それぞれのボリュームをコントロールし、交互にフェードで再生されるようにしてみました。
スクリーンショット 2019-12-19 18.26.56.png

再生を確認

再生ボタンを押して、再生を確認してみます。

キューシートのビルド

ビルドしてUnityで再生できるようにしましょう。
「ビルド」→「Atomキューシートのビルド」を選択、今回はUnityで使いたいので、「追加出力」から「Unity Assets出力」をチェック。ビルドボタンを押します。
これで、必要なacfファイルとacbファイルが出来上がります。
スクリーンショット 2019-12-19 18.30.31.png

CriAtomViewerで確認

作られたacfとacbファイルをCriAtomViewerにドラッグ&ドロップします。
キュー名を選択して、再生してみましょう。
・・・ですが、自分のところでは暗号化された音声が流れてしまいました。これは自分の環境が商用CRI ADXを使っていて、かつ暗号化されたデータを再生したことがあるからかもしれません。作成済みのサンプルデータでも同様だったため、Unityでの再生を優先します。
スクリーンショット 2019-12-19 18.33.32.png

Unityで再生を確認

適当にサンプルシーンを改造して、再生してみます。
CRIWAREにいるCri Stomに、acfファイル、acbファイルを指定して・・・
スクリーンショット 2019-12-19 17.39.54.png

CRI AtomSourceにCueSheetとCueNameを指定。Play On Startなので、実行すれば再生されるはずです。
スクリーンショット 2019-12-19 17.39.37.png

実行してみます。

無事再生されました!

色々やってみよう

AtomCraftが使えると、ランダム再生やシーケンス再生などインタラクティブなオーディオ再生を色々使うことが可能です。
是非いろんな機能を試してみてください。

今回のサンプル作成にあたり、以下の素材を使わせていただきました。ありがとうございました。
楽曲素材:Music-Note.jp

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

以前のバージョンと比較しながら3DサポートされたProject Tinyを触ってみる

この記事はPONOS Advent Calendar 2019の21日目の記事です。

はじめに

本記事では、Project Tinyを以前のバージョンと比較しながら、
先日リリースされた3Dサポートバージョン(0.20.0-preview.3)の導入方法や使用感について
紹介していきます。

Project Tinyについて

コアランタイムサイズが極めて小さい、Unityの軽量版です。
用途としては、モバイルブラウザ向けゲームや
プレイアブル広告(広告内でゲーム等がプレイ可能な広告)を作成するための機能
として提供されています。
https://blogs.unity3d.com/jp/2018/12/05/project-tiny-preview-package-is-here/

以前はPackage ManagerにTiny Modeと表記されていましたが、
最新のバージョン(0.20.0-preview.3)ではProject Tinyの表記に変更されていました。

バージョンごとの大きな変更点

変更ログ
https://docs.unity3d.com/Packages/com.unity.tiny@0.16/changelog/CHANGELOG.html

ver0.13.2-preview

  • 2018年12月4日から公開
  • オープンβとしてPackageManagerに公開
  • Unity2018.3.0b12以降から使用可能
  • 専用のTiny Modeと呼ばれるモードで構築
  • ECSベースで作成
  • スクリプトはTypeScriptのみ

導入・作成方法

詳しい導入方法は紹介しませんが、htmlファイルを出力するまでの流れを紹介します。

  1. Tiny ModeとしてPackageManagerからインストール
  2. Editor上のTinyタブからTiny Mode用のプロジェクトを作成
  3. HierarchyからEntityGroup(シーンのようなもの)を作成、その中にEntityを作成
  4. 必要に応じてTypeScriptを作成し、Entityを制御

実行

Editorから実行するとローカルサーバーが立ち上がり、ブラウザ上で表示されます。
GameViewではQRコードが表示されているため、モバイルからの確認も可能です。
対応している出力形式はHTML5のみです。

ビルド

.utprojectファイルを選択してReleaseモードでBuildすることでhtmlファイルが出力されます。
ただし、表示するにはhtmlファイルをサーバーに配置する必要があります。
htmlファイルの出力先: [ProjectName]/⁨TinyExport⁩/[TinyProjectName]⁩/⁨html5⁩/release⁩/⁨bin⁩

スクリーンショット 2019-12-18 14.10.14.png

使用感

  • 今後C#が対応されるため、現状のTypeScriptから自動移行できる機能がないのであれば、
    スクリプトによる実装は様子見のほうがよいと思われます
  • 実行から確認までの時間は早く、GameViewにQRコードも表示されるため、
    本来の目的であるモバイルでの実装確認も容易に行える
  • 出力されたhtmlファイルからの実行も、ブラウザで読み込みまでの時間もほんの数秒でした
  • また、releaseビルドでSprite一枚のみを配置したバイナリのサイズは2MBでした

ver0.15.3-preview

  • 2019年5月31日から公開
  • Unity2019.2.0b3以降から使用可能
  • 以前のバージョンとの互換性はなし
  • TypeScriptのサポート廃止
  • C#対応
  • QRコード削除
  • DOTS APIサポート
  • DOTS modeの追加
  • プロジェクトファイルの拡張子が.utprojectから.projectファイルに変更
  • 一部Tinyの表記がDOTSに変更

導入・作成方法

詳しい導入方法は紹介しませんが、htmlファイルを出力するまでの流れを紹介します。

  1. Project TinyとしてPackageManagerからインストール
  2. エラーが出るので、PackageManagerからBurst(バーストコンパイラ)を1.1.2にアップデート
  3. DOTSモードに正常に移行しない場合があるので一度Unityを再起動
  4. Editor上のDOTSタブからTiny Projectを作成
  5. Hierarchyからシーンを作成し、シーン内にEntityを作成

実行・ビルド

選択したPlatformに合わせた形式で実行およびビルドされます。
実行時にビルドも合わせて行われるためhtmlファイルも出力されます。
htmlファイル出力先: [ProjectName]⁨/⁨Library⁩/DotsRuntimeBuild/⁨build⁩/[ProjectTinyName]/[ProjectTinyName]-[platform]-[buildtype]
ただし、表示するにはhtmlファイルをサーバーに配置する必要があります。

対応しているプラットフォームは、Mac、WindowsとWebです。

スクリーンショット 2019-12-18 16.53.13.png

スクリーンショット 2019-12-18 16.53.28.png

使用感

  • PackageManagerからインストール後にコンソール上にエラーが表示されたりと導入時点から躓いてしまいました forumに改善方法が載っていたため参考にしながら導入を進めることをおすすめします
    https://forum.unity.com/threads/project-tiny-preview-0-16-1-c-available-and-upcoming-changes.708875/
  • ver0.13.2と同様に専用のEditorモードでの作成になりますが、多少、名称等は変わりましたが機能自体は然程変わっていなかったです
  • 実行の際に合わせてビルドを行うため、初回は時間がかかりますが二回目以降は数秒で確認ができます。 できれば実行とビルドは分けて、Editor上で確認できるのが理想なところです
  • C#対応後でも高速に起動・読み込み
  • releaseビルドでSprite一枚のみを配置したバイナリのサイズは1.7MB

ver0.20.0-preview.3

3Dサポートリリース!
https://forum.unity.com/threads/project-tiny-fall-update-tiny-racing-preview-3-020-0-is-available.792999/

  • 2019年12月12日から公開
  • Unity2019.3.0f1以降から使用可能
  • 3Dサポート
  • iOS/Android/HTML5/Windows/Macのビルドサポート
  • 以前のバージョンからの移行は手動で行う必要があり
  • 独自のエディターモード(DOTS mode)を廃止
  • DOTS変換のワークフローを採用
  • 2D、UI、物理演算、アニメーション等の機能はまだ含まれていない(2D、物理演算は2020年にサポート予定)
  • 今後は既存のUnityに依存しないように提供していくことを目標

デモ

Unity公式から公開されているデモ
http://www.tiny.vision/TinyRacing/TinyRacing.html

3Dサポートされたver0.20.0-preview.3を触ってみる

forumにあるドキュメントを参考に導入をしていきます。
https://docs.google.com/document/d/1A8hen2hLFY5FLkC5gd3JP2Z-IpHfnAX-CpYLK3aOdwA/edit#

環境

  • Unity 2019.3.0f3
  • Project Tiny 0.20.0-preview.3

導入方法

Packages/manifest.jsonに以下を定義

"com.unity.dots.runtime": "0.1.0-preview.5",
"com.unity.tiny": "0.20.0-preview.3",
"com.unity.tiny.desktop": "0.20.0-preview.2",
"com.unity.tiny.rendering": "0.20.0-preview.3",
"com.unity.tiny.web": "0.20.0-preview.2",
"com.unity.platforms": "0.1.7-preview.3",
"com.unity.platforms.android": "0.1.7-preview.6",
"com.unity.platforms.desktop": "0.1.7-preview.2",
"com.unity.platforms.ios": "0.1.7-preview.10",
"com.unity.platforms.linux": "0.1.7-preview.3",
"com.unity.platforms.macos": "0.1.7-preview.3",
"com.unity.platforms.web": "0.1.7-preview.6",
"com.unity.platforms.windows": "0.1.7-preview.4",

 

PackageManagerからHybrid Rendererをインストール

DOTSに変換したオブジェクトを描画するために、インストールします。
バージョンは"0.3.0-preview.4"
最新のバージョンではエラーが出て駄目でした。
スクリーンショット 2019-12-18 18.53.33.png

 

Assembly DefinitionにProject Tinyを定義

Assetsを右クリックして、CreateAssembly Definitionを選択
スクリーンショット 2019-12-19 1.02.19.png

名前はProjectNameにしておきます。
スクリーンショット 2019-12-19 1.02.44.png

作成したAssemblyDefitionファイルを選択し、
Auto ReferencedUse GUIDsのチェックを外します。
スクリーンショット 2019-12-19 1.05.03.png

次に、Assembly Definition Referencesに以下のAssemblyファイルの
参照を付け足していきます。

Unity.Entities
Unity.Transforms
Unity.Mathematics
Unity.Tiny.Core
Unity.Tiny.Rendering
Unity.Tiny.EntryPoint
Unity.Tiny.Main

スクリーンショット 2019-12-19 1.15.34.png

追加後、下までスクロールしてApplyを選択します。

Universal Renderning Pipeline(以下URP)の導入

URPをPackageManagerからインストールしておきます。
スクリーンショット 2019-12-19 11.03.46.png

インストール後、URPを作成していきます。
Assetsを選択して、右クリックからCreateRenderingUniversal Render Pipelilne
Pipeline Asset(Forward Renderer)を選択して作成します。
スクリーンショット 2019-12-19 11.14.31.png

作成したURPを設定していきます。
FileBuild SettingsPlayer SettingsGraphicsを選択して、
Scriptable Render Pipeline Settingsに先程作成したものを設定していきます。
スクリーンショット 2019-12-19 11.16.46.png

作成

今回は、Unityで配置された3Dのキューブを回転させることを目標とします。

そのためにこれから以下の作業を行っていきます。

  • シーンを作成し、一部のオブジェクトをSubSceneとして設定
  • SubSceneにCubeを配置
  • 回転するためのComponentDataとComponentSystemを作成

シーンを作成し、一部のオブジェクトをSubSceneとして設定

SubSceneとして設定し、Entity化することで、
Project TinyのECSベースでも表現できるようにしていきます。

SubSceneについては、詳しく説明していただいているこちらをご参考ください、
http://tsubakit1.hateblo.jp/entry/2019/03/07/013558
 
シーンを新たに作成します。
Main.unity
スクリーンショット 2019-12-19 1.41.04.png

Mainシーン内に、オブジェクトをSubSceneに設定するため、
空のオブジェクトをCreate Emptyで作成します。
スクリーンショット 2019-12-19 1.41.32.png

オブジェクトを選択した上で、
右クリックでNew SubScene From Selectionを選択すると、
SubSceneとして作成されます。
スクリーンショット 2019-12-19 1.41.56.png
スクリーンショット 2019-12-19 1.44.58.png

SubScene設定の際にできた、子オブジェクトは削除しておきます。
スクリーンショット 2019-12-19 1.42.08.png
また、ProjectビューのSceneのディレクトリも削除して同じ階層に移動させます。
スクリーンショット 2019-12-19 1.42.46.png

SubSceneにCubeを配置

SubSceneを編集するには、Projectのシーンファイルを開いて、直接編集をするか、
MainシーンからSubScene化したオブジェクトを選択して、
SubSceneComponentからEditモードにすることでも編集が可能です。
今回はEditモードを使用します。
スクリーンショット 2019-12-19 1.44.58.png

Editモードにした状態で、SubSceneのオブジェクト階層に、
MainCameraとDirectionl Lightを複製します。
そして、Createから3DのCubeを追加します。
スクリーンショット 2019-12-19 1.44.43.png

回転するためのComponentDataとComponentSystemを作成

IComponentDataを継承したRotateComponent.cs、
ComponentSystemを継承したRotateSystem.csをそれぞれ作成します。

RotateComponent.cs
using Unity.Entities;

[GenerateAuthoringComponent]
public struct RotateComponent : IComponentData
{
    public float Speed;
}
RotateSystem.cs
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;

public class RotateSystem : ComponentSystem
{
    protected override void OnUpdate()
    {
        var dt = Time.DeltaTime;
        Entities.ForEach((ref Rotation rot, ref RotateComponent rc) => {
            rot.Value = math.mul(rot.Value, quaternion.RotateY(dt * rc.Speed));
        });
    }
}

 
RotateComponentを回転させるCubeに追加します。
スクリーンショット 2019-12-19 2.37.36.png

実行

今までのTinyとは異なり、
Unity Editorから実行することで動作・表示の確認が可能です。

ビルド

ビルドにはBuild Settings for DOTS Runtimeというものを使用していきます。
Assetsを右クリックして、CreateBuildBuild Settings for DOTS Runtimeを選択。
それぞれ設定を追加していきます。

General Settings
Product Name → プロジェクト名を記入
Company Name → 会社名を記入

Scene List
ScenesにSizeを1を指定し、表示するシーンを追加

Dots Runtime Build Profile
Web向けにビルドを行うので、TargetをWeb(Wasm)に選択

右下の+ボタンより追加
(追加)Conversion System Filter Settings
Sizeに1を指定し、Unity.Rendernig.Hybridを指定

(追加)Emscripten Settings
Sizeに1を指定し、TOTAL_MEMORY=64MBを指定

スクリーンショット 2019-12-19 11.22.39.png

Build And RunからWeb用のバイナリが出力されます。
バイナリ出力先:⁨[プロジェクト名]⁩/⁨Builds⁩/DotsRTBuildSettings/
以前のバージョンと同様に表示するにはhtmlファイルをサーバーに配置する必要があります。

デモ

※Webブラウザで動いています
※Gifにしたことで少しカクついていますが、スムーズに動いています。

使用感

  • 専用のモードが廃止されたことにより、今までのUnityのように実装可能になったのは大きな点かと思います
  • ただ以前のバージョンまでと比べても設定する項目が増えたため、より実装が複雑になったと感じます
  • cubeを数個配置したバイナリのサイズは2.9MBでした

おわりに

  • Project Tinyではどのコードモジュールを含めるかを細かく制御できるため、
    ランタイムサイズが小さく、起動までの時間も短縮することが可能です
  • ただ、実装にはDOTSを詳しく理解する必要があるため学習コストは高いです
  • まだプレビュー版のためバージョンが上がるごとに大きな変更や
    一部の機能が廃止されたりしてしまう可能性もあります。 様子をみながら実装を進めていくことをおすすめします
    Unity forumのProject Tinyのスレッドがおすすめです
    https://forum.unity.com/forums/project-tiny.151/

明日は@nisei275さんよろしくおねがいします。

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

[サーバーレス]UnityとFirebaseでアプリのアップデートをせずに、動作と外観の変更を行う

この記事は、鹿児島大学生 Advent Calendar 2019の21日目の記事です。

概要

以前、クライアントからの要件でサーバーを準備せずにアプリ内の表示を変更したいという要望があったので、その時に行なった対応と、UnityとFirebaseの連携を簡単に解説します。

今回はできるだけシンプルな状態で実装まで行おうと思います。
上手く活用すると、アプリの背景画像の変更を行なったり、広告表示の頻度もデータをみながら即時反映することができます。
またFirebaseとの連携でA/Bテストへの応用も簡単に行うことができます。

環境

  • iMac Catalina 10.15.1
  • Unity 2019.3.0f3
  • Firebase for Unity 6.8.1

Catalinaだと訳あってUnity2019.2系が上手く動いてくれないのでまだ正式リリースされていない2019.3系で行います。。。
UIが変わったのは個人的には好きです。

セットアップ

Firebaseは、Googleのプラットフォームでいくつものサービスがありますが
今回はRemote Configを使用していきます。
スクリーンショット 2019-12-18 21.17.27.png

Unityのプロジェクト構築

まずはサンプルプロジェクトを作成していきます。
中身はなんでもいいのですが、今回は2DプロジェクトでFirebaseからデータを取得するボタンと取得した文言を表示するテキストを準備します。
こちらのやり方は、Unity ボタンとかUnity Textなどで調べるとすぐにわかるので今回は割愛します。
スクリーンショット 2019-12-18 21.21.54.png

Firebaseプロジェクトを追加

Firebaseを使用するため、Firebaseコンソールからプロジェクトを追加していきます。
スクリーンショット 2019-12-18 21.26.40.png

手順2でのアナリティクスは有効にすることで他のFirebaseのサービスと連携することができるのですが、
今回はできるだけシンプルに考えられるようにしたいので、Offにします。
実際は有効にして使うことがほとんどです。
スクリーンショット 2019-12-18 21.28.51.png

Unityアイコンから構成ファイルの作成を行なっていきます。
スクリーンショット_2019-12-18_21_30_25.png

Register as iOS appとRegister as Android appにチェックを入れてバンドルIDとパッケージ名を登録していきます。
ここは後から変更ができないので、先にストアの作成からしてバンドルIDとパッケージ名を確定しておいた方がいいかもしれません。
スクリーンショット 2019-12-18 21.44.09.png

構成ファイルがダウンロードできるので、指示通りダウンロードしてUnityのAssets直下にDDで追加します。
構成ファイルはAssets直下であればSDKがよしなに読み取ってくれるので任意のフォルダに整理しても大丈夫です。
スクリーンショット 2019-12-18 21.52.12.png

SDKをダウンロードしインポートします。
スクリーンショット 2019-12-18 21.55.11.png

zipを解凍したらdotnet3dotnet4のフォルダが作成されます。
Unity 5.0以前では、.NET 3.x フレームワークを使用しているため、dotnet3フォルダのpackageを使用します。
Unity 2017.x以降では.NET 4.x フレームワークを使用できるため.NET 4.xを使用する場合はdotnet4フォルダのpackageを使用します。
FirebaseRemoteConfig.unitypackageをダブルクリックで開いているUnityプロジェクトにインポートできます。
スクリーンショット 2019-12-18 22.00.07.png
スクリーンショット 2019-12-18 22.08.05.png

インポートまで完了したらセットアップは完了です。

実装

Android 向け Firebase Unity SDK には Google Play 開発者サービスが必要であり、SDK を使用する前に最新版にしておく必要があります。
アプリケーションの先頭に次のコードを追加します。
SDK で他のメソッドを呼び出す前に Google Play 開発者サービスを確認し、必要であれば、Firebase Unity SDK で必要とされるバージョンに更新するようにします。

初期化

    void Start()
    {
        Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
        {
            var dependencyStatus = task.Result;
            if (dependencyStatus == Firebase.DependencyStatus.Available) {
                // 使用する準備が整った時に通る
            } else {
                Debug.LogError(String.Format("すべてのFirebase依存関係を解決できませんでした: {0}", dependencyStatus));
            }
        });
    }

デフォルトパラメータ値の設定

Remote Config オブジェクトにデフォルトのパラメータ値を設定しておくと、Firebaseから値を取得できない場合にデフォルト値を使用するようにできます。
これにより、オフラインなどの状況でもアプリがクラッシュしないようにできます。

      // リモート設定を初期化し、デフォルト値を設定します。
    void InitializeRemoteConfig() {
        Dictionary<string, object> defaults = new Dictionary<string, object>();
        defaults.Add("remote_string_value", "ローカルの文字です。");
        FirebaseRemoteConfig.SetDefaults(defaults);
    }

パラメータ値の取得

Firebaseからデータをフェッチすることでデータを取得できます。

    //フェッチリクエストを開始します。
    public Task FetchDataAsync() {
      Debug.Log("データを取得しています...");
      System.Threading.Tasks.Task fetchTask = Firebase.RemoteConfig.FirebaseRemoteConfig.FetchAsync(
          TimeSpan.Zero);
      return fetchTask.ContinueWithOnMainThread(FetchComplete);
    }

    void FetchComplete(Task fetchTask) {
      if (fetchTask.IsCanceled) {
          Debug.Log("フェッチはキャンセルされました。");
      } else if (fetchTask.IsFaulted) {
          Debug.Log("フェッチでエラーが発生しました。");
      } else if (fetchTask.IsCompleted) {
          Debug.Log("フェッチが正常に完了しました!");
      }

      var info = Firebase.RemoteConfig.FirebaseRemoteConfig.Info;
      switch (info.LastFetchStatus) {
        case Firebase.RemoteConfig.LastFetchStatus.Success:
          Firebase.RemoteConfig.FirebaseRemoteConfig.ActivateFetched();
          Debug.Log(String.Format("リモートデータがロードされ、準備完了 (最終取得時間{0}",
                                 info.FetchTime));
          break;
        case Firebase.RemoteConfig.LastFetchStatus.Failure:
          switch (info.LastFetchFailureReason) {
            case Firebase.RemoteConfig.FetchFailureReason.Error:
              // 不明な理由でフェッチに失敗しました
              break;
            case Firebase.RemoteConfig.FetchFailureReason.Throttled:
              Debug.Log( info.ThrottledEndTime + "まで取得を抑制");
              break;
          }
          break;
        case Firebase.RemoteConfig.LastFetchStatus.Pending:
          Debug.Log("最新のフェッチ呼び出しはまだ保留中です。");
          break;
      }
    }

パラメータ値を使用するにはGetBalue()関数を使用します。

var value = Firebase.RemoteConfig.FirebaseRemoteConfig.GetValue("remote_string_value").StringValue;

これらを使用して、ボタンを押したらフェッチを行います。
先ほど作成したテキストに状態を表示できるようにしていきます。
Debug.LogをすべてDebugLogに置き換えることで表示を更新できるようにします。

 //デバッグログテキストフィールドとコンソールにテキストを出力します。
    public void DebugLog(string s)
    {
        uiText.text = s;
    }

あとはこれらをUnityに設定していきます。

動作確認

33527-pabho.gif

このままだと、まだデフォルトしか表示されていないので次にFirebase側で更新したいパラメータを設定していきます。
先ほど作成したFirebaseプロジェクトからRemote Configの管理画面を開きます。
スクリーンショット 2019-12-18 22.58.13.png

管理画面から、簡単にパラメータの追加が行えるので
先ほどプログラムで引数に与えたremote_string_valueのキーで設定していきます。
追加できたら右上の変更を公開を押して動作確認してみてください。
スクリーンショット 2019-12-18 22.59.37.png

さいごに

とても簡単にサーバーレスで即時にアプリの変更をすることができましたね。

ストアの規約上、なんでも変更していいというわけではないですが
A/Bテストなどではとても力を発揮すると思いますので是非使ってみてください。

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

Unity でOVRLipsync を使い作った BlendShape のアニメーションをクリップに変換する方法

要約

UnityでOVRLipsyncを使い作ったBlendShapeのアニメーションをアニメーションクリップに変換するには、GameObjectRecorderクラスを使えばできます。
Unity - Scripting API: GameObjectRecorder

はじめに

Unityでアニメーション作ろうと思った際に、口パク面倒だなーと思っていたら、OVRLipsyncという神ツールを見つけました。ですが、ほとんどインタラクティブに使う用途ばっかりで、そのアニメーションをアセットにしたくても方法が見つからない...と、そこに現れた救世主!
Unityユーザー助け合い所
質問したらソッコーで回答をくれました。本当にありがとうございます!

方法

Unityちゃんを使います。
キャプ01.PNG

OVRLipsyncをunityに入れて音声データに合わせてBlendShapeの値が動く(口パクする)ように設定します。ここまでは他の記事を参考にしてみてください。

Unity - Scripting API: GameObjectRecorder
のページを参考にして下記のようにしたスクリプトを作ります。

using UnityEngine;
using UnityEditor.Animations;

public class RecordTransformHierarchy : MonoBehaviour {
    public AnimationClip clip;

    private GameObjectRecorder m_Recorder;

    void Start()
    {
        // Create recorder and record the script GameObject.
        m_Recorder = new GameObjectRecorder(gameObject);

        // Bind all the Transforms on the GameObject and all its children.
        m_Recorder.BindComponentsOfType<SkinnedMeshRenderer>(gameObject, false);
    }

    void LateUpdate()
    {
        if (clip == null)
            return;

        // Take a snapshot and record all the bindings values for this frame.
        m_Recorder.TakeSnapshot(Time.deltaTime);
    }

    void OnDisable()
    {
        if (clip == null)
            return;

        if (m_Recorder.isRecording)
        {
            // Save the recorded session to the clip.
            m_Recorder.SaveToClip(clip);
        }
    }
}

これをunityちゃんの表情のblendshapeがあるMTH_DEFに割り当てます。
また、空のクリップを作り、スクリプトのclipの欄に割り当てます。
キャプ02.PNG

次に、UnityちゃんにデフォルトでついているAnimator, Idle Changer, Face Updata, Auto Blinkのチェックを外してUnableにします。
キャプ05.PNG

この後、Playを押してStopすると、割り当てられたクリップにキーフレームがうたれます。この時、Pauseを押してからPlayを押して、Pauseを外して再生したほうがうまくいくと思います。下の図は失敗例。
キャプ03.PNG

しかし、アニメーションのキーフレームが打たれているところのプロパティが黄色くなって、このままでは使えません。
ので、新しいクリップを作り、手動でプロパティを追加して、先のクリップから対応するプロパティにキーフレームをコピペします。日本語の場合は、_A,_I,_U,_E,_Oのプロパティのキーフレームを移せばいいと思います。(先の画像と今回の画像で使っているアニメーションが違うのでキーフレームが対応していないです。)
キャプ04.PNG

その後、Animatorなどに今度はチェックをいれてableにして、音声と共に再生してみると口パクしているのがわかります。もし音声と口パクがずれていたら、Timelineなどを使い調節すると便利です。
キャプ06.PNG

まとめ

面倒な部分を簡略化できると思いますが、現時点で私が口パクを作る頻度が高くないので更新はしないと思います。
もし、もっといい方法を思いついた方がいたら記事作ってください。私のためにもお願いします!(めんどくさがり)

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

【Unity】Navigationを使って経路探索させる

概要

今回は以下のようなシンプルなプロジェクトを作り、Navigationの超基本的な使い方を学びます。

今回のプロジェクトでは、Unityちゃんがプレイヤー、赤いCubeが目的地になっています。

Qiita4.gif

【この記事の対象】 初中級程度の方

Navigationとは?

UnityにはNavigatonという機能が搭載されています。

Navigationとはシーンのジオメトリから生成されるナビゲーションメッシュを使用して、ゲームの世界を知的に歩くことのできる機能です。
(Unity公式リファレンスより:ナビゲーションと経路探索

今回はNavMeshAgentというコンポーネントを使ってNavigationを使っていきたいと思います。

1.GameObjectを配置

まずは任意の場所にプレイヤー、目的地、障害物、地面を配置します。

スクリーンショット 2019-12-14 11.54.43.png

今回はそれぞれのGameObjectに

種類      名前
プレイヤー(Unityちゃん) Player
目的地(Red) Destination
障害物(Green) Obstacle
地面(White) Ground

という名前をつけました!

2.NavMeshAgentをつける

次に今回の記事の要であるComponentのNavMeshAgentをつけていきます。

NavMeshAgentは経路探索をして、動いて欲しいObjectにアタッチします。
今回のプロジェクトではPlayerにアタッチします。

スクリーンショット 2019-12-14 10.51.22.png

3.Playerのスクリプトを書く

次にPlayerのスクリプトを書いていきます。

PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class PlayerController : MonoBehaviour
{
    NavMeshAgent Player_Nav;
    GameObject Destination;

    void Start()
    {
        //プレイヤーのNavMeshAgentを取得
        Player_Nav = GetComponent<NavMeshAgent>();
        //目的地のオブジェクトを取得
        Destination = GameObject.Find("Destination");
    }

    void Update()
    {
        //目的地を設定
        Player_Nav.SetDestination(Destination.transform.position);
    }
}

ポイントは

   1.名前空間using UnityEngine.AIを記入しているか
   2.PlayerのNavMeshAgentをきちんと取得できているか
   3.SetDestinationをきちんと書いている(目的地の指定ができている)

の3点です!!

4.NavigationWindowを開く

次にPlayerが行動できる範囲を指定するために、NavigationWindowを開きます。
navigationwindow.gif

5.移動範囲をBakeする

それではPlayerの移動範囲を指定していきましょう。

Ground、Obstacleを選択し、Inspectorビュー内のStaticの横にある三角をクリックし、Navigation Staticを選択します。

About Static.gif

次に歩かせる範囲と歩かせない範囲を指定します。

範囲の指定にはNavigationWindowのObjectのNavigation Areaの部分をいじっていきます。

Navigation Area 機能
Walkable 選択したエリアが歩けるようになる
Not Walkable 選択したエリアが歩けないようになる
Jump auto-generated、Off-Mesh Links の際に利用する(今回は使用しません)

スクリーンショット 2019-12-14 12.12.09.png

今回のプロジェクトにおいて歩かせる範囲はGround、歩かせない範囲はObstacleにあたるので、
GroundをWalkableに、ObstacleをNot Walkableに設定します。

以上の設定が完了したら、NavigationビューBakeの右下にあるBakeをクリックして移動範囲の指定を完了させます。

Bake3.gif

上の画像のように、移動範囲が青く表示されたら完了です!!!

6.動かしてみる

以上の設定が終わったらプレビューボタンを押してみましょう。

Preview.gif

PlayerのUnityちゃんが自動で経路探索し、指定範囲の上を歩きましたね!!
これでNavigation機能を使うことができました!!

最後に

いかがだったでしょうか?

Navigation機能はこんなに簡単に実装できてしまうんです。

次回の記事ではNavigation機能を使用して、動く障害物を避ける方法をご紹介したいと思います。

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

VTuberオタク大学生がKinect v2で美少女アバターを動かすために1年間やったこと

この記事は、VTuber Tech #1 Advent Calendar 2019の20日目の記事です。

昨日は @ iwaken71 による記事でした!

はじめに

どうも、にー兄さんと申します。VTuberTechアドカレということで記事を執筆させていただきます。
自分は普段xRやHumanoidアバター制御、CGなどの領域で個人開発をしている大学2年生でして、メインで進めているプロジェクトとして汎用モーキャプシステムの開発を(のびのびと)やっています。このプロジェクト自体は、もともと4月から始めていた「ARアバター配信システム」の機能の一部として開発していたものです。下のツイートが進捗っぽいものになります。

見て頂ければわかると思うのですが、 モーションキャプチャがお粗末すぎる んですよねぇ。どうにかしたいと思い試行錯誤している間に、モーキャプシステム開発にのめりこんでしまい、今に至ります。今回は、そんな感じで自分が試行錯誤した結果や実装した機能などを紹介したいと思います。
最後までお付き合いいただけたら光栄です。

美少女受肉を実現するには

概要

使用したデバイス・開発環境

Kinectについて

Unityでアバター制御をする

アバターを自然に動かすために

補間、補正をする意味

FKとIK

体形を合わせる~キャリブレーション~

データの平滑化

システムを設計する

保守しやすい設計を目指して

MV(R)Pパターンの導入と債務の分離

VTuberオタクはバーチャル美少女受肉の夢を見るのか?

個人的な夢

バーチャル時代の最高のユーザ体験を作るために

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

TBD

スミマセン、自動更新の設定を変えずに間違って下書きを公開してしまいました...
内容につきましては、もうしばらくお待ちください
失礼いたしました。

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

コードを生成するコードを作ると人生が楽になる 【Unity】

シーン・サウンド・エフェクト等が追加された事で変数も新しく追加で用意する必要が出てきて
何回も決まりきった流れのコードを追記していく経験はありませんか

これはコードの自動生成で対策することが出来ます。

なにか難しそうに感じると思うのですが、とても単純でコード文を書いてファイル出力するだけで作れます

作り方

   private static string ASSETS_PATH = Application.dataPath + "/";
   private static string SOURCE_TEMPLATE =
    @"public class #SCRIPTNAME#
    {
    }";

    /// <summary>
    /// ソース出力
    /// </summary>
    /// <param name="fileName"></param>
    private static void CreateSource(string fileName)
    {
        // インポート開始
        AssetDatabase.StartAssetEditing();

        StreamWriter cs = new StreamWriter(ASSETS_PATH + fileName + ".cs", false, Encoding.UTF8);

        // 書き出すコードを組み立てる
        StringBuilder stringBuilder = new StringBuilder(SOURCE_TEMPLATE);

        // ※ここで用途に合わせ追記

        // ファイルにコードを書き込む
        cs.Write(stringBuilder);

        // ファイルを閉じる
        cs.Close();

        // インポート終了
        AssetDatabase.StopAssetEditing();

        // アセットインポートする
        AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
    }

次回はこの仕組みを使って何か便利な仕組みを紹介できればと考えています。

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

ARCore入門チュートリアル(Unity)

こんにちはJUNOと申します。

最近本屋でAR開発に関する本を探していますがまだ数は少ないようです。

そこで今回、AR初心者向けに
AR開発環境(Unity)の導入方法とAndroidにおけるチュートリアルアプリを紹介します。

参考元:Google公式ドキュメント

私の環境

・Unity
・エディタ
  VisualStudio2019(今回のチュートリアルでは使用しません)
・開発PC
  MacBookPro(恐らくWindowsでも同じように動作する)
・Android端末
  HUAWEI P20 LITE(Android v9)

要件

ハードウェア

ARCore対応端末を確認してください。
・デバイスと開発PCがUSBケーブルで接続できるもの

ソフトウェア

それぞれ後ほどダウンロードしていきます。
・Unity 2017.4.34f1 以降のバージョン
・Android SDK 7.0 (API Level 24) 以降のバージョン
・ARCore SDK for Unity 1.13.0 以降のバージョン

【参考】
AndroidSDKを導入するため、以前はAndroidStudio(以下AS)をインストールする必要がありましたが、今はUnityHubでインストールできるのでASはなくても大丈夫かと思われます。
(検証していないため、UnityHubでAndroidSDKが導入できない場合はASを導入してください。)

Unity導入

Unity及びAndroidSDKを導入していない方は以下の手順で導入してください。
今回はUnity Hubを用いてUnityを導入してみます。

Unity HubというのはUnity本体ではなく、Unityのバージョンを管理してくれるツールです。
これでUnityの各種バージョンを導入でき、同時に各種モジュール(AndroidSDKなど)のインストールも行えます。

Unity Hubはこちらからダウンロードしてください。

スクリーンショット 2019-12-18 1.44.55.png

DLしたら開いて、Unityをインストールします。
Unity2019で良いでしょう。

スクリーンショット 2019-12-18 1.40.20.png

追加するモジュールにAndroidBuildSupportにチェックを入れてください。
ここがチェックされていればAndroidSDKも導入できます。
他のモジュールはチェックをいれなくても良いです。

スクリーンショット 2019-12-18 1.40.30.png

この状態でインストールしてください。
これでUnityの導入は完了です。

ARCoreSDKのダウンロード

こちらからダウンロードしてください。
スクリーンショット 2019-12-18 22.41.41.png

プロジェクトの作成

ここからは実際にプロジェクトを作成し、サンプルアプリをAndroid端末に導入していきます。

①新規作成

「プロジェクト」の「新規作成」を押します。
テンプレートは「3D」で、プロジェクト名に適当な名前を入力して「作成」を押してください。
スクリーンショット 2019-12-18 22.35.00.png

これでプロジェクトが作成されます。

スクリーンショット 2019-12-18 22.49.09.png

②Unity2019の場合パッケージをインストールする。

メニューバーからWindow > Package Managerを開く。
スクリーンショット 2019-12-18 22.56.11.png
開いたら、この中から下記2つのパッケージをインストールする。
Multiplayer HLAPI
XR Legacy Input Helpers
スクリーンショット 2019-12-18 23.05.03.png

インストールが完了したらPackageManagerを閉じる。

③ARCoreSDKのインポート

メニューバーからAssets > Import Package > Custom Packageで先ほどDLしたARCoreSDKパッケージ(arcore-unity-sdk-1.14.unitypackage)を選択する。

スクリーンショット 2019-12-18 23.13.07.png

Import Unity Packageが表示されたら「Import」を押す。
スクリーンショット 2019-12-18 23.13.23.png

これでARCoreSDKのインストールが完了しました。

④シーンを開く

Assets/GoogleARCore/Eamples/HelloAR/Scenes/HelloARを開く。
Hiearchy内のHelloAR Controllerをクリックする。
Inspectorでオブジェクトの設定などができる。「ARCorePawn」というのが設置するオブジェクトで右側の点を押して変更もできる。
スクリーンショット 2019-12-18 23.22.37.png

⑤ビルドセッティング

メニューバーからFile>Build Settingsを開く。
Platformは「Android」を選択し、SwitchPlatformをクリック。
PlayerSettingsを押し、設定画面を開き、以下の設定を行う。

OtherSettingsを開き、
・GraphicsAPIs中で「Vulkan」を選択し-で削除する。
・PackageNameをユニークな名前に設定する(初期値でもOK!)
(ex:com.DefaultCompany.ARCoreApp)
・Minimum API LevelをAndroid7.0'Nougat'より高いものに設定する
XR Settingsを開き、
・ARCoreSupportedにチェックを入れる。

スクリーンショット 2019-12-19 0.13.20.png

スクリーンショット 2019-12-19 0.39.30.png
スクリーンショット 2019-12-19 0.39.36.png

ここまで設定できたら設定画面を閉じる。

⑥Build&RUN

Android端末とPCをUSBケーブルで接続する。
この時、Androidはデバックモードを設定し、かつファイル送信可能にしておく。
スクリーンショット 2019-12-19 1.05.25.png
Build And Runをクリックする。
端末でアプリが起動する。

Screenshot_20191219_012331_com.DefaultCompany.ARCore.jpg

平面を認識して、その平面上でタップするとオブジェクトが出現する。

終わりに

今回はUnityを導入してARCoreのチュートリアルを体験しました。
環境を作って設定するだけでARを体験できるのはすごいですね。
機会があれば次なるステップの記事をあげられたらいいなと思います。

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

Shaderお絵かきを初めて行うためのアプローチ

この記事は、UnityAdventCalender2019その2の19日目の記事です。

まだ記述途中です。22日中には記述終える予定です。

対象読者

  • シェーダーお絵かきをしたい人
  • シェーダーお絵かきしたいが、アプローチをとれば良いかわからない。
  • どこから初めて良いかわからない人
  • 板ポリに対して、色んな絵を記述できる(かも?)
  • シェーダーで何か作りたいけどどういう風のつくり方をしていいかわからない

この記事で得られる知見

  • シェーダーお絵かきのアプローチがわかるかも?

前提知識

  • テクスチャのUV座標とかがわかる

今回しないこと

  • がっつりなシェーダー内容(絵作り的な意味合いのもの)

今回の環境 

Unity2019.3.0f
ShaderGraph 7.1.6
LightWeightRP 7.1.6

本当はUnity2018の環境で行う予定でしたが以下の理由により、ShaderGraphが開くことができない状態の模様なので、Unity2019に移行しました。

Unity2019で行った事情

UnityのVer2018.4.9fにてShaderGraphの4.0以上を使った場合は、そもそもShaderGraphを使用できずにそもそも立ち上げることなく以下のエラーを吐き出す場合があります。
上記IUnityVerと4.0もしくは4.10を行なった際には、少なくとも、私の環境では発生しました。

同じくUnityForm上で、以下のやりとりが行われているので、起きる場合は往々にありそうです。
https://forum.unity.com/threads/shader-graph-crashes-when-opening-graph.661312/

解答としては、Unityの2019のverにあげて、そのタイミングのLightWeightRenderPipline(UniversalRenderPipeLine)にて行うことができたので、そちらに移行

目次

  • ShaderGraphの使うまでの前準備
  • アプローチの仕方の基本
  • シンプルな表現
  • 例題に対しての分解のアプローチ
  • 実際に何か作ってみよう

ShaderGraphの使うまでの前準備

メニューバーにある Window/PackageManagerでPackageManagerを開きます
image.png

ShaderGraph と UniversalRPをinstallします。

ShaderGraphを使用する上でPipeLineAssetを設定する必要があるので
Project画面の上で、右クリック/Create/Rendering/UniversalRenderPipeLine/PipeLineAssetを選び作成します。
image.png

作成すると以下のファイルが作成されます。
UniversalRenderPipelineAsset.asset
UniversalRenderPipelineAsset_Renderer.asset

この2つのうちのUniversalRenderPipelineAsset.assetを
メニューバーのEdit/ProjectSettingで開かれる以下の画面からGraphicsという項目を選択し、赤枠部分に、ドラッグ&ドロップを行います

image.png

次にProject画面部分で、右クリック Create/Shader/UnlitGraphで.ShaderGraphファイルをダブルクリック
これで準備は完了

アプローチの仕方の基本

Shaderお絵かきを行うに当たって、「要素の分解」というのが重要です。
例えば、以下のような場合(縦に縞模様が動きながら、点滅するようなシェーダー)のものだと

今回作るものはこちら
ShaderGraph.gif

縞模様が動きながら点滅を行えるようになるものです。

要素としては
- 点滅
- 移動する縞模様
- 縦に一定間隔で表示(縞模様)
- 移動する
-αを適用する

といった感じの要素に分解されます。
これらの要素の組み合わせを行う事で、作りたいものに対して、どのようなアプローチをすれば良いかがわかります。

それでは、それぞれの最小の部分では、どういった要素によって組み合わせられているでしょうか?

点滅

ノードとしては以下の組み合わせになります。
Time + Sin (+ Absolute)

Timeノードは、時間と共に数値が変化するためのものです。
Wが一番値が大きく変化し、XYZという順番に遅くなっていきます。(TODO:要検証)
TODO:図も軽く存在した方が良い

Sinノードは、与えられた値を、Sinの式に対して当てはめます。
0−2の間に対して、−1〜1の値が出力として返却されるので、以下のようなものが出力として存在します。

上記の二つのノードを組み合わせることで
Timeの値をSinに与えて、Sinで出力したものを色として扱って出力を行う事で、点滅ができます。

何故点滅が行われるかというと
Sinノードから出力される値は、あくまでも−1 〜 1の値が出力されます。
これを色情報(X,Y,Z,W(アルファ))に対して、Sinノードからの出力を設定しているためおきます。
プログラム的には、

float c = sin(Time.deltaTime);
Vector4(c,c,c,c);

みたいなイメージでしょうか?

ただし、あくまでも白くひかるタイミングというのは、0を超えたタイミングとなるため
Sinから出力される値が、負の値の場合は黒くなっているため、比較的に長く暗くなっているように見えてしまいます。

TODO:ここに、負の部分は見えない図を表示する。

そこで、Absoluteノードが役に立ちます。

Absoluteは入力された値の絶対値を出力するためのものです。
絶対値というのは、大雑把にいうと、マイナスでも マイナスの値をとった数値のみを取り出すというものです。
厳密には、少し違うので、きになる場合は、調べてください。

このAbsoluteを使用する事で、先ほど、の負の値の部分が、正の値になるので、
以下のような感じになります。

TODO:変化したSinの値を変化させる。

縞模様

縞模様を作る時には、どういうアプローチがあるでしょうか?

縞模様を作成する場合は入力に工夫が必要です。
理由としては、単純に、最終的な出力に大きく関わるもののためです。
この縞模様は、最終的に出力を行なった際に、この模様をそのものを使用するためです。
「その場所の際に、この色を塗る」という状態にしなければいけません。
その場所の際にというものは、情報のあり方は色々とあります。
・光が当たらない状態の場所
・UV座標のこの位置
・(Local World)Positionのこの位置

などの、その場所を特定する何かで、色を塗らなければいけません

移動する

今回でいうならば、入力自体の値を変化するという必要があります。
つまるところ「変化し続ける何か」が必要になります。
今回は、Time部分を使用することにします。

これを Moduloに与える前に足しこむことで、
以下のような図になります。

TODO:実際の図形、原理の図形

これによって、縞模様が出力される場所がずれ込むことになるので、それによって、縞模様が移動しているように見えることになります。

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

一日で俺の嫁を作る方法 ~一日で自分の好きな声・キャラ・見た目でおしゃべりしてくれるAIキャラクターを作ろう~

はじめに

いくつかのAPIを組み合わせることで、一日で自分の好きな声・キャラ・見た目でおしゃべりできるAIキャラクターを作りました。この記事を読めば同じ感じで誰でも一日で俺の嫁を作ることができるようになります。
また今回はVR環境版とスマートフォン環境版の二種類を作成しました。
これらのアプリとUnity Projectは以下のgithubで公開しています。
軽く試してみたい人は作り方の6に従って、AgentCraftでAIの会話例を作成して、それをSebastienでデバイスIDとして発行すれば試すことができます。詳しくは6および6に載せている資料をご覧ください。
https://github.com/gyokuro33/ai-agent

何を作ったか

こんなのです。

スマートフォン版

VR版

使用したもの

NTTドコモのAgentcraft : AIエージェント作成ツール
NTTドコモのSEBASTIEN : AIエージェント基盤
SEBASTIENと音声対話するためのUnity向けSDK
Oculus社のOculus RiftS もしくはOculus LinkでOculus Riftsと同様に操作可能にしたOculus Quest
Oculus社のOVRLipsync : 3Dモデルに音声に合わせた口パクを行わせるツール
Unity Technolosies Japanのunity chan! © UTJ/UCL : 3Dモデル。可愛いくて様々なポーズや表情が揃っている。違うキャラが作りたい人は自分の好きなキャラの3Dモデル
Unity(2018.4.13f1) : ゲーム開発エンジン
適当なAndroidのスマートフォン

参考にした記事

ドコモAIエージェントAPI
【UnityC#講座】ユニティちゃんの表情を替える【SetLayerWeight】
キャラクターを喋らせる!OVR Lip Syncの導入から問題発生時の解決法まで
Unityで作る!ドコモAIエージェントAPIを使った音声対話アプリ作成ハンズオン

構成図

アプリの仕組みは以下のようになっています。
基本アプリ側で行うのはグラフィックの描画と音声のInput,Outputのみで、それ以外の音声認識や音声合成、会話作成などは連携するAPI先で処理しています。

image.png

作り方

以下の手順に従っていけば、AIキャラクターを表示させておしゃべりを楽しむことができるようになります。

1. 使用したものの欄にあるものをすべてダウンロード

バージョン指定されているものはそのバーションのものを。バーション指定されていないものは最新のものをダウンロード。

2. Unityに空のプロジェクトを作成する

3. ダウンロードした以下の三つのファイルを作成したプロジェクトにインポートする

  1. SEBASTIENと音声対話するためのUnity向けSDK
  2. OVRLipsync
  3. Unity Chan

インポートの方法は以下の記事を参考にしてください。
パッケージのインポート

4. Asset/Sebastien/Scenes/mainのシーンを開く

image.png

5. 以下の記事を参考に、Unitychanが音声を再生することで口パクしてくれるようにする

キャラクターを喋らせる!OVR Lip Syncの導入から問題発生時の解決法まで
ただし最新のOVRLipsyncを使う場合ならVisemeToBlendTargetsの設定は記事とは異なり、以下のように設定する必要があります。
またUnity chan以外をしゃべらせたい場合は違う3Dキャラクターを同様の手順で設定して、口パクできるようにしてください。
image.png

6. 以下のハンズオン資料に従って、エージェントとの対話までできるようにする

Unityで作る!ドコモAIエージェントAPIを使った音声対話アプリ作成ハンズオン
対話内容はお好みで。この段階で、キャラがしゃべる声や会話内容などを作成します。
Agentcraftの詳しい使い方や作り方はここに載っています。
簡単に説明すると、会話については以下のように発話例とそれへの応答を決めることで、会話への対応パターンを作ることができます。
またキャラクターの声は以下のように、50以上の声から選ぶことができます。声のサンプルはここで聞くことができます。
さらにこれらの声は声質や話速、抑揚、声の高さなど様々なパラメーターをチューニングすることで、自分だけの声を作ることも可能です。
また以下の動画のように、会話中に声を変更することも可能です。
image.png
image.png

7. SpeakToLipsyncというC#スクリプトを書き、手順5で作成したLipSyncSoundに追加する

コードの内容は以下のもの。
書いている内容としては、Sebastienが合成した音声をOVRLipSyncで再生させることで、言った内容と同じことを口パクしてくれるようにする、というもの。

SpeakToLipsync.css
using System;
using UnityEngine;
using System.Diagnostics;
using Debug = UnityEngine.Debug;
using System.Threading;

public class SpeakToLipsync : MonoBehaviour

{
    public AudioSource currentAudioSource = null;
    public AudioSource speakAudioSource = null;
    public GameObject speakOb;

    private AudioClip beforeAudioClip;

    void Awake()
    {
        speakAudioSource = speakOb.GetComponent<AudioSource>();
        if (!currentAudioSource) currentAudioSource = GetComponent<AudioSource>();
        if (!currentAudioSource) return; 

    }
    // Start is called before the first frame update
    void Start()
    {
        currentAudioSource.mute = false;
        beforeAudioClip = speakAudioSource.clip;

    }

    // Update is called once per frame
    void Update()
    {

        if (beforeAudioClip != speakAudioSource.clip)
        {
            currentAudioSource.clip = speakAudioSource.clip;
            currentAudioSource.Play();
        }
        beforeAudioClip = speakAudioSource.clip;


    }

}

8. SpeakToLipsync.cssのSpeakObにHierarchyにあるSpeakを入れる

image.png

9. HierarchyにあるCanvasのGameObjectを非アクティブにする

10. Asset/Sebastien/Example内にあるExample.cssを以下のように変更する

関数Startの一番最後、speak.start();の次に以下の二行を入れてください。

speak.cancelPlay();//音声再生をキャンセルする
speak.unmute();

また関数onPlayEndに以下の一行を入れてください。

speak.unmute();

こうすることで、AIキャラクターが常に音声を聞いて反応してくれるようになります。

11. (VR版を試したい場合は)Player SettingのXR SettingからVirtual Reality Supportedにチェックを入れて、VRに対応できるようにする。

12. (android版を試したい場合は)使用プラットフォームをAndroidに変える

13. 各デバイスをPCにつなぐ

14. アプリをBuild&Runする

応用例

以上に書いた作り方は基本です。
これを基にさらに工夫を加えることで、より人間のような応答をAIキャラクターがしてくれるようになります。

1. AIキャラクターの応答に表情を加える

DocomoのAgentcraftには言葉以外のメタ情報を応答の際に送るという機能が存在します。
その機能を使って、AIキャラクターが応答する際に以下のような感情の情報も一緒に送り込み、その感情に応じた表情をさせることで、AIキャラクターが表情豊かに話してくれます。
表情の変え方は以下の記事を参考にすれば簡単に変えることができます。
詳しい作り方は、いいねが50超えたら書きます……(力尽きた感)
【UnityC#講座】ユニティちゃんの表情を替える【SetLayerWeight】
image.png

2. AIキャラクターが会話を記憶して、その情報を基に話すようにする

DocomoのAgentcraftには会話中で発された言葉を記憶して、会話を作成する機能があります。
例えば「私のことを覚えていますか?」 という質問に対して、その人と話したことがあるかで、以下のように分岐を作ることができます。
image.png

この機能を活用すると、以下のように、自分の好みなどのパーソナライズな情報を汲んでくれる、まさしく俺の嫁を作ることができます!

image.png

3. AIキャラクターを攻略できるようにする

応用2のさらなる応用です。
このAIキャラクターには情報を記憶させることが可能です。
そして会話にはその記憶から分岐を作ることが可能です。
そしてこの記憶は会話内以外にもあらかじめ設定することが可能です。
つまり、AIキャラクターと会話して、AIキャラクターの好みに合った返答を行えば好感度が上昇or下降するようにする。そうした会話を多数作れば、会話するにしたがってどんどん好感度が上昇(もしくは下降)していく、攻略可能な俺の嫁が誕生します!
ただ一つ問題点があり、自分で作るとそこらへんの好みや会話をすべて知っている状態で会話をすることになり、非常に虚しいことです……
この記事を読んだ誰かに作ってほしい……

まとめ

以上のように作っていくことで、自分の好きな声・キャラでおしゃべりしてくれるVRアシスタントを作ることができるようになります。
ぜひみんなで自分だけのキャラクターを作って、楽しんでください。
またこのアプリはSEBASTIENのデバイスIDを使用することで作成したキャラクターのAIの振る舞いを試すことができます。
つまり、他の人が育成したキャラクターとおしゃべりすることもできるんです!
この記事を読んでくれた方は、ぜひ自分だけのキャラクターを作り、それを公開することで色んなキャラクターを生み出してほしいです!

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