Unityのエディタ拡張でモデルを表示したいな...となった時に調べたものの備忘録です!
PreviewRenerUtility
を使用すると比較的簡単にエディタ拡張のウィンドウ上にモデルを表示できました〜
Unityのバージョン:2022.3.36f1
こんな感じでプレビューできます
これだけだと味気ないので、後半で回転させられるようにコードを追加します!
とりあえず最低限のコード
using UnityEditor;
using UnityEngine;
public class ModelPreviewEditor : EditorWindow
{
[MenuItem("Tools/Open Model Preview")]
private static void OpenModelPreview()
{
ModelPreviewEditor modelPreview = EditorWindow.GetWindow<ModelPreviewEditor>("Model Preview");
modelPreview.Initialize();
}
private PreviewRenderUtility previewRenderUtility;
private GameObject modelObj;
private Texture2D modelTexture;
private bool initialized;
public void Initialize()
{
GameObject modelPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/Cube.prefab");
previewRenderUtility = new PreviewRenderUtility();
// SceneViewやGameViewに映らないところにインスタンス化.
modelObj = previewRenderUtility.InstantiatePrefabInScene(modelPrefab);
// 適当な座標に移動させる.
modelObj.transform.position = new Vector3(0, -0.5f, 0);
// PreViewRenderUtilityにGameObjectを追加する.
previewRenderUtility.AddSingleGO(modelObj);
// カメラをいい感じに調整.
previewRenderUtility.camera.farClipPlane = 5000;
previewRenderUtility.camera.transform.position = new Vector3(0, 0, -10);
// 描画.
previewRenderUtility.BeginStaticPreview(new Rect(0, 0, 400, 400));
previewRenderUtility.Render();
modelTexture = previewRenderUtility.EndStaticPreview();
initialized = true;
}
private void OnGUI()
{
if(!initialized) return;
// Windowにテクスチャを描画.
GUI.DrawTexture(new Rect(0, 0, 400, 400), modelTexture);
}
private void OnDisable()
{
previewRenderUtility.Cleanup();
}
}
簡単に解説
上記コード上のInitialize()
メソッドでPrefabをGameObject化、PreviewRenerUtility
に追加して描画しています。
PreviewRenerUtility
のメソッドの呼び方が一番重要かもしれません。
順に簡単に解説します。
PreviewRenderUtilityのインスタンス化
previewRenderUtility = new PreviewRenderUtility();
特に解説することはなし...!
インスタンス変数に格納して、後で取り回ししやすいようにしています。
GameObjectの準備
modelObj = previewRenderUtility.InstantiatePrefabInScene(modelPrefab);
modelObj.transform.position = new Vector3(0, -0.5f, 0);
ここではプレハブをもとにGameObjectとしてインスタンス化しています。
いつものInstantiate()
を使用すると、普通にSceneViewにインスタンス化されてしまうのでご注意を。
GameObjectの位置などもここで調整しています。
GetComponent()
やAddComponent()
で自作クラスのインスタンスを取得したりすると、いろいろできますね〜
previewRenderUtility.AddSingleGO(modelObj);
↑このコードで、PreviewRenerUtility
にGameObjectを追加します。
カメラの調整
previewRenderUtility.camera.farClipPlane = 5000;
previewRenderUtility.camera.transform.position = new Vector3(0, 0, -10);
PreviewRenerUtility
にはあらかじめカメラが用意されているようです。
ありがたく調整して、モデルがいい感じに表示されるように調整します。
描画処理
previewRenderUtility.BeginStaticPreview(new Rect(0, 0, 400, 400));
previewRenderUtility.Render();
modelTexture = previewRenderUtility.EndStaticPreview();
指定したRectの領域に描画してくれます。
EndStaticPreview()
を最後に呼び出すと、Texture2D
のインスタンスが取得できます。
これをEditorWindowに表示してあげればOKです!
オブジェクトの状態などを変更してBeginStaticPreview()
~EndStaticPreview()
を呼んで都度描画すれば、テクスチャに反映されます。
また、BeginPreview()
・EndPreview()
を使用するとTextureが取得できるようです。
EditorWindowに描画
GUI.DrawTexture(new Rect(0, 0, 400, 400), modelTexture);
OnGUI()
上で上記を呼び出せば、指定した領域にテクスチャが描画されます!
後始末
private void OnDisable()
{
previewRenderUtility.Cleanup();
}
EditorWindowを閉じるときに後処理をしてあげましょう。
やらないとエディターに怒られます。
モデルを回転できるようにしてみる
コード全体はこんな感じです!
using UnityEditor;
using UnityEngine;
public class ModelPreviewEditor : EditorWindow
{
[MenuItem("Tools/Open Model Preview")]
private static void OpenModelPreview()
{
ModelPreviewEditor modelPreview = EditorWindow.GetWindow<ModelPreviewEditor>("Model Preview");
modelPreview.Initialize();
}
private PreviewRenderUtility previewRenderUtility;
private Texture2D modelTexture;
private GameObject modelObj;
private bool initialized;
private int currentRotateAngle;
public void Initialize()
{
GameObject modelPrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/Cube.prefab");
previewRenderUtility = new PreviewRenderUtility();
// SceneViewやGameViewに映らないところにインスタンス化.
modelObj = previewRenderUtility.InstantiatePrefabInScene(modelPrefab);
// 適当な座標に移動させる.
modelObj.transform.position = new Vector3(0, -0.5f, 0);
// PreViewRenderUtilityにGameObjectを追加する.
previewRenderUtility.AddSingleGO(modelObj);
// カメラをいい感じに調整.
previewRenderUtility.camera.farClipPlane = 5000;
previewRenderUtility.camera.transform.position = new Vector3(0, 0, -10);
// 描画.
previewRenderUtility.BeginStaticPreview(new Rect(0, 0, 400, 400));
previewRenderUtility.Render();
modelTexture = previewRenderUtility.EndStaticPreview();
initialized = true;
}
private void OnGUI()
{
if(!initialized) return;
EditorGUILayout.Space(420);
// 回転する角度を取得.
currentRotateAngle = EditorGUILayout.IntSlider("モデルの回転", currentRotateAngle, 0, 360, GUILayout.Width(300));
previewRenderUtility.BeginStaticPreview(new Rect(0, 0, 400, 400));
modelObj.transform.rotation = Quaternion.Euler(0, currentRotateAngle, 0);
previewRenderUtility.Render();
modelTexture = previewRenderUtility.EndStaticPreview();
// Windowにテクスチャを描画.
GUI.DrawTexture(new Rect(0, 0, 400, 400), modelTexture);
}
private void OnDisable()
{
previewRenderUtility.Cleanup();
}
}
ほぼOnGUI()
の中身だけが変わっております。(currentRotateAngle
というインスタンス変数だけ増えてます。)
BeginStaticPreview()
とRender()
の間でモデルオブジェクトを回転させています。
わかりやすく間に挟みましたが、別に挟まなくても大丈夫そうです。
まとめ
サクッとエディタ拡張でモデルをプレビューさせるだけなら、PreviewRenderUtility
は便利ですね!
本格的にプレビューさせたい場合は、いろいろ足りていないのでこちらのブログ記事などが参考になるかもです:https://light11.hatenadiary.com/entry/2020/02/29/211114
この記事を書くにあたり参考にさせていただいたブログ様
https://msa-i.com/unity/83432/