概要
UnityのURPでRendererにセットしたRendererFeatureのインスタンスを取得するには、無改造ではシングルトンとしてstaticメンバでクラスインスタンスを取得できるようにするぐらいしか手がありませんが、クラスインスタンスが1つで済むとは限りません。
以下のページの様にReflectionを利用してprivateメンバを引っぱりだせば可能ですが、この方法を生理的によしとしない人もいるでしょう。
https://qiita.com/makisin/items/5d66f1ea97f525f0c6d8
そこでURPを改造して 2つ簡単なクラスメソッドを追加 することで、Camera からRendererFeatureのインスタンスにたどり着くまでの方法を紹介します。
(準備) URPをカスタムできる状態にする
- Unityが終了している状態にしてください
- ProjectFolder/Library/PackageCache から com.unity.render-pipelines.universal@(バージョン番号) のフォルダを、ProjectFolder/Packages にコピーします
- このコピーした方を改造してください
- 次にUnityでそのプロジェクトを起動するとPackageCacheの同フォルダは消えてしまうので、無改造の状態を残しておきたい場合は、プロジェクトフォルダ外にバックアップしておいてください
- 次にUnityでそのプロジェクトを起動してPackageManagerで見ると UniversalRP が [CUSTOM] に変わっているはずです
(改造1) カメラに設定したRenderer番号をとってくる機能
- Runtime\UniversalAdditionalCameraData.cs
- SetRenderer の次辺りに追加すると良いでしょう
//=========================================================================================
/// <summary>
/// カメラにセットされたレンダラー番号を取得する 改造
/// </summary>
/// <returns> m_RendererIndex (カメラにセットされたレンダラー番号)</returns>
public int GetRendererIndex()
{
return m_RendererIndex;
}
//=========================================================================================
(改造2) UniversalRenderPipelineAssetから指定したindexに従ってScriptableRendererDataを返す機能
- Runtime\Data\UniversalRenderPipelineAsset.cs
- classの最後にでも追加しましょう
//=========================================================================================
/// <summary>
/// m_RendererDataListをindexで取得できるようにする 改造
/// </summary>
/// <param name="index"></param>
/// <returns>パイプラインにセットしたScriptableRenderer列のindex番目にあたるScriptableRendererData、indexがオーバーしているときはnullが返る</returns>
public ScriptableRendererData GetScriptableRendererData(int index)
{
if (index < 0 || index >= m_RendererDataList.Length)
{
return null;
}
return m_RendererDataList[index];
}
//=========================================================================================
使い方
- Camera _cameraとしてRendererFeatureを取り出したいRendererが設定されたカメラが引ける状態
- int _myRendererFeatureIndex として取り出したいRendererFeatureの順番が入っている状態 (レンダラー設計者として何番目かはわかっているはず)
//カメラのURP拡張データを取り出す
UniversalAdditionalCameraData cameraData = _camera.GetUniversalAdditionalCameraData();
//改造メソッドでレンダラー番号を取り出す
int rendererIndex = cameraData.GetRendererIndex();
//プロジェクト設定からパイプラインアセットを取り出す
UniversalRenderPipelineAsset _renderPipelineAsset = ((UniversalRenderPipelineAsset)GraphicsSettings.renderPipelineAsset);
//カメラから取り出したレンダラー番号から改造メソッドでScriptableRendererDataを取り出す
var scriptableRendererData = _renderPipelineAsset.GetScriptableRendererData(rendererIndex);
//そのレンダラー内のRendererFeature配列を取り出す
var rendererFeatures = scriptableRendererData.rendererFeatures;
//何番目がなんのRendererFeatureかというのはレンダラー設計者は知っているハズ
MyRendererFeature myRendererFeature = (MyRendererFeature)rendererFeatures[_myRendererFeatureIndex];
//インスタンスを取り出せたので制御しよう(仮想コード)
myRendererFeature.SetHoge(true); //Hogeを有効にする