今日は、Unity Editorのスクリプトの書き方についてお話します。 この記事は、Unity3Dにすでに精通しており、なんとかしてはいるが、エディター用のスクリプトを作成しようとはまだ決めていない人を対象としています。
要するに、エディターモードでは、スクリプトはゲームモードとまったく同じようにすべてを実行できます。
簡単なものから始めましょう。 エディターモードで10個のサイコロを作成し、それらを一列に並べたいとします。 まず、タスクを簡素化し、エディターを忘れて、アプリケーションの起動時にこれらのキューブを作成しましょう。
public class CreateCubes : MonoBehaviour {
エディターモードでこのコードを実行してみましょう。このため、Create10Cubes()関数のコードにマジックアトリビュート[ContextMenu()]を1つだけ追加する必要があります。
コードは次のようになります。
[ContextMenu("CreateCubes")] private void Create10Cubes() { Vector3 position = new Vector3(0, 0, 0); for (int i = 0; i < 10; i++) { GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube); cube.transform.position = position; position += new Vector3(5, 0, 0); } }
ここで、スクリプトのタイトルを右クリックすると、CreateCubesアイテムがそこに表示されます。クリックすると、関数もまったく同じように実行されます。
重要な注意:ContextMenu属性でマークされた関数にはパラメーターがあってはなりません。パラメーターがある場合は、この方法で呼び出すことはできません。
個人的には、オブジェクトのグループで何かをする必要があるときにこのメソッドを使用します。たとえば、名前に「withoutshadow」が含まれるオブジェクトのすべての子の影の投影をオフにします。
[ContextMenu("DisableCastShadows")] private void DisabeCastShadows() { Renderer[] renderers = GetComponentsInChildren<Renderer>() .Where(x => x.name.Contains("withoutshadow")) .ToArray(); foreach (var r in renderers) { r.castShadows = false; } }
一般に、このメソッドはオブジェクトの束に対する1回限りのアクションに適しています。目的のコードを別のクラスにすばやく投げ、目的のオブジェクトに投げて、すぐにこのクラスをヘアドライヤーユニットに削除しました。
では、次の問題を解決しましょう。オクルージョンカリングをベイクする必要があります。 これを行うには、他のオブジェクトをブロックするすべてのオブジェクトで[オクルーダースタティック]ボックスをオンにし、オクルーダーの後ろに隠されるすべてのオブジェクトで[オクルードスタティック]チェックボックスをオンにする必要があります。 つまり、すべての静的オブジェクトを分離し、不透明なオブジェクト(実際にはすべて)に両方のドーズを配置し、透明な(オクルードのみ)、オクルーダーをオフにする必要があります。
まあ、それは何だろう、私はペンでステージを走り回った-私は誰のためにダニを設定した-それはそれだ。 しかし、問題はシーン内に多くのオブジェクトが存在する可能性があり、プロジェクトの開発中にシーンが変更される可能性が高いことです。 これらすべてのチェックマークを確認してください-あなたは夢中になることができます。 そのため、これを行う小さなスクリプトを作成します。
まず、作業を行う便利なコードを作成し、それを別のウィザードに配置します。
ここには2つのタスクがあります。
1)シーン内で関心のあるオブジェクトを見つけます。
2)ボックスをチェックします。
どこからでも呼び出すことができ、どのウィザードで呼び出されるかに依存しないように、別のコマンドの形式でコードを発行します。 注:次のコードを含むファイルは、Editorというフォルダーに配置する必要があります。これは、このコードがメインビルドに該当しないようにするために必要です。
using UnityEngine; using UnityEditor; using System.Linq; public class SetStaticOclluderFlagsCmd { private const int TransparentQueue = 3000; const int OverlayQueue = 4000; public void Execute() { var scene =Object.FindObjectsOfType(typeof(GameObject)); var transparents = scene.Where(o =>IsStatic(o) && IsTransparent(o)).ToArray(); var occluders = scene.Where(o => IsStatic(o) && !IsTransparent(o)).ToArray(); SceneModeUtility.SetStaticFlags(transparents, (int)StaticEditorFlags.OccluderStatic, false); SceneModeUtility.SetStaticFlags(transparents, (int)StaticEditorFlags.OccludeeStatic, true); SceneModeUtility.SetStaticFlags(occluders, (int)StaticEditorFlags.OccluderStatic, true); SceneModeUtility.SetStaticFlags(occluders, (int)StaticEditorFlags.OccludeeStatic, true); Debug.Log("SetStaticOclluderFlagsCmd done"); } private bool IsStatic(Object obj) { GameObject gameObject = obj as GameObject; if (gameObject == null) return false; return GameObjectUtility.AreStaticEditorFlagsSet(gameObject, StaticEditorFlags.BatchingStatic); } private bool IsTransparent(Object obj) { GameObject gameObject = obj as GameObject; if (gameObject == null ||gameObject.renderer == null) return false; return obj.renderer.sharedMaterials.Any(x => x.renderQueue >= TransparentQueue && x.renderQueue < OverlayQueue);; } }
ここでは、静的オブジェクトが何らかの方法で(おそらくペンで)既に検出されており、静的チェックボックスでマークされていると想定しています。これは、BatchingStaticを含むことを意味します。
IsTransparent()メソッドの実装について。私はシェーダーを書くのが苦手で、そのような実装が正しいことを保証することはできません。標準シェーダーでのみ機能すると言えます。 誰かがより正確な実装方法を要求した場合、私は間違いなくそれを置き換えます
このコマンドを簡単に呼び出すことができるように、別のウィザードを作成しましょう。
これがEditorWindowクラスが便利なところです。
using UnityEngine; using UnityEditor; public class OcclusionCullingUtilites : EditorWindow { [MenuItem("Window/OcclusionCullingUtilites")] static void Init() { GetWindow<OcclusionCullingUtilites>(); } void OnGUI() { if(GUILayout.Button("SetStaticFlags")) { SetStaticOclluderFlagsCmd cmd = new SetStaticOclluderFlagsCmd(); cmd.Execute(); } } }
これでレビューは終わりです。完全にはほど遠いことがわかりました。
次の記事では、クラスのカスタムインスペクターを作成する方法、アセットのインポートプロセスに介入する方法、ベイクドシャドウを20レベルで順番に配置し、結果のスクリーンショットをメールで取得する方法について説明する予定です。