かつて代官山らへんで働いてたengineerのUnityブログ

サーバサイドやってきたエンジニアがUnityとか触って遊ぶだけのブログ

Unityエディタ拡張でシーン内のオブジェクトに関連付けられたコンポーネント内の変数を取得する

タイトルめっちゃ長い

シーン内の変数一覧が欲しくなったのでエディタ拡張から取得出来ないか頑張ってみました
本当は値も欲しかったのだけど、今回とれたのは変数名一覧だけでした

using UnityEngine;
using UnityEditor;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;


public class EditorExWindow : EditorWindow
{


	[MenuItem("Window/EditorEx")]
	static void Open()
	{
		EditorWindow.GetWindow<EditorExWindow>( "EditorEx" );
	}

	string textArea = "";

	void OnGUI()
	{
		if( GUILayout.Button("Caputure") )
		 	Find();
		GUILayout.Label( "TextArea" );
		textArea = GUILayout.TextArea( textArea );

	}

	 

	private void Find (){
		// TextAreaクリア
		textArea = "";

		List<GameObject> AllObjects =  new List<GameObject>();
		List<MonoBehaviour> allMonobehaviourList = new List<MonoBehaviour> ();

		foreach (GameObject obj in UnityEngine.Resources.FindObjectsOfTypeAll(typeof(GameObject)))
		{
			// アセットからパスを取得.シーン上に存在するオブジェクトの場合,シーンファイル(.unity)のパスを取得.
			string path = AssetDatabase.GetAssetOrScenePath(obj);
			// シーン上に存在するオブジェクトかどうか文字列で判定.
			bool isScene = path.Contains(".unity");
			// シーン上に存在するオブジェクトならば処理.
			if (isScene)
			{
				AllObjects.Add (obj);
			}
		}

		allMonobehaviourList.AddRange (GetComponentsInList<MonoBehaviour> (AllObjects));

		foreach(var componentData in allMonobehaviourList){
			foreach(MemberInfo mi in componentData.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance |  BindingFlags.DeclaredOnly)){
				textArea += mi.Name + "\n";
			}
		}
	}

	public static IEnumerable<T> GetComponentsInList<T> (IEnumerable<GameObject> gameObjects ) where T : Component 
	{
		var componentList = new List<T> ();

		foreach (var obj in gameObjects) {
			var components = obj.GetComponents<T> ();
			if (components != null) {
				foreach(var component in components){
					componentList.Add (component);
				}
			}
		}
		return componentList;
	}
}

変数名が取れたんだから中身も取れると思うんだけど...
もうちょっとがんばろう


github.com

Unityエディタ拡張を作ってみる

やっとUnityの記事が書ける
エディタ拡張だけど

というわけでエディタ拡張のサンプルを作ってみました
元々サーバの方の人間なのでUnityって作業の自動化とか効率化ってどうやってるのっていうのはずっと気になってました

参考にさせてもらったのはケットシーウェアさんのサイト
【エディタ拡張徹底解説】初級編①:ウィンドウを自作してみよう【Unity】 | ケットシーウェア


僕がなに書いても意味ないくらい超丁寧でわかりやすかったです
それで出来たのがこちら

using UnityEngine;
using UnityEditor;
using System.Collections;

public class EditorExWindow : EditorWindow
{
	[MenuItem("Window/EditorEx")]
	static void Open()
	{
		EditorWindow.GetWindow<EditorExWindow>( "EditorEx" );
	}

	string textArea = "";

	void OnGUI()
	{
		if( GUILayout.Button("Find  Objects") )
		 	Find();
		GUILayout.Label( "TextArea" );
		textArea = GUILayout.TextArea( textArea );

	}

	private void Find (){
		// TextAreaクリア
		textArea = "";
		foreach (GameObject obj in UnityEngine.Resources.FindObjectsOfTypeAll(typeof(GameObject)))
		{
			// アセットからパスを取得.シーン上に存在するオブジェクトの場合,シーンファイル(.unity)のパスを取得.
			string path = AssetDatabase.GetAssetOrScenePath(obj);
			// シーン上に存在するオブジェクトかどうか文字列で判定.
			bool isScene = path.Contains(".unity");
			// シーン上に存在するオブジェクトならば処理.
			if (isScene)
			{
				// GameObjectの名前を表示.
				Debug.Log(obj.name);
				textArea += obj.name + "\n";
			}
		}
	}
}


Unityエディタから表示してみるとこんな感じになります
f:id:chroske:20150608202732p:plain

やってることは
①Findボタンが押されたらイベント実行
②イベントからResources.FindObjectsOfTypeAllでシーン内のオブジェクトを全て取得
③TextAreaに書き込む
これだけです

これで何が出来るってわけでもないけど
なにが出来そうっていうのはなんとなくわかったのではなかろうか
もちろん取得だけじゃなくて操作や生成も行える
すばらしい、夢が広がるね
なにか実用的なものができたらまた載せようと思う

はてなブログでのソースコードの載せ方

ネタがないのではてなブログのことでも

前までさくらVPSを借りたりraspberry piを自宅サーバにしたりしてwordpressを動かしてたのですが
さくらVPSはテラリアのゲームサーバに使い始め、raspberry piは夏だし燃えたらこわいので(燃えないと思うけど)こっちに引っ越してきた
こっち来てまず調べたのはブログへのソースコードの載せ方、一応技術ブログなので


>||
ここにソースコードを書くよ
||<


こんなかんじで「>||」「||<」で囲むと中がエスケープになりなんでも書き放題です
ちなみにこれははてな記法での書き方になっており、デフォルトでは「見たままモード」になっているので、はてなブログの設定の編集モードのところから変えてやりましょう
C#に特化した見た目にしたい場合は


>|cs|
ここにC#ソースコードを書くよ
||<


こんな感じです
多分他の言語もあるんじゃないかな




ちなみにエスケープに使われてる「>||」「||<」はどうやってエスケープしてんのよって話ですが、別にわざわざ「見たままモード」にしてるわけではなくASCIIコードをそのまま貼り付けてます
じゃあASCIIコードで書いたエスケープはエスケープできんのか?!って話ですが
やってみた感じできませんでした。
まあ使わないしいっか

svnのコミットを取り消そう

またsvnについて
どうせならUnityの記事が書きたい
せめてgitの...
1日1記事、いつまで続くか


svnで間違ったファイルをコミットしちゃうこと結構あると思う
自分もよく親ファイルからまとめてコミットこのやろー!してしまうので結構しくじる
しかしあわてることなかれ
svnは特定のcommitまで戻すことが出来る(なぜかcommitじゃなくてリビジョンと言うらしい)

svn log -l 10

最近のログ10件を取得
だいたい戻すなら最近のコミットになるかと
ここでリビジョンの番号を確認して控えておく

svn update

一応updateしとく

svn merge -r 1000:999 .

1000が戻すべき現在のリビジョン番号
999が戻し先リビジョン番号
日本語難しい

svn commit -m "リビジョン巻き戻し[1000:999]"

ローカルが前の状態に戻るのでそれをcommit
戻したリビジョン番号を書いておくといいかも





※2015/7/8追記
svn merge -r 1000:999 .に続けてファイルパスを指定すると特定のファイルだけを巻き戻すことが出来る

svn merge -r 1000:999 ./Asset/Plugins/hoge.cs

同じファイルさえ変更されていなければ、自分のあとにコミットされてしまったとしても巻き戻すことが出来る

F**kin svn!!!

svn updateを行おうとしたらsvnがゴネ始めた

svn: run 'svn cleanup' to remove locks (type 'svn help cleanup' for details)


なるほどなるほど
svn cleanupをご所望か

svn: E000022: Can't convert string from native encoding to 'UTF-8':
svn: E000022: ../../Confidential/Doc/?\232?\168?\173?\229?\174?\154?\230?\184?\136?\227?\129?\191plist/ABCDE.plist

wtf!!?
恐らく日本語名のファイルにお怒りなのだろう
うちはWindowsMac/Linuxの開発者が混合しているのでそうなるのもわかる

Can't convert string from native encoding to 'UTF-8':でググってみるとこのブログに辿り着いた

オデの日記@WEB系: svnでどんなに頑張っても"can't convert string from 'utf-8' to native encoding"エラーが治らない


なんか同じ状態っぽい
とりあえず脳死状態で上から打ち込んでみる
が、上手くいかない


やはり脳死プレイはよくないな...
上からなにをやっているのか考えながら進めていく

export LC_CTYPE=ja_JP.utf8

ロケールをja_JP.utf8に設定している
これをすると日本語の文字化けが防げたりするが、内部でなにがどうなって化けないようになるのかはよくわからない
たいていの場合はこれでどうにかなるそうです、ならなかったけど

locale -a | grep ja
localedef -f UTF-8 -i ja_JP ja_JP.utf8

そもそもロケールが存在しない場合があるらしい
locale -a | grep jaで一覧を表示してlocaledef -f UTF-8 -i ja_JP ja_JP.utf8で追加してやる
一覧に普通にあったのでここはスルー

export LC_ALL=ja_JP.utf8

恐らくすべての環境のロケールを一択で設定する項目にja_JP.utf8を設定している
すでに最終手段感が出ている
しかしこれも効果なしでLC_CTYPEと設定がかぶってるよと警告が出てしまう始末

export LC_CTYPE=ja_JP.sjis

ロケールをja_JP.sjisに設定している
つまり日本語特化型に設定しているということ
他の部分で色々不都合が生じそうだが...

これでもダメか...と思われたがどうやら前に設定したLC_ALL=ja_JP.utf8が優先されてしまっていただけでexport LC_ALL=してやることでsvn cleanupすることが出来た。なんてこった。

自分の打ってるコマンドくらい100%理解していなければいけないと実感させられたのである



thank you svn!!