GenerateHLSL完全に理解した
Unity2021.2のOverlay機能を使う
Overlay機能
Unity2021.2からSceneView上の要素はOverlayというものに置き換わり、自由に配置を動かせるようになりました。
ParticleSystemを選択したときのウィンドウも↓こんな感じになっていて左上をドラッグすることで自由に動かすことができます
自分でも追加したくなったのでやってみたのですがめちゃくちゃ簡単だったのでメモ
フレア処理を高速化した話
この記事はQualiArts Advent Calendar 2020の20日目の記事になります。
昨日は 無料のDataformでBigQueryにおけるデータ加工のDXを改善して幸せになろう - Qiita でした
はじめに
現在開発中のプロジェクトではUniversalRenderPipeliene(以下URP)を使用しているためレンズフレアを使用することができません
LensFlareどころかHaloも使用できないため画面にフレアを描画する手段がURPには用意されていません。
他にもかなり機能制限があるので比較を見たい方はこちら
docs.unity3d.com
そこでアセットストアでLensFlareを探すと何個か引っかかるのですが意外と存在しない…
https://assetstore.unity.com/?q=Lens%20Flare&orderBy=0
この中で一番細かく設定できそうだったProFlareを導入したのですが、大量のフレアを出すとCPU,GPU共に負荷が高く、実機でボトルネックとなってしまったのでSRP用に描画部分を作り直すことにしました
このアセット自体は非常に高品質なレンズフレアを作成できるためちょっと使う分であればオススメです
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になっているため、何かしらの方法でアクセスできるようにする必要があります
2個めはかなり無理矢理な手法になってしまうので直接スクリプトを追加する方針にしました
github.com
↑このリポジトリはクソデカなので落とすときは気をつけてください
最低限必要なファイルを複製する
My~とか適当な名前をつけて以下のファイルを複製します
PBRMasterGUI.cs
生成されたシェーダコードに使用されるMaterialEditor
PBRMasterNode.cs
MasterNode実体 Slotの追加や設定で使用するシリアライズパラメータもここでもたせる
PBRSettingsView.cs
PBRSubShader.cs
SubShader生成時の文字列生成ロジック(includeファイルとか)
これだけであとは型を置き換えればMasterNodeが完成します
ここからは機能を追加してみます
Timeline関連メモ
何かあったら追記していきます
Timelineでカスタムトラックを作成したときにcurves編集ボタンを出す条件
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しているのですが、どうも適切に開放、確保ができていないようです。
ReloadSceneにチェックを付ければエラーは発生しなくなりました
UnityTimelineのTrackをスクリプトから入れ替える
現在Timeline関連の実装をしているのですが、Trackの順序をスクリプトから入れ替えたくなったのでメモ
多分こんなことしたい人いないと思うので需要ゼロです
入れ替えたい理由はPlayableOutputの接続順をプログラム的に変えたかったためです
本来はWindow内でTrackを掴むことで順番を入れ替えられます
このTrackを保持しているのはPlayableDirectorに指定しているTimelineAssetですが、このTimelineAssetにはMoveが用意されていません
悲しいことにCreateTrackとDeleteTrackしかなく、TimelineWindowの実装を追っていくと内部でMove的なメソッドは存在していますが呼び出しやすい感じにはなっていません…
そこでTrackを入れ替えたときのTimelineAssetの差分を見てみると `List
なので無理やり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}); <||