太郎Work

Unityとかで困ったこと等を残しておきます

Unityで文字エスケープ変換

C#でやろうとしていたがUnityに実はあったのでメモ

http://docs.unity3d.com/Documentation/ScriptReference/WWW.UnEscapeURL.html

WebViewのjsからJSON適当に送ろうとしたらエスケープ文字で来るのでこれで簡単に変換できる

WWWは結構使っていたがこのメソッドが目に入っていなかった。

ありがとうUnity

UnityのiOSディレクトリアクセスまとめ

結構複雑で忘れてしまったのでメモ 一部間違っているかもしれません。

Documents

バックアップ対象になるセーブデータ等の重要なファイルを保存 Application.persistentDataPath

Library/Preferences

バックアップ対象になる環境設定ファイル等 ・Unityからアクセスすることは多分ない

Library/Caches

バックアップされないがアプリを終了しても消されない領域、大量の画像データとか しかし、容量不足の場合消される可能性あり。ロード時は存在しない前提で実装する Application.temporaryCachePath

tmp

バックアップされずアプリが終了したら削除される領域。一時保存ファイルとか Cachesと違い、実行中は削除されないことが保証される

Unity4.3で作成したアニメーションがLegacyと言われて動かない

Unityに標準で組み込まれているAnimationは、NGUI等の通常オブジェクトにも簡単にアニメーションが追加でき、publicなパラメータもアニメーションで来て非常に便利。

特にUnity4.3で導入されたDopeSheetのお陰で劇的に作りやすくなった。

しかし、いざGameObjectに追加しようとすると今まではAnimationComponentが自動でアタッチされていたものがAnimatorになってしまう。 確かに動くが、スクリプトからスタートとストップが弄れない! 空のStateをデフォルトにして遷移させれば動きそうだが単純に再生させたいだけなのにState管理とかやりたくない。

方法があるのかもしれないが、殆どがやっぱりAnimationの説明でAnimatorはインポートされたモデルアニメーションの説明ばかり。

そこで諦めてComponentからAnimationを追加してクリップを追加したらアニメーションが再生されず、アニメーションクリップをLegacyにしろと言われて動かない…

モデルデータならインポート設定にLegacy項目があるが、Unity上で作ったのだからあるわけない…

4.3以前に作成したアニメーションはやっぱり普通に動くので調べたら同じ問題で困っている質問を発見。

Create a legacy animation without a model - Unity Answers

まさに同じ状況。

EditorをForceTextにしてから、.animファイルをテキストエディタで開いて以下のように修正

m_AnimationType: 2 -> m_AnimationType: 1

これで今までどおりの使い方が出来るようになった。animationでのアクセスも問題なし。

前回のEditorWindowで<size=~>が使えなくなっている件といい、地味に4.3で謎の改変が入っている。

最終的にAnimationからAnimatorにフェードしていくらしいけどAnimationのシンプルさは残しておいてほしいなあ…

他にもなにかありそうで怖くなってきた。。。

EditorWindowでのフォントサイズ設定

今までEditorWindow上の文字サイズを変更する際は

GUILayout.Label("<size=32>Test</size>");

のように指定していたのだが、恐らくUnity4.3にしてからこの指定が出来なくなっていた。

これを使うとボタン等も簡単にフォントサイズが変更できて重宝していたが、削除されたのだろうか…

でもDebug.Logでは今までと同じように使用できるのでますますわからない。

結局普通?に

GUI.skin.label.fontSize = 32;
GUILayout.Label("Test");
GUI.skin.label.fontSize = 0;

で対応したが3行になるのは気持ち悪い。

もちろんGUIStyleを保存しておいて代入でも大丈夫だけど、なんだかなぁ…

拡張EditorでTextFieldの表示を更新する

拡張Editorを使っているとよく起きる問題。

TextFieldの文字を選択中にその中身を書き換えても文字列が更新されない(内部的には更新されている)

f:id:tarowork:20131007174507p:plain

このように上のTextFieldを選択した状態で上のTextFieldを消すと本当は”TEST2”と表示されるはずが、 ”TEST”が残ったままになる。 実際には”TEST2”が代入されているので問題はないが、他のエリアをクリックしない限り更新されないのですごく紛らわしい。

今までは気にしないようにしていたが、調べたら出てきたのでここに書いておく

http://answers.unity3d.com/questions/180659/editorgui-refresh.html

キーボードコントロールIDを初期化してフォーカスを外す感じ?

GUIUtility.keyboardControl = 0;

値を削除するタイミング等でこの一文を入れておけば想定した挙動になる。

あとこんな使い方もできた

string s = EditorGUILayout.TextField(text);
if(s != text) {
    GUIUtility.keyboardControl = 0;
}

文字を打とうとするとフォーカスが外れるので、条件による選択フィールドっぽくも出来る。

UnityEditor奥が深い・・・

NGUIではないオブジェクトをNGUIの手前に描画する方法

※追記 3.0.6あたりから仕様が変わり、細かく指定できるようになったため以下の様なことを気にする必要がなくなりました

先日、NGUIが3.0にアップデートされUIPanelの挙動が大幅に変更されていました。

そこで結構困惑したのでついでに2.0系含めてまとめておきます。

2.0系(2.7では3.0の挙動と切り替え可能)はUIPanel単位でUIWidgetを収集して描画リクエストを送る仕様になっていて、

描画順は

  1. UIPanelの中に含まれている同一Materialを持つUIWidgetのZ値を平均化
  2. Z値を平均化した上でdepth設定に基づいた頂点座標・カラー順でメッシュを生成
  3. Mobile/Particles/Alpha Blended等で描画(DrawCall 1)

この仕様は内部仕様を把握すれば、DrawCall及び描画順を完全に操作することができるので個人的には非常に扱いやすかったのですが、慣れないと特に上記の1の仕様によりかなりカオスな事になります。

例えば単一UIPanel内に以下の3つが含まれている場合大変なことになります。

Widget1(material1,z=-5f,depth0)
Widget2(material2,z=-1f,depth1)
Widget3(material1,z=5f,depth2)

マテリアルが同じなWidget1,3が1DrawCallとなり平均化されz=0にdepthが低い順に描画。

Widget2は-1fなので手前に描画され、完全に意図していない順になってしまいます。

意図したとおりにするにはWidget3(又は1)だけUIPanelを分離すればいいのですが、階層構造がかなり複雑になってきます。

そこでNGUI3.0では完全にdepthで操作できるようになり、上記のようなサンドウィッチ状の場合は自動でDrawCallを分けてくれます。Z値は気にする必要がありません。


そして本題ですが、この副作用として内部的にMaterialを複製するため、自分で作ったシェーダパラメータを変更しようとすると更新が定期的なためにカクカクしたような表示になってしまいます。

そこでUnityのQuadメッシュを使って描画しようとすると今度は表示されない!

理由は、今回からMaterialのRenderQueueをDrawCall分だけ足し算するようなっており、実質強制最前面で描画されているためです。(もしかしたら仕様がそのうち変更されるかもしれません)

この辺りのコードはUIDrawCall.cs辺りまで読まないと何が起きているか分からないのでかなり躓きました。。。

解決策として背景画像となっているWidgetのRenderQueueを引き算しておくか、メッシュのRenderQueueを大きめな値に指定しておくと想定通りの描画になりました。

細かい描画順はUIWidgetからUIDrawCallを取得してrenderQueueの値を見ることで調整できます。

この仕様を見ると本当にボタン等のインターフェースのみでNGUIを利用して背景やメインゲームは他のもので作ってねという意味合いが込められてるのかもしれません。

長くなってしまいましたが、検証に時間を掛けているわけでもないので間違っている部分がありましたらご指摘よろしくお願いします。

読みにくくて申し訳ないです。


ちなみにNGUI3.0からはdepth操作が大量に発生しますが、depthを一括変更するには UIWidgetを複数選択してNGUI->Selection->Adjust Depth ショートカットキーが設定されているので複数回押すことで全体を+10とかが可能です。

Bring To Frontを使えば最前面に持ってくることも可能 最初はこれに気づかず一個ずつ値を変更していました…

以上、慣れると便利なNGUI3.0の話でした。