ゴイサギ日記

東京でエンジニアとして頑張って何とか生きてます。。ゆる~く更新していきます

【Unity】Projectビューのお気に入り情報を抜き出してみる

前回に引き続き今回もProjectビューです。お気に入り情報を抜き出してファイルにエクスポート/インポートするエディタ拡張を作ってみました。

別PCのUnityエディタに自分のお気に入り情報をインポートしたい時くらいにしか使えない気がしますが内部処理を把握するのに良い勉強になりました ^^;

github.com

Unityのソースコードが公開されているのでそちらを参考にしました。調べたところSavedSearchFilter がお気に入り情報を管理してたのですが internal class だったのでリフレクションを使って参照しています・・ ^^; tsubakit1.hateblo.jp

【Unity】Projectビューについて

f:id:aki517:20180924135509p:plain

Unityエディタで開発をする上で大変お世話になるProjectビュー(Projectウインドウ?Projectブラウザ?) 色々と便利な機能があるのに私自身も知らない機能があったのでメモがてら書いていきます。

ショートカット
Windows Mac 操作
Ctrl + D Cmd + D 選択中のアセットを複製
Delete なし 選択中のアセットを削除(ダイアログ確認あり)
Delete + Shift Delete + Cmd 選択中アセットを削除(ダイアログ確認なし)
F2 Enter 選択中のアセットの名前を変更
F F フォルダ内の選択したアセットを表示
Tab Tab 左側カラム(フォルダ一覧とFavorites)と右側カラムを

自分が良く使うものだけ抜粋しました。

フィルタ機能
タイプ (t:)

Search by Type ボタンからアセットのタイプでフィルタリングします。 f:id:aki517:20180924133612g:plain

ラベル (l:)

Search by Label ボタンに設定されているラベルでフィルタリングします。 f:id:aki517:20180924133621g:plain

ちなみ以下のように任意のラベルを作成する事もできます。 f:id:aki517:20180924133630g:plain

アセットバンドル名 (b:)

その名の通りアセットバンドル名でフィルタリングします。 f:id:aki517:20180924134738g:plain

参照 (ref:)

これはほぼ使う機会がないのですが、パス or InstanceID 指定で参照するオブジェクトを検索します。Assets以下のアセット数が多くなると検索に物凄い時間がかかります。下手するとUnityエディタ固まります・・

例えば Assets/Scripts/Player.cs (InstanceID:12345)を参照するオブジェクトを検索する場合は「ref:Scripts/Player.cs」(Assets/を除く) または「ref:12345:」と入力します。
f:id:aki517:20180924133645g:plain

Scene内とかも検索する場合はこのスクリプト使ったほうが良いですね ^^;

qiita.com

ちなみに InstanceID は Object.GetInstanceID() で取得するか、下図のように Inspector > Debug に切り替えると確認できます。
f:id:aki517:20180924133605g:plain

お気に入り機能

検索結果に好きな名前を付けて左側カラムのFavoritesに保存できます。検索ファイル名 + フィルタといった複数条件も保存出来るので便利です。Unityエディタ単位での設定しか出来ず、プロジェクト単位での設定が出来ないのが懸念点ですが・・・

f:id:aki517:20180924121847g:plain

参考

プロジェクトウィンドウ - Unity マニュアル

【Linux】コマンドメモ

いまの業務でコマンド叩く事が多くなってきたので備忘録的なやつを残しておく、CUI上で全ての操作を行うサーバーエンジニアさん本当凄いです。。 ^ ^;)

cat
#ファイルの先頭10行を出力
cat memo.txt | head -10
#ファイルの末尾10行を出力
cat memo.txt | tail -10
find
# ホームディレクトリ以下のhtmlファイルを検索
find ~/ "*.html"
xargs
# 指定コマンドと初期引数に標準入力から読んだ引数を着けてコマンドライン生成して実行
# tempディレクトリ内のtxtファイルの先頭10行を表示
ls temp/*.txt | xargs head
grep
# test.txt内の"target"を検索
grep target test.txt
# ホームディレクトリ以下のtxtファイル内の'target'を検索
find ~/ *.txt | grep target

# input.txtファイル内の任意文字列がある行から2行後を表示
grep -A 2 -n "hogehoge" input.txt
# 2行前なら -B
grep -B 2 -n "hogehoge" input.txt
# 前後2行なら -C
grep -C 2 -n "hogehoge" input.txt
tail
# エラーログのリアルタイム監視
tail -f error.log
scp

リモートマシン間でファイルをコピーする

#ローカルで作成した公開鍵を www.example.co.jp に hogeユーザーでログインしてコピー (XXXXはipアドレス)
scp ~/.ssh/id_rsa.pub hoge@www.example.co.jp:/home/hoge/.ssh
du
# hogeディレクトリ以下のファイル容量表示
du /hoge
# ディレクトリだけでなくファイル容量も表示
du -a /hoge
# 単位付き表示
du -h /hoge
# 取得内容をソートして上位10件のみ表示
du -m -h | sort -rn | head -10
sed
# ファイル内の「goisagi」を「kosagi」に置換
sed -i -e "s/goisagi/kosagi/g"
pushd, popd

カレントディレクトリを変更する

pushd /var/log  #カレントディレクトリを /var/log に変更
  #何かの処理 
popd #pushd実行前のカレントディクトリに戻す
環境変数を設定(zsh版)
# vim で ~/.zshrc を開き、任意のパスを追加  
vim ~/.zshrc  
# source で適用
source ~/.zshrc

【Houdini】Game Development Toolset と Impostor Texture

久しぶりの Houdini です。普通にチュートリアル進めようと思ったのですが Side Effect Software 提供の Game Development Toolset というものがありゲーム用アセットの作成に便利な機能が色々と揃っているので今回はこれを試してみます!!

インストール

1.こちらGitHubから Clone または zipダウンロードして任意のディレクトリに解凍しておきます。私は C:\HoudiniTools 以下に配置しました。

2.次に houdini.env を開き、以下の様に環境パスを通します。

HOUDINI_PATH = {C:\HoudiniTools\GameDevelopmentToolset};&

houdini.envは各OSに応じて以下の場所にあります。

OS 場所
Windows C:\Users[username]\Documents\houdini[ver#]
OSX(Mac) /Users/[username]/Library/Preferences/houdini/[ver#]
Linux ~/houdini[ver#]

※[ver#]はインストールしたHoudiniバージョン番号

3.Houdiniを起動 シェルフの「+」> Shelves > Game Development Toolset を選択する事が出来ればインストールは完了です。
f:id:aki517:20180429193410p:plain

Impostor Texture

インストールが完了したので Impostor Texture という機能を使ってみます。カメラの視点によって参照するUVを切り替えることによって3Dオブジェクトのように見えるテクスチャを出力するものです。今回は Houdiniでテクスチャを出力 > Unityで描画までやってみます。
f:id:aki517:20180603201040p:plain

テクスチャを出力

まずは、Houdiniから Impostor Texture を作成して出力します。

1.シーンビューで Tabキー > Test Geometory: Tommy を作成、適当に名前を「geo_tommy」にしておきます。
f:id:aki517:20180603185915p:plain

2.ネットワークビューから Tabキー > GameDev > GameDev Imposture Camera Rig を作成、名前を「impostor_camera_rig」にしておきます。
f:id:aki517:20180603185920p:plain

3.ネットワークビュー上部のメニューから Other Network > out を選択して Outputs に切り替えます。
f:id:aki517:20180603185923p:plain

4.Tabキー > GameDev > GameDev Impostor Texture を作成します。
f:id:aki517:20180603185926p:plain

5.パラメータビューのBaseSettingタブで以下の設定を行います。
Render in One Image:チェックを入れる
Impostor Type:Full 3D Impostor を選択、全方位からレンダリングします。
Source Geometry:「geo_tommy」を選択
Camera Rig:「impostor_camera_rig」を選択
Sprite Resolution:128を設定、1マス辺りの解像度を指定します。
Frames Around Z Rot...:9を設定、こうすると45°毎にレンダリングします。
Output Picture:テクスチャの出力パスを設定します。
f:id:aki517:20180603201023p:plain

6.「impostor_camera_rig」を選択して、パラメータビューから Impostor ROP に 作成した Impostor Texture のパスを設定します。
f:id:aki517:20180603185929p:plain

7.Impostor Texture のパラメータビューに戻り「Render」ボタンをクリックするとテクスチャが出力されます。

Unityで描画する

1.最初にインストールしたGameDevelopmentToolsetフォルダ > unity > shader を UnityのProjectビューにドラッグ&ドロップします。
f:id:aki517:20180603201100p:plain

2.次にProjectビューからMaterialを新規作成して sidefx/Impostor Alpha Blended を選択します。
f:id:aki517:20180603201103p:plain

3.MaterialのInspectorビューから出力したテクスチャを設定、Rows と Columns は Sprite Resolution と同じ値を設定します。

4.Hierarchyビューからパーティクルを新規作成してRendererモジュールに先程のMaterialを設定して、更に Custom Vertex Streams に下図の順になるよう頂点ストリームを設定します。
f:id:aki517:20180603202532p:plain

Custom Vertex Streams についてはこちらを参照ください。
goisagi-517.hatenablog.com

5.これで準備は完了です。Unityの再生ボタンをクリックしてカメラをぐりぐり動かすと以下のようにカメラの視点に合わせてテクスチャUVの参照位置が切り替わります。なんか凄くシュールな絵になってしまいましたが・・(^_^;)
f:id:aki517:20180603203221g:plain

まとめ

今回は Game Development Tools のインストールと Impostor Texture 機能を試してみました。ちなみにHoudini内で設定したアニメーションもテクスチャとして出力できるので群衆の表現とか色々と応用が出来そうですね。

参考

GitHub - sideeffects/GameDevelopmentToolset: A series of Houdini shelf tools that are geared towards game developers! Impostor テクスチャ生成 | SideFX

【Unity】新機能の Presets について

Unity 2018.1 から導入された Presets を試してみました。

Presets とは

Unityでアセットを管理する際にInspector上からパラメータを設定する事があると思います。例えば、テクスチャであれば Texture Type は Default か Sprite なのか、メモリ消費を抑えるために Read/Write Enabled のチェックを外すなど、アセットの種類(画像、モデル、アニメーション、サウンド)と制作するゲームに応じて様々な設定が必要になってきます。

そうした全ての設定を手動で行ったら物凄い時間掛かりますね。。。Presets は Inspector上で設定したパラメータを設定ファイル(以下preset)として保存後、それを他のアセットにも適用出来る機能です。

使ってみる

まずはpresetを作ります。Inspector上で対象アセットの設定が完了したら右上のスライダーアイコンをクリックして Select Preset ウインドウから「Save current to ...」をクリックすればpresetが作成されます。
f:id:aki517:20180525011541g:plain

次に別アセットを選択して同様に Inspector上のスライダーアイコンをクリックして Select Preset ウインドウから先ほど作成したpresetを選択するとパラメータが適用されます。
f:id:aki517:20180525011617g:plain

PresetManager

更にPresetManagerを使う事によってアセットインポート時の初期パラメータをpresetの値で設定できます。使い方はメニューの Edit > Project Settings > Preset Manager の Default Presets から「+」をクリックして任意の preset を登録するだけです。

f:id:aki517:20180525011629g:plain

また、preset は png, ogg, fbx だけでなく、Component にも設定できます。なので ParticleSystem の Max Particles を 1000 -> 100にした preset を用意してPresetManager に登録すれば、エフェクトのアセット作成時に制限値や必要な初期設定を手動で行う必要が無くなり、設定ミスによる不具合なども減りそうです。
f:id:aki517:20180526105712p:plain

気になった点
①presetがアセットの種類単位でしか設定できない

同じ種類のアセットだけど用途ごとに専用の設定をしたい場合はどうするんだろと思いました。例えば wav ファイルで Load Type を SE は Compressed In Memory、BGM は Streaming 、Voiceは、、といった場合です。

対処法として思いついたのは専用の設定をしたいアセットを置くフォルダと同階層に専用presetを用意して AssetPostprocessor からその preset を適用するというものです。これなら専用presetが無い場合は PresetManager で設定した preset が適用されます。

f:id:aki517:20180527193433p:plain

スクリプトはこんな感じです。

using UnityEditor;
using UnityEditor.Presets;
using System.IO;

public class PresetPostProcessor : AssetPostprocessor
{
    public const string PRESET_EXT = ".preset";

    public override int GetPostprocessOrder(){ return 1; }

    public void OnPreprocessAsset()
    {
        if( Directory.Exists( assetPath )){
            // フォルダなら何もしない.
            return;
        }
    
        string ext = Path.GetExtension( assetPath );
        if( ext == PRESET_EXT ){
            // .presetなら何もしない.
            return;
        }

        // 対象アセットの保存ディレクトリから専用presetパスを作る.
        string dirName = Path.GetDirectoryName( assetPath );
        string presetPath = (dirName + PRESET_EXT);

        if( !File.Exists( presetPath )){
            // 専用.presetが無いなら何もしない.
            return;
        }

        if( assetImporter.importSettingsMissing )
        {
            // 専用.presetを適用する.
            var preset = AssetDatabase.LoadAssetAtPath<Preset>( presetPath );
            if( preset != null ){
                preset.ApplyTo( assetImporter );
            }
        }
    }
}
②presetの変更が適用されない

preset の値を変更してもインポート済みアセットには変更が適用されないです。難しいところとして、もし preset が変更される度に該当する全アセットに適用処理が実行される場合、アセットが増えれば増えるほど、処理が完了するのに時間が掛かってしまいます。

①のような専用preset であれば値を変更後に Reimport を実行する事によって AssetPostprocessor のコールバックでインポート済みアセットに変更を適用することが出来そうです。かなり強引ですが・・ (^_^;)

まとめ

幾つか気になる点はありましたが、個人的には便利な機能だと思います。Presets の APIも提供されているのでプロジェクトに応じたカスタマイズも色々と出来そうです。

参考

https://forum.unity.com/threads/presets-feature.491263/
Preset - Unity スクリプトリファレンス

【Unity】Shuriken Particle「Custom Vertex Streams」

今回は Shuriken Particle の Renderer モジュールにある Custom Vertex Streams を試してみます。機能自体はUnity5.5からあるものですが使った事がなかったのでまとめてみました。

はじめに

Custom Vertex Streams を使えばパーティクル粒子1つ1つの状態(速度、回転速度、中心座標、etc...)をシェーダーに送る事ができます。つまり、そのデータを元に独自シェーダーを書けば、標準モジュールでは出来ない表現をすることが可能になるとの事です。
docs.unity3d.com

使ってみる

標準モジュールで生存時間(Color over Lifetime)と移動速度(Color by Speed)によるカラー変更は用意されていますが回転による設定は無いので、今回はパーティクルの回転速度に応じて色を変更するサンプルを作ってみます。以下のような回転速度が速いほど赤色になるサンプルです。
f:id:aki517:20180513225318g:plain

まずはParticleオブジェクトを作成して Rendererモジュール の Custom Vertex Streams にチェックを入れて 「+」から Rotation > RotationSpeed を選択します。
f:id:aki517:20180513224127p:plain

「RotationSpeed (TEXCOORD0.z)」となっているのは 「TEXCOORD0 セマンティクス*1の z に回転速度を渡す」という意味になります。
f:id:aki517:20180513224137p:plain

あと確認しやすくするために「Rotation over Lifetime」を有効にして Random Between Two Constants を選択、値を 0 - 720 で設定しておきます。
f:id:aki517:20180513225449p:plain

次にシェーダーを用意します。

Shader "Custom Vertex Streams/Color by Rotation Speed"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _MaxRotAng ("Max Rotation Angle Per Frame", Float) = 12
        _TarCol ("Target Color", Color) = (1,0,0,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;
                float4 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _MaxRotAng;
            fixed4 _TarCol;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                float rate = clamp((v.uv.z / _MaxRotAng), 0, 1);
                o.color = lerp( fixed4(1,1,1,1), _TarCol, rate );
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                return tex2D(_MainTex, i.uv) * i.color;
            }
            ENDCG
        }
    }
}

プロパティに最大回転角度/Frameを設定する MaxRotAng と変更色を設定する TarCol を追加してあります。

_MaxRotAng ("Max Rotation Angle Per Frame", Float) = 12
_TarCol ("Target Color", Color) = (1,0,0,1)

ここで回転角度に応じた色変更を行っています。このシェーダーでは uv が TEXCOORD0 セマンティクスとして扱っているので v.uv.z にパーティクルごとの回転角度/Frameが入ってきます。

float rate = clamp((v.uv.z / _MaxRotAng), 0, 1);
o.color = lerp( fixed4(1,1,1,1), _TarCol, rate );

最後に上記シェーダーを適用したMaterialを対象Particleオブジェクトに設定します。プロパティの Max Rotation Angle Per Frame の値を 12 にしているのは Rotation over Lifetime で最大回転角度(秒)が 720° に設定してあるので 12 = 720° / 60フレーム となるためです。
f:id:aki517:20180513224151p:plain

Custom Data モジュール

更にCustom Vertex Streams を使って Custom Data モジュール で設定したパラメータを頂点データに流し込んでみます。

まずはParticleオブジェクトの Custom Data モジュールを有効にして Custom1 のデータ設定を行います。Mode は Vector, Color があります。今回は Vector を使用してみます。Number of Components は使用する要素数です。今回は1つしか使わないので 1 にして下図のように適当にカーブを設定します。
f:id:aki517:20180515004259p:plain

次に RotationSpeed を設定した時と同様に Renderer モジュール から「+」> Custom > Custom1.x を選択して、項目が「Custom1.x (TEXCOORD0.w)」になるのを確認します。 f:id:aki517:20180515004302p:plain

最後に先程の頂点シェーダに以下の1行を追記します。

o.color.a = v.uv.w; // Custom1.x をα値として使う.

最終出力結果は下図のようにCustom1に設定したカーブの周期でαフェードが適用されます。
f:id:aki517:20180515004315g:plain

まとめ

Custom Vertex Streams と Custom Data モジュールを上手く使えば標準モジュールやビルトインシェーダーでは表現出来ない演出が実現できそうです。

また、Custom1, Custom2のパラメータはスクリプト側から渡す事も出来るのでプレイヤーのステータス情報などを渡してそれに応じた演出なども出来そうです。 docs.unity3d.com

【Houdini】何か作ってみる

前回に引き続き、今回も Houdini です。スクリプト書いて色々とやってみたいと夢を膨らませていたのですが、まずは基本操作とか最低限のことを理解する必要あるだろう(^ ^;) という事で今回は下図のように基本図形のTorusにMaterialを割り当てて変形させるまでをやってみます。

f:id:aki517:20180506214126p:plain

  1. Houdiniを起動して上部メニューの File > New Project を選択して Project Name にプロジェクト名、Project Path にこのプロジェクトの保存先を指定して Acceptボタン をクリックして新規プロジェクトを作成します。
    f:id:aki517:20180506211029p:plain
    プロジェクト設定をした方が良い理由はこちらの動画で詳細に説明しています。 vimeo.com

  2. シーンビューを選択して Tabキーを押してオペレータ一覧を表示した状態で「Torus」を選択後、Enterキーを押すとシーンに Torus が生成されます。
    f:id:aki517:20180506211259p:plain

  3. Torusに割り当てるMaterialを作成します。ネットワークビューから Material Palette タブを押してベースとなるMaterialを選択して右側のウィンドウにドラッグすると新規Materialが作成されます。
    f:id:aki517:20180506212557p:plain

  4. TorusにMaterialを適用します。Torusを選択してパラメータウィンドウからRenderタブを押して、作成したMaterialを選択後、Acceptボタンをクリックします。別の方法としてMaterialを選択してシーンビューのTorusにドラッグ&ドロップする方法でも適用できます。
    f:id:aki517:20180506212610p:plain

  5. Materialのパラメータ変更は下図のボタンを押すか、または先程のMaterialPaletteから変更する事が出来ます。今回は黄色にしてみました。絵心なくてすみません・・(T T)
    f:id:aki517:20180506212621p:plain f:id:aki517:20180506211408p:plain

  6. 最後に形状を変形させるためにネットワークビューからTabキーを押してオペレータ一覧から「Mountain」を選択します。
    f:id:aki517:20180506211422p:plain

  7. Torus と Mountain を接続すると形状が変化します。変形度合の調整をする場合はパラメータウィンドウから Height, Element Size の値をいじると分かりやすく変化します。 f:id:aki517:20180506212708p:plain

最後のTorusとMountainによるオペレータ接続ではパラメータの違うMountainを複数用意して状況に応じてTorusを接続すれば色々な表現ができたり、その逆で Torus ではなく Plane モデルを配置してMountainに接続する事によって複雑な地形を作成する事もできるなぁと思いました。

次回はもっと複雑な事ができないか頑張ってみます(^^;)