今開発中のもので、デバッグ用のカメラとOculus向けのカメラを交互にオン/オフしてデバッグしていました。
が、意外とこれがめんどくさい。なんとかスクリプトでできないかなーと思っていたところ、Editor ScriptのMenuItem
を使って達成できそうだということでやってみました。
サンプルコード
なにはともあれコードを。
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.IO;
public static class CameraToglle {
private static string oculusCameraName = "LeapOVRCameraRig";
private static string clientCameraName = "debugCamera";
[MenuItem("Tools/CameraToggle")]
private static void Menu() {
GameObject oculusCamera = null;
GameObject debugCamera = null;
// シーンファイルの拡張子
string unityExtension = ".unity";
// リソースからすべてのオブジェクトを取得し、その中から該当オブジェクトを探す
foreach(GameObject obj in Resources.FindObjectsOfTypeAll(typeof(GameObject))) {
if (obj.name == oculusCameraName) {
string path = AssetDatabase.GetAssetOrScenePath(obj);
string ext = Path.GetExtension(path);
if (ext == unityExtension) {
oculusCamera = obj;
}
}
else if (obj.name == clientCameraName) {
string path = AssetDatabase.GetAssetOrScenePath(obj);
string ext = Path.GetExtension(path);
if (ext == unityExtension) {
clientCamera = obj;
}
}
}
// Activeをトグルする
bool isOculusActive = oculusCamera.activeSelf;
oculusCamera.SetActive(!isOculusActive);
clientCamera.SetActive(isOculusActive);
}
}
ちょっとトグルするだけなのにだいぶ冗長な感じです。
が、一度inactive
にしてしまうとGameObject.Find
メソッドで検知できなくなってしまいます。
なのでこんな周りくどいことをやっているんですね。
なにをやっているか
Resources.FindObjectsOfTypeAll()
を使ってUnityが認識しているリソース全体から該当オブジェクトを探しています。
微妙に分岐が入ってるのは、シーン内のオブジェクトに限らずAssetsディレクトリに配置されているファイルも検索対象だからです。
今回の場合は特に、 Prefab化したものもマッチして2回検知されてしまう ためそれを分岐して処理している、というわけです。
AssetDatabase.GetAssetOrScenePath
から返る文字列は「Assetsディレクトリのどこにあるか」が返されます。
ただしシーン内に配置されているオブジェクトの場合は****.unity
ファイル内ということになり、そのパスが返されます。
なので.unity
にマッチしているかを確認しているわけです。
余談
ちなみに最初、シンプルな確認用プロジェクトを作って試したところいっこうにpath
に値が入らず「???」でした。
が、シーンを保存しておらず、Assetsディレクトリ配下にないために空文字が返されていた、というちょっとマヌケな理由でした。
普通のプロジェクトであればシーンが保存されていないことはまずないと思うのでそういう問題は起きないと思います。
閑話休題。
さて、上記の処理でinacitveな該当オブジェクトを見つけることができるので、あとは普通にスクリプトを書くのと同じように処理を書いてやればOKです。
今回の例ではふたつのオブジェクトのactive
をトグルして入れ替える、というものです。
細かい処理ですが頻繁に切り替えながら開発する場合は意外に重宝します。