UnityのInputにおけるXbox 360 Controllerの割当て(Mac)

最近は有り難いことにXbox 360 ControllerのMac用ドライバーを作ってくれている方がおり、Macでも360のゲームパッドを使って遊ぶことが出来ます。

http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver

これをUnityに繋ぐとボタン入力をサクッと取ることが出来る訳ですが、ボタン・スティックの割当をあらためて調べたので備忘録代わりに書いておきます。

アナログ入力:

デジタル入力:

InputManagerのデフォルトで設定されてるjoystick button 0-3 が割当なしになっていたのでボタン類がそのままだと何も反応せず大分焦りました(^^;;

値の取得に関しては、デジタル入力に関しては Input.GetButton()、アナログ入力に関しては Input.GetAxis()を使って取得します。

@2ヶ月前・リアクション3件

Unityのオンラインドキュメントの日本語/英語を切り替えるブックマークレット

Unityの日本語オンラインドキュメントがわりかし整備されてきました。

Unityオンラインドキュメント(日本語)

Unityオンラインドキュメント(英語)


さまざまな有志の方々の協力によって、日本語のドキュメントはいい感じになってきたと思いますが、読んでみてちょっと分からないところなどがあるときに、手軽に英語の同じページを参照出来ると便利です。
そこで、2つのドキュメントを気軽に行き来できるようにするためのブックマークレットを作ってみました。

Unityのオンラインドキュメントの日本語/英語を切り替えるブックマークレット:


上記のリンクをブックマークツールバーにドラッグ&ドロップすると使えます。オンラインドキュメント以外のところを開いているときに押すと、オンラインドキュメント(日本語)のトップに飛びます。

ソース(上記リンクが上手く行かないときのために):

javascript:var%20x="//docs.unity3d.com/";var%20y="//docs-jp.unity3d.com/";var%20i=location.href;var%20eidx=i.toLowerCase().indexOf(x);var%20jidx=i.toLowerCase().indexOf(y);if(eidx>-1){location.href=y+i.slice(eidx+x.length);}else%20if(jidx>-1){location.href=x+i.slice(jidx+y.length);}else{location.href="http://docs-jp.unity3d.com/"} 

上記をコピーして新しく作ったブックマークのURLに貼り付けると機能するはずです。

@4ヶ月前・リアクション2件
ススキノの歓楽街。裏道に残るこういう雰囲気、いいよね (Instagramで撮影)

ススキノの歓楽街。裏道に残るこういう雰囲気、いいよね (Instagramで撮影)

@11ヶ月前

実行中にスクリプトを編集したときのNullReferenceExceptionを回避する

Unityでスクリプトを作成していると、実行中にスクリプトを編集して、Unityエディターに戻ったときに、NullReferenceExceptionが発生してプログラムを続行出来なくなることがあります。これを回避するにはどうすればよいでしょうか。

スクリプトの編集でNullReferenceExceptionが発生する状況を見てみると、クラスの持っている変数(static変数)に対して発生していることがわかります。

 // IndicatorElement.js
#pragma strict 
var index = 0; 
private var meter = 0.0; 
public static var analyzer : AudioAnalyzer; 
function Update() { 
    meter = Mathf.Max(meter * Mathf.Exp(-10 * Time.deltaTime), analyzer.bandLevels[index]);
    transform.localScale.y = meter * 40.0; 
} 


このコードを含むプロジェクトで、プロジェクト内のどこかのスクリプト(このスクリプトに限らない)を更新すると、以下のようなエラーが大量に出て、プログラムを再実行しないと続行出来なくなります。

image

この例では、スクリプトを編集して戻ってくると、値が設定されていたはずのanalyzerがnullになってしまっています。

なぜこうなるかを理解するには、Unityがプロジェクト実行中にスクリプトを書き換える機能をどう実現しているかを(半分くらい推測ですが)考えてみたいと思います。おそらく、中でこんなことをしています。

image

Typeインスタンスの生成は実際には最後のデシリアライズをする過程で同時に生成されていくのだとは思いますが、ここでは単純化のために分けて書いています(どっちにしろ想像の範囲内なので・・)。
シーン上(Hierarchy上)のインスタンスはすべて捕捉されているので、すべて保存&デシリアライズが行われます。しかし、スクリプトは全て再コンパイルされていて、新しいアセンブリを使ってインスタンスが復元されるので、Typeインスタンスは新しいものが利用されます
わかりにくいかもしれないので図にしてみます。

まず、スクリプト編集前の状態はこんな感じです。

image


このシーンには、複数のIndicatorElementのインスタンスと一つのAudioAnalyzerインスタンスがあるとします。IndicatorElementもAudioAnalyzerもMonoBehaviorを継承している、なにがしかのGameObjectに張り付いているコンポーネントだと思って下さい。

ここで、AudioAnalyzerかIndicatorElementのスクリプトを編集して、Unityエディタに戻ってくると、

  1. 全てのスクリプトがコンパイルされて新しいアセンブリが生成され、
  2. シーン上の全てのオブジェクトがシリアライズされてシーンのインスタンス情報とそのプロパティが保存され、
  3. 1で作った新しいアセンブリを使って、2の情報を元に全てのインスタンスを生成し、
  4. 2で作ったシリアライズ情報を元に、保存されているすべてのプロパティを復元(デシリアライズ)

図にすると

image


こうなって、
image

こうなる感じです。

つまり、アセンブリが変わってしまっている以上static変数を持っているTypeインスタンス*1も新しいものになってしまっているのですが、この部分はシーンデータから復元されないので、nullのままになっていて、結果analyzerにアクセスするとNullReferenceExceptionが発生する訳です。もしかすると古いアセンブリはアンロードされてしまっていて、情報は残ってないかもしれません。そうだとすると、static変数を復帰させようにもやりようがないというのも分かる話です。

さて、ではNullReferenceExceptionを回避するには、どうすればいいのでしょうか。

  1. static変数の先のオブジェクトも、シーンの管理対象にする(ScriptableObjectやMonoBehaviourの継承クラスにしておく)
  2. static変数がnullになったら、GameObject.FindObjectOfType()を使ってシーンから探してくる

この二つを行うようにすれば、NullReferenceExceptionを回避することができます。乱暴な例ですが、下記のように実装することで実現出来ます。

 // IndicatorElement.js
var index = 0;
private var meter = 0.0;
public static var analyzer : AudioAnalyzer;
static function GetAnalyzer() {
	if(analyzer == null) {
		analyzer = GameObject.FindObjectOfType(AudioAnalyzer);
	}
	return analyzer;
}
function Update() {
	meter = Mathf.Max(meter * Mathf.Exp(-10 * Time.deltaTime), GetAnalyzer().bandLevels[index]);
	transform.localScale.y = meter * 40.0;
}

実行中にスクリプトが編集出来るとやはり便利なので、できなくなったという人はすこし手を加えてみてはどうでしょうか。

*1: ここでは、分かりやすくするためにTypeインスタンスが持っていることにして説明していますが、実際にはstatic変数への参照をどのように管理しているかはVMの実装依存の領域だそうです。

参考情報:

@3ヶ月前・リアクション1件

BBEditでJSONをフォーマットする

JSON Pretty Print formatting in BBEdit

http://crisp.tumblr.com/post/2574967567/json-pretty-print-formatting-in-bbedit

BBEdit 10以降ではブログ先のスクリプトをコピペしてPrettyJSON.pyを作成し、 “~/Library/Application Support/BBEdit/Text Filters” に入れる。すると、Edit>Text Filters にPretyJSON という選択肢が出てくるので、これを適用。

バッチリ綺麗になりました!Thx!

@6ヶ月前・リアクション2件