unity study

Unityでサクッとモックを作れるようになることを目指して、基本的なテクニックを抑えていく過程を残すブログのつもりだったけど、今はただ自分のトラブルシューティングメモになってるブログ

SendMessageの謎挙動

PhotonUnityNetworkingを使っていて、OnPhotonJoinRoomFailed(object[] log) が呼ばれず、OnPhotonJoinRoomFailed()が呼ばれるという現象に遭遇し、色々と調査していたらどうもSendMessageの不思議な挙動が原因のようだ。
ちなみにUnity5.3.5f1での確認。
追記:Unity5.4.0f3でも検証したが同じ挙動

using UnityEngine;

public class SendMessageTest : MonoBehaviour
{
	void Foo()
	{
		Debug.Log("Foo() 1");
	}
	void Foo(string param)
	{
		Debug.Log("Foo() 2, " + param);
	}

	void Start()
	{
		// 当然こちらは Foo() が呼ばれる
		SendMessage("Foo", SendMessageOptions.DontRequireReceiver);
		// しかしこちらも Foo() が呼ばれる??
		SendMessage("Foo", "test", SendMessageOptions.DontRequireReceiver);
	}
}

何故か、引数付きのSendMessageも引数なしメソッドの方が呼ばれる。
SendMessageってこういう制約あるんだっけか?
で色々試してみたら

using UnityEngine;

public class Test : MonoBehaviour
{
	void Foo(string param)
	{
		Debug.Log("Foo() 2, " + param);
	}
	void Foo()
	{
		Debug.Log("Foo() 1");
	}

	void Start()
	{
		// エラーになる
		// Failed to call function Foo of class SendMessageTest
		// Calling function Foo with no parameters but the function requires 1.
		SendMessage("Foo", SendMessageOptions.DontRequireReceiver);
		// こちらは意図した通り Foo(string) が呼ばれる
		SendMessage("Foo", "test", SendMessageOptions.DontRequireReceiver);
	}
}

えー、メソッドの定義順を入れ替えると挙動が変わる!?
自分ではSendMessage()なんか全く使わんから、今までこういう挙動があること知らんかった。
というか、過去のバージョンではこういう挙動じゃなかったんじゃないかって気もする。
う〜ん、Unityのバージョン変えながら検証するの、めんどいなぁ。

UnityでiOS向けにビルドした際に、iPadPro用のAppIconが設定されない話

Unity5.2.3f1使ってて、iOS向けビルドしたものをiTunesConnectへアップしようとしたら警告が出た。
iPadPro用の167x167のAppIconが設定されてない、とのこと。
確かにUnity側のアイコン設定に、そのサイズのものがない。
まぁいずれ対応してくれるんだろうけど、毎度Xcodeに書きだした後で手動で設定するのは面倒だな。
と思って何とかならんかと探したら、ちょうどそういうことやってるのを見つけた。

クラウドクリエイティブスタジオ - 開発者ブログ: UnityでiPad Proのアイコンが自動設定されない問題を解決する

Android版のビルド時に出たエラー

どうにもAndroidManifest.xml周りで、よく分かっていないがためにビルドエラーにハマる。
とりあえずさっき、下記の方法で一つの問題は解決したのでメモ。
stackoverflow.com
Assets/Plugins/Android/res/values/version.xml を置くって話なんぞ知らんがな。
それとも本来は別の方法で解決すべき問題なのか?

XCode6から7にした時のトラブル対応メモ

XCode7にしてバイナリをiTunesConnectにアップロードしようとした際に、幾つかトラブルがあったのでどう対応したかメモを残す。
と言っても、解決した情報へのリンクだけど。

続きを読む

Unity5でGameCenterの達成項目を解除できないバグ対応

どうやらUnity5から、5.2.1時点でもまだ解決されていないバグらしい。hwks.hatenadiary.jp
とりあえず下記に従ってネイティブプラグインで解決するか。qiita.com
ところで、アプリバージョンアップタイミングから達成項目を追加する場合のテスト方法が分からない。
iTunesConnectで達成項目を追加して、Sandbox環境へログインしてもGameCenterの画面に表示されず。
LeaderBoardも同様。
ただ、どういうタイミングかは分からないのだが、ログイン/ログアウト繰り返したりしながら色々確認していたら一度だけ表示されたことがあった。
今はまた表示されない状態になってしまっていて困ったままだ。

Debug.Log()はかなり重いよ

ちゃんと計測してないんだけど、毎フレームあちこちでログ出力してるとかなりフレーム落ちる。
書き換えて周るのも面倒だなーと色々調べてたら、Debugクラスをグローバルスコープで定義して、単にDebugと書いている場合にUnityEngine.Debugではなく、自分の定義したDebugが通るようにする方法があるらしいことを発見。
なるほど、これだと既存のコードに手をつけなくて済むし良いな。
実機でチェックしてみたら劇的に動作が軽くなった。
めでたしめでたし

リリースビルド時にデバッグログ出力をしないようにするためのラッパー

Application.LoadLevel()でのエラーハンドリング

ステージ毎にシーンを分けて作っていて、そのシーンを

Application.LoadLevel("Stage" + n);

って感じで読み込んでいる。
何らかのミスでそのシーンが存在しない場合はエラーになるが、調べた感じだとうまいエラーハンドリングが見当たらない。
Exceptionをcatchできるわけでもないし、そもそもそのシーンが存在しているかどうかを調べる方法もないっぽい?
どうしたもんかなー、とぼんやり考えていて、結局こうすることにした。

IDisposable timer;

void Load()
{
    Application.LoadLevelAsync("Stage" + n);
    // x秒以内に読み込み完了しないということは、存在しないと判断する
    timer = Observable.Timer(TimeSpan.FromSeconds(x))
        .Subscribe(_ => {
            // エラーハンドリング処理
        });
}

// 読み込み先シーンから叩かせるメソッド
void OnLoaded()
{
    timer.Dispose();
}

タイマーの部分は別にコルーチンでも何でも。