アピリッツの知識共有サイト「ナレッジベース」で公開されている内容をアピスピでも紹介します。こちらはES部のエンジニア・Iさんによる記事です。
クライアントエンジニアのIです。
現在Switchの新規開発(Unity)のローカライズ担当のクライアントとして仕事をしています。
今回は実際に業務の中で実装した「文字列が設定されているオブジェクトを検索する機能」について紹介をしたいと思います。
経緯
プランナーやデザイナーの画面を見ながら会話をしているとScene上のオブジェクトを沢山クリックしてオブジェクトを探すという光景が良く見られます。
Unityでは画面上でオブジェクトを直接クリックすることでオブジェクトを選択状態にすることができ、選択したオブジェクトの状態をInspectorで確認することができますが、基本的に多くのオブジェクトが重なっているので中々確認したいオブジェクトに辿り着かなかったり、クリックをしすぎて通り過ぎてしまったりと中々オブジェクトを選択状態にするのが大変です。
実装している人は何となくオブジェクト名を覚えているはずなので簡単に検索して探せるかもしれませんが、プランナーが確認するときにオブジェクトを探す手段はやはりクリックして追いかけるしかないです。
ローカライズを対応があるので「テキストのフォントサイズ等を確認しないといけない」みたいなシチュエーションが多くありました。
そこで「画面上に出ている文字列からオブジェクトを検索できるような機能」があれば便利かなあと思って実装しました。
実装
実装はシンプルで文字列を入力できるEditorWindowを作成して、TextMeshProのテキストに検索で入力した文字が含まれているものを一覧で表示します。
それぞれがボタンになっていてクリックするとオブジェクトが選択された状態になります。
これでInspectorにそのオブジェクトの状態をすぐさま確認することができます。
public class FindObjectByText : EditorWindow
{
private static float WINDOWSIZE_W = 500f;
private static float WINDOWSIZE_H = 500f;
// 入力テキスト
private string _inputText = "";
// 検索結果
private List<TMP_Text> _resultTexts = new List<TMP_Text>();
private Vector2 _scrollPos = new Vector2();
[MenuItem("Tools/FindObjectByText")]
public static void ShowWindow()
{
var window = GetWindow<FindObjectByText>();
var windowPos = window.position;
windowPos.size = new Vector2(WINDOWSIZE_W, WINDOWSIZE_H);
window.position = windowPos;
}
private void OnGUI()
{
using (new GUILayout.VerticalScope())
{
GUILayout.Label("テキストを入力してください");
_inputText = EditorGUILayout.TextField(_inputText);
if (GUILayout.Button("検索"))
{
SearchObject(_inputText);
}
if (_resultTexts.Any())
{
GUILayout.Space(10);
GUILayout.Label("検索結果");
using (GUILayout.ScrollViewScope scroll = new GUILayout.ScrollViewScope(_scrollPos,EditorStyles.helpBox))
{
_scrollPos = scroll.scrollPosition;
foreach (var tmp in _resultTexts)
{
if (tmp == null)
{
continue;
}
if (GUILayout.Button(tmp.name))
{
Selection.activeObject = tmp;
}
}
}
}
}
}
private void SearchObject(string text)
{
_resultTexts.Clear();
var textObjects = FindObjectsOfType<TMP_Text>();
for (int i = 0; i < textObjects.Length; i++)
{
var textObj = textObjects[i];
// 検索
if (textObj.text.IndexOf(text, StringComparison.Ordinal) > -1)
{
_resultTexts.Add(textObj);
}
}
}
まとめ
大した機能では無いですが、あると地味に便利だと思います。
テキストだけでなく「CharacterIdからキャラのモデルを検索」したりなど色々なComponentに対して応用することが可能です。
このような「何かのComponentの情報からオブジェクトを検索する機能」は特にバグ修正の時などにも使いやすい機能だと思うので是非使ってみてください。
最近業務をする上で少しでも「自分が不便だな」と感じたり、他の人の作業を見たときに「何か不便そうだな」と感じたらなるべく効率化できる機能を実装することを心掛けています。
皆さんも今回のようなちょっとした機能でもいいので「うちのプロジェクトで使ってるこの機能地味に便利だよ!」というものがあれば是非教えて欲しいです!