太郎Work

Unityとかで困ったこと等を残しておきます

ShaderGraphのPBRMasterNodeを拡張してみた

UniversalRPには標準でPBRMasterNodeがありますが、Fogの処理を変えたかったりほんの少し処理変えたかったりしたかったので自作のMasterNodeを作ってみました
速攻で仕様変わっていたらすみません...
Unity2019.4+ShaderGraph7.5.0+UniversalRP7.5.0

8/24追記
ShaderGraph9.x.xでは仕様が全く違うためここで作ったものは動きません...

  • はじめに
  • 最低限必要なファイルを複製する
  • Culling設定をMaterial側に持たせる
    • PBRMasterNodeからTwo Sidedを削除
    • SubShaderにCull設定を追加
    • ShaderPropertiesにCull設定を追加
  • Fogを自前のものに置き換える
    • fogのmulti_compileを更新
    • hlsl複製
    • シェーダ改修
  • Cutoffの数値でAlphaTest処理を分岐させる
    • ShaderGraphのAlphaTest仕様
    • 従来の処理に合わせて_ALPHATEST_ONマクロを定義する
  • おわり

はじめに

ShaderGraphのクラスはprivateになっているため、何かしらの方法でアクセスできるようにする必要があります

  • Graphicsリポジトリをフォークしてその中に直接スクリプトを追加する
  • AssemblyInfo.csに記載されている名前でasmdefを作成する

2個めはかなり無理矢理な手法になってしまうので直接スクリプトを追加する方針にしました

github.com
↑このリポジトリはクソデカなので落とすときは気をつけてください

最低限必要なファイルを複製する

My~とか適当な名前をつけて以下のファイルを複製します

PBRMasterGUI.cs
生成されたシェーダコードに使用されるMaterialEditor

f:id:tarowork:20200818165435p:plain
拡張しなければデフォルトのGUIで描画される

PBRMasterNode.cs
MasterNode実体 Slotの追加や設定で使用するシリアライズパラメータもここでもたせる

f:id:tarowork:20200818165403p:plain
Graphの終点に配置するコード生成を行うノード

PBRSettingsView.cs

f:id:tarowork:20200818165130p:plain
MasterNodeの右上のアイコンをクリックしたときのウィンドウ


PBRSubShader.cs
SubShader生成時の文字列生成ロジック(includeファイルとか)


これだけであとは型を置き換えればMasterNodeが完成します
ここからは機能を追加してみます

続きを読む

Timeline関連メモ

何かあったら追記していきます

Timelineでカスタムトラックを作成したときにcurves編集ボタンを出す条件
f:id:tarowork:20200722180312p:plain

AnimatedParameterUtility.cs内に実装があった
IPlayableBehaviour を実装したクラスのフィールドを必ず持つ必要がある

static FieldInfo[] GetScriptPlayableFields_Internal(IPlayableAsset asset)
{
    return asset.GetType()
        .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
        .Where(
            f => typeof(IPlayableBehaviour).IsAssignableFrom(f.FieldType) &&                                        // The field is an IPlayableBehaviour
            (f.IsPublic || f.GetCustomAttributes(typeof(SerializeField), false).Any()) &&       // The field is either public or marked with [SerializeField]
            !f.GetCustomAttributes(typeof(NotKeyableAttribute), false).Any() &&                 // The field is not marked with [NotKeyable]
            !f.GetCustomAttributes(typeof(HideInInspector), false).Any() &&                     // The field is not marked with [HideInInspector]
            !f.FieldType.GetCustomAttributes(typeof(NotKeyableAttribute), false).Any())         // The field is not of a type marked with [NotKeyable]
        .ToArray();
}

EnterPlayMode時にNativeArrayのエラーが発生する

Unity2019.3.1f1の時点です

再生までの時間が早くなるEnterPlayModeを使用すると
NativeArrayアクセス時に↓このエラーが発生します

InvalidOperationException: The NativeArray has been deallocated, it is not allowed to access it

ExecuteAlwaysを指定しているためOnEnableでnew、OnDisableでDisposeしているのですが、どうも適切に開放、確保ができていないようです。

f:id:tarowork:20200226111055p:plain

ReloadSceneにチェックを付ければエラーは発生しなくなりました

UnityTimelineのTrackをスクリプトから入れ替える

現在Timeline関連の実装をしているのですが、Trackの順序をスクリプトから入れ替えたくなったのでメモ
多分こんなことしたい人いないと思うので需要ゼロです

入れ替えたい理由はPlayableOutputの接続順をプログラム的に変えたかったためです

本来はWindow内でTrackを掴むことで順番を入れ替えられます

f:id:tarowork:20200219134548p:plain
Timeline Window

このTrackを保持しているのはPlayableDirectorに指定しているTimelineAssetですが、このTimelineAssetにはMoveが用意されていません

docs.unity3d.com

悲しいことにCreateTrackとDeleteTrackしかなく、TimelineWindowの実装を追っていくと内部でMove的なメソッドは存在していますが呼び出しやすい感じにはなっていません…

そこでTrackを入れ替えたときのTimelineAssetの差分を見てみると `List m_Tracks` 中身を変更しているだけでした
f:id:tarowork:20200219144759p:plain

なので無理やりSerializedPropertyから書き換えることで入れ替えがうまくいきました。

var so = new SerializedObject(timelineAsset);
var tracks = so.FindProperty("m_Tracks");
tracks.MoveArrayElement(src, dst);
so.ApplyModifiedProperties();
so.Dispose();

これだけだとTimelineWindowの描画が更新されないのでReflectionでTimelineAssetを再読み込みするメソッドを呼び出します
第4引数のboolをtrueにしておくことで実質Reload状態にすることが出来ました

var timelineWindowType =
    typeof(UnityEditor.Timeline.TimelineEditor).Assembly.GetType("UnityEditor.Timeline.TimelineWindow");
var window = EditorWindow.GetWindow(timelineWindowType);
var method = timelineWindowType.GetMethod("SetCurrentTimeline",
    BindingFlags.Instance | BindingFlags.NonPublic,
    null,
    new[] {typeof(TimelineAsset), typeof(PlayableDirector), typeof(TimelineClip), typeof(bool)},
    null);

method?.Invoke(window, new[] {timelineAsset, _director, (object) null, true});
<||

VFXGraphで星空を描画してみた

はじめに

本記事は QualiArts Advent Calender 2019 24日目の記事になります。
昨日は @ogrszk の 「Spineでできること〜エディタのTipsとAPI使用例〜」でした


f:id:tarowork:20191121212257j:plain
星空
Unity2019になり、UniversalRenderPipelineなど新機能が追加されましたが、その中の一つであるVFXGraphを使用して星空を描画してみました

注意:

  • 天文学全くわからない素人なので厳密な計算とかは分からないです
  • 新機能の基本的な使用方法は割愛しています

環境

  • Unity2019.3.0b11
  • UniversalRP 7.1.5

目次

  • はじめに
  • 星のデータを用意
  • プロジェクトの作成
  • 星描画に使うPointCacheを生成
    • テキストからMesh化するプログラム
    • 明るさ
    • MeshからPointCacheAssetを作成
    • 星のテクスチャを作成
  • VFXGraph
    • Spawn
    • PointCacheNode
    • GetAttributeNode: color
    • Output Particle Quad
    • VFXGraph全体
    • 結果
  • レンダリング
  • まとめ
続きを読む

Unity2019時代のパッケージ管理

今までのUnityでは .unitypackage を使用したり Assets 以下にGitのSubmoduleで管理するといった方法がありましたが、やっとPackageManager周りが実用的になったので個人的に良いなと思ったフローを紹介します

今回の記事は2019.1.3で作成しています。今後仕様が変わる可能性があるので注意してください
ここで作成したサンプルはこちらに上げているので気になったらどうぞ
github.com

続きを読む

UnityEditorのGameViewが更新されない時の対処方法

非実行時にEditorスクリプトからHierarchey内のオブジェクトに変更を加えても
UnityEditor全体に対しての更新通知が行かないため、SceneView,GameViewの描画更新が行われない

Viewサイズを変える、Inspectorから変更をする等をすれば更新されるがすぐに確認したい場合

Unity - Scripting API: EditorApplication.QueuePlayerLoopUpdate

遡ると2017.2から追加された模様

これを呼び出せばUnityEditor全体にRepaint通知が行ってすぐに見た目が確認できるようになった