C# に関する投稿を表示しています

Inspector拡張の話、MFUのコンフィグの

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

参照: http://sourceforge.jp/projects/mmd-for-unity/scm/svn/commits/149
※r149が最新のコミットでもリリースされたものでもないので間違いないようおねがいします。

 InspectorBase.cs で [CustomEditor(typeof(Object))] を引っ掛けて、PMDInspector/VMDInspector に振り分けています。もし、他のスクリプトなどでも [CustomEditor(typeof(Object))] を使っている場合は、どちらかが動かなくなってしまうので、動かさなくてもいいほうをコメントアウトするとよさそうです。
 そのために、InspectorBase.cs の先頭あたりの#defineの1行をコメントアウトするだけで、InspectorBase.cs全体を無効化することができます。

 PMDInspectorでは、PMDLoaderWindow相当の機能を提供しています。EditorGUILayoutを使ってGUIを組んで、PMDLoaderScriptに投げているだけですけれども。

 VMDInspectorも大体同様で、VMDLoaderWindow相当の機能を。こちらもEditorGUILayout使ってGUIを組み上げ、MMDLoaderScriptに投げています。


 ここまででInspectorの話はおわりまして、追加してみたMMD.Configの話を。

 作った経緯としては、何度もインポート作業をするような場合、設定が毎回リセットされててつらぽよーとかなりそうなので作りました。ほんとうは、Inspectorを使うか使わないか、の設定を載せたかったのですが、そんな高等なことはできなさそうだったので無しです...

 中身は、ScriptableObjectを継承したConfigクラスを中心に、あとは保存したいフィールドを用意しているだけです。なので、あとで設定が増えた、項目が変わった、といったことが起きても対応しやすい、と、思います。

 Inspectorで表示したり共通設定を用意したりと、のために ConfigBase というクラスを用意しており、これを継承することで折りたたみがついているGUIを形成できます。やっていることは簡単なので、継承しなくてもいいと思いますが...(決してラムダ式を使ってみたかっただけ...ではないですよ、決して。ええ、戻り値をboolにしても行けますけど、まあ、はい。)

 で、Configクラスのメンバで、このConfigBaseを継承したクラスを放り込むことで、保存、読み込み、Inspector表示、ができるわけです。

 どこかで使うときは、Config.LoadAndCreate() で、得られます。

// Sample: PMDLoaderWindow
20 public PMDLoaderWindow()
21 {
22     // デフォルトコンフィグ
23     var config = MMD.Config.LoadAndCreate();
24     shader_type = config.pmd_config.shader_type;
25     rigidFlag = config.pmd_config.rigidFlag;
26     use_mecanim = config.pmd_config.use_mecanim;
27     use_ik = config.pmd_config.use_ik;
28 }

 保存は意図的に行わなくても、多分大丈夫です。多分。
 Config.csと同じフォルダにConfig.assetとしてバイナリが保存されます。
 Config.csファイルが他にもあると、そっちに保存されてしまう可能性があります。という部分だけ注意をしていただければ....(直したい

 あとは....r149で追加したものはすべてMMD名前空間に放り込みました、というぐらいですか。
 思えば、MMD.Editors とかの名前空間の方がよかったかも..?

 他は...とくにないですかね。
 追加したInspector周りにバグがあるっぽいので、上の件と合わせて検証して直します。

enabled=false なスクリプトに対して SendMessage

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

1. 適当なオブジェクトについてるスクリプトをInspectorから無効化します。

2. スクリプト内の Start() とかその他のメソッドが走らないことを確認します。

3. 無効化したスクリプトに向けてSendMessageします

4. SendMessageで指定したメソッドが走ります

5. 楽しい!✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌

MMD for UnityのIKスクリプトのパフォーマンス計測もどきをしてたらめっちゃアラート出てきました。
ルートオブジェクトについたMMDEngineからSendMessageしてCCDIKSolver.Solveを呼び出していまるので上記に該当してたわけですね。

無効化したスクリプトに対しても何事もなくSendMessageを呼べてしまうの、んっ!? となったけどいいんでしょうかね

ともかく、髪IKがどうこうみたいな問題もありますので、一旦これでコミットしま(す|した)
(CCDIKSolver.Solveの先頭に if(!this.enabled) return; が増えただけですが)


追記

3.5のときはこの問題(?)はなかったような気がしますけど、多分気のせいですね。
その内確認するかもですが、別にやったからといって、うぅん・・・


Inspector拡張の

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

MMD for Unity (http://sourceforge.jp/projects/mmd-for-unity/) で、メニューアイテムからじゃなくてインスペクターでPMD->PrefabとVMD->Animationが出来たらいいなー、と思ってあれこれ弄って詰まったのでその話を。

 

Unity拡張ってどうやんねん!という話はしないので、http://www.slideshare.net/lucifuges/extending-the-unity-editor とかみてください。ほぼすべてなんでも出来るようになるので、ここ設定するのに使いづらいなーというポイントがあれば、改善できる可能性があります。
試しにやってみましょう。

本題です。まず必要なのは、Projectウィンドウで選択されたものをInspectorウィンドウに表示する方法です。

通常のInspector拡張であれば、

[CustomEditor(typeof(MyScript))]
public class MyScriptEditor : Editor
{
  public override void OnInspectorGUI()
  {
    EditorGUILayout.LabelField("Its MyScript");
  }
}

というような感じでできます。

 

このときのCustomEditor属性の第一引数に適当なクラス型を入れることで、そのクラス型に対する拡張になります。この場合は、MyScriptというクラス専用のエディタ拡張になります。
(実際に試していないのですが、)MyScriptを適当なオブジェクトにくっつけてやると、MyScriptEditorのインスタンスが勝手に生成されて、Inspectorには"Its MyScript"というラベルが表示されているはずです。

で、これを、Projectウィンドウにどう引っ掛けるか。
色々試した結果、typeof(UnityEngine.Object)を指定すればいいようです。
但し、これは全てのアセットを対象に出来ないようで、Unity側でInspectorが用意されていないもの、が該当になります。
(例えば、認識されない拡張子、*.unityファイル(シーンを保存したもの)、フォルダ、など)

CustomEditor属性の第二引数にtrueを指定することで、そのクラスを継承した子クラスにも適用されるらしいですが、その指定をしてもMaterialだったりTextureだったりには設定出来ませんでした。

 

さて、[CustomEditor(typeof(Object))] と指定すれば引っ掛けられることがわかったので、後はPMDLoaderWindow.csに含まれるGUI部分を移すだけで出来ました。

 

が!! 問題はここから。
別のファイルに分けたほうがよさそうなのでVMD用InspectorをPMD用Inspectorからコピーして作ったところ、VMD用Inspectorが動作しないじゃありませんか。

コンストラクタでDebug.Logをするように書いてもVMD用Inspectorのインスタンスが作られる雰囲気もないので、うーん。
推測として、CustomEditor属性の挙動が、最初に読み込まれた(実行された)方が優先されて、どうこう、みたいな。

MMD for Unityの中に閉じた問題なら、InspectorBaseみたいなものを作って、そこからPMDorVMDに振り分ければいいと思います。ですが、もし他のエディタ拡張スクリプトを導入なり自作なりで、そちらでも同様に[CustomEditor(typeof(Object))]が行われていた場合を考えるとぐぬぬ。

 

Editorを継承すると、"target"という変数が使えるようになるのですが、Unityに認識されない拡張子またはフォルダの時に、これに入ってくる値の型が、UnityEngine.DefaultAsset という内部型みたいです。
グーグル大先生に聞いてもなにひとつそれっぽい答えがでてこなかったので、それが分かっても問題解決への鍵にはなりませんでした。

 

某所になんかいい方法ないですかと質問を投げたのですが、「そもそもの話、そんなことしようとする人口数~w」という気がするのでうーん。諦める方向ですかねー…

あ、カスタムインポータを書いて、UnityにPMDが放り込まれたら自動的に読み込むというのもアリ...?
どちらにせよ、現状で特につらぽよポイントは無さそうなので、それが出来なくても、あ、はい、程度な気がしますね。

 

参考URLとか:

  • http://docs.unity3d.com/Documentation/Components/gui-ExtendingEditor.html
  • http://docs.unity3d.com/Documentation/ScriptReference/CustomEditor.CustomEditor.html
  • http://answers.unity3d.com/questions/11680/how-can-i-make-a-custom-inspector-for-this-object.html
  • http://forum.unity3d.com/threads/101654-Showing-Unknown-Extensions-in-the-Inspector

 
 

そうだそうだ、「Materials」「Materials 1」「Materials 2」「Materials 3」....と増え続けていくバグは直ったので、r143でコミットしました。

Unite Japan 2013 Day1の

この記事は公開されてから1年以上経過しており、情報が古い可能性があります。

と!いうわけで、Unite Japan 2013 Day1へと行って来ました。
だって学生の早割が3kというので、これは行かなきゃと…

(Uniteってなんぞやという方 -> http://japan.unity3d.com/unite/ )

そこで聞いてきた、メモしてきた話を思い出しつつ補完しつつ書きました。
英語での講演もあったので若干解釈がことなる部分があるかもしれませんが、
そこは後日公開される資料であったり、他の方のブログ記事やメディア記事などを参照していただければと思います。

"書いちゃまずい系のもの"はとくに無かったかと思います。
もしあったのであれば申し訳ありません。すぐに消します。

◆ 基調講演
GDCに出てきているゲームの層にインディーズ系が増えてきていること。
5年前は難しかった無名少人数チームで壮大なゲームを作るのが今では可能なこと。
Unityはそれを実現するツールとして優秀なこと。

REPUBLIQUEおもしろそう!楽しみにしています!!

République

 

◆ "Unity for Wii-U"とWii-Uでのゲーム開発

今普及しているUnityとは別物にとして、"Unity for Wii-U"として別途用意されるようです(auのSkypeみたいなアレ)
SDKの都合からか、OSはWindows専用だそうです。
また、リリーススケジュールとしては、通常のUnityと同期して行い、例外的に追加機能が先に入ったり、ということもあるようです。

Wii-U向けのビルドは至って簡単で、ビルドセッティングのウィンドウからWii-Uを選択するだけ。
Windows/iOS/Androidとか書いてあるあの枠にWii-Uの項目が追加されます。

ビルドが完了すると、転送用のバッチファイルとROMデータが生成されるようです。
そのバッチファイルを起動すれば、何かしらの方法で接続している開発用の実機に転送され、実機テストができるとのこと。

Wii-Uといえば、ディスプレイのついたゲームパッドですが、そちらへの対応も簡単にできるようです。
その方法は、カメラを追加して、追加された項目である出力ターゲットをゲームパッドにするだけ。
実際にデモとしてAngryBots(Unityについてくるサンプルプロジェクト)にカメラを1つ追加して、ゲームパッドに3人称視点を出す、ということをやっていました。

Wii-Uの機能として用意されている、フレンド/アカウント/ストアなどへのアクセスは、C/C++のネイティブプラグインを導入することにより可能になるとのこと。

そして、開発者登録をすればUnityのProライセンスが無くとも、無償で全ての機能が利用できるということでした。

ただし!
残念なことに、日本からは個人での開発者登録はできないとのこと。。

 

◆ Nintendo Web Framework のご紹介

Webkitベースに作られた、Wii-U向けアプリケーションを最近流行りのHTML5で作れるフレームワークだそうです。
イメージ的には、PhoneGapとかTitaniumとか、それのWii-U版といったところでしょうか。

フレームワークの方でJavaScriptが拡張されており、Wii-U向けの各種命令郡が使用できるようです。
例えば、ゲームパッドとTVと違う画面を出力したり、ゲームパッドの傾きや振動を取得したり、フレンドやアカウント機能を使用したり....

デモでは、既存のWebページ(動画リストがあって、選択すると再生する)をWii-U向けにビルドしていました。
その時の特徴として、既存コードには一切の手を加えていないというところです。
既存コードにはjQueryやvideoタグなどが含まれていますが、その辺りをうまいことやってくれるようです。
(裏はWebkitが動いているようなので当たり前っちゃあ当たり前っぽい気も)

もう一つのデモとして、同じようにWebページとして作られたゲームがありました。
こちらは、Wii-Uでできることの総集編のようになっており、前述の拡張されたJavaScriptがフルに活かされているようです。
またこのデモはフレームワーク付属のサンプルのようになっており、ソースコードの至るところにコメントがしっかりと付いているとのことです。

最後のデモにベンチマークが出てましたが、これはどうにも比較対象がないのでなんとも。
700くらいのスプライトがでてるけど60fps維持できてますねー、というものでした。

そしてこれまた残念なことに、日本からは個人での開発者登録はできないとのこと。

 

◆ シリアライズ徹底解説

まずなぜシリアライズを行うか。
これはプレイデータの保存やエディタの状態を保存するために行う必要があります。
ここでは、エディタ内に絞った形で講演していました。

・プロジェクトの読み込み
・スクリプトのコンパイル
・ゲームのスタート、ストップ
といったタイミングでシリアライズが行われます。

適当なエディタウィンドウを作って適当にいじって、ゲームのスタート・ストップと行うと、
そのウィンドウ内のデータがシリアライズされてないと吹っ飛びます。

 

intとかfloatとかビルトインの場合は、publicにしたり、privateでもSerializeFieldアトリビュートをつけることで解決します。
自作クラスの場合は、クラス自体にSerializableアトリビュートを付ける必要があります。
この2点を守ればデータのシリアライズが行われます。

また、structsはシリアライズがされないので、シリアライズしたい構造体があるのであれば、クラス化しましょう。

 

ここでシリアライズの問題点として、クラスを参照する場合がでてきます。
同じインスタンスを参照する変数を2つ用意してシリアライズしようとすると、片方しか反映されないとのことです。
なぜならば、それらは別にシリアライズされてしまうからです。

この問題の解決には、ScriptbleObjectを継承したクラスにする必要があります。
その際に、nullチェックやhideFragを使うことで~~

Listなどのリストの場合、簡単なクラス(親クラス型のリストに子クラスのインスタンスを入れるとか"しない")の場合はうまくいきます。

逆に、それらが含まれる場合、そのままでは上手く出来ないので、ファイルを分けて~・・・・

 

シリアライズしたデータ(ScriptableObject?)から、アセットファイルの生成も可能になります。
AssetDatabase.CreateAssetを叩くといいようです。

-----
という具合で、正直よくわからんかったので勉強してきます。。
(英語だったのでよくわからんという点を差し引いても分らなかったとこがありました...)

 

◆ Editorスクリプティング入門

なぜUnityのエディタを拡張するか?という点について、
・他人が触るときに触ってほしくない箇所を隠す
・制約がめんどうなとき("ここはこう設定!"などと定められているなど)
・見やすくする
・編集しやすく、使いやすくする
といった点があり、ここは変えたほうがイイネ、という部分はいじっていきましょう。

では、エディタを拡張が具体的に何ができるか。

 

1つに表示項目の改善があります。
これは例えば2Dゲーム開発でのTransformのZ軸を隠したり、テクスチャの設定欄に小さい窓をつけたり。
メニュー項目を追加したり、シーンビューに追加のハンドルを表示したり、などなど可能性は色々あると思います。
現に、アセットストアに出てる凄い系のものに付属しているエディタちっくなものは、そういった拡張がアツいと思います。

 

もう1つはビルド前後に処理ができるようになります。
具体例こそ示されていませんでしたが、現場の方々であれば色々と必要そうなアレコレをできるのではないかと思います。
最後に、アセット管理における移動や削除の制御ができます。
これらのファイルはこのフォルダ!など、パスに対してマッチングさせて制御するコードを書いていきます。

今回の講演では、主に1つ目。表示項目の改善などについてでした。

(なんだかメモ書きがすごい適当でまったくわからない現象が...)
まとめると、Editorクラスをちゃんと理解しましょう。理解していじらないと最悪Unity毎オチます。
理解した後に、EditorWindowだとか、CustomEditorだとか、シーン/ゲーム/プロジェクト/ヒエラルキーなどへと広げていくといいようです。

余談ですが以前、タワーディフェンス的なサムシングをやろうかと、UnitySteerを使いパス...というか座標を辿るものを使いました。
その時、座標のリストを作るときに、シーンビュー上に"座標の箇所にハンドルを設置してマウスで操作できるように"したらめっちゃ楽でした。

 

◆ Androidでコンテンツを守る方法 -Unity,Androidでのプログラムとデータの暗号化、およびハッキング対策-

セキュリティを最近勉強しはじめている私にとっては今日一番わくわくしていたものです。

まず、Unity on Androidは
Linux | Android | Unity | Mono | Script
という形で、Unityを堺にJavaVMとMonoVMが動いているような。
Unityが何をしているかというと、C#で書かれたスクリプトをJavaへとマッピングを行なっています。

 

よくある?ハックとして課金コンテンツがあります。
これは、AndroidであればGooglePlayLicenseを経由して行われます。

その仕組みは
App -> {random number} -> Google
App <- {message, signature} <- Google
という流れで行われます。
オンライン環境であれば、定期的に確認すればいいのですが、オフライン時にはユーザのデータを信用するしかありません。

また、そのメッセージ・シグネチャを保持するために、アプリのバックエンドにサーバを用意して、
同じような形式でやりとりするのが好ましいようです。

Unity上でこれを実現するには、"GooglePlayLicenseVerification"というライブラリがGithubで公開されているので、
それを使いましょう、とのことです。

 

次にアプリケーションの改竄を検出する方法です。
これは、ゲームコードの変更やチートなどの不正行為を防止するために必要です。

チェックする項目は
・アプリがデベロッパーのプライベートキーで署名がされているか
・Javaコードが正しいか(class.dex)
・Unity/Monoが正しいか(Unityランタイム郡)
・C#コードが正しいか
というものがあります。

詳しくはわからないのですが、こういったことはAndroid開発者の方々には当たり前なのでしょうか。
C#などUnity側からでもJavaのコードを実行できるのでそれで確認しましょう、という具合でした。
(AndroidJavaObjectというクラスが用意されており、それで実行できます)

 

次は暗号化です。

・ゲーム進捗
Unityでは簡単にゲーム進捗を記録できるPlayerPrefsというクラスが用意されています。
そのままではやはり簡単に編集され、メダルXXXXX枚などとされてしまう可能性があります。

これは、key/valueのペアとして記録することに加えて一工夫することで改善できます。
例えばkeyは本来のkeyのハッシュ値、valueには保存するべき値に対してTripleDESなどを掛けるなどを施します。

・スクリプト
スクリプトは暗号化、よりも難読化がメインになります。
ただし、Unityで書けるプログラムは何の変哲も無い普通のC#なので逆コンパイルなどが容易であり、難読化されていても解読は可能です。
Unityのビルドではここに対してなんの暗号化/難読化も掛けられません。
ゲームの根本に関わるような大切なソースコードであれば、自分で暗号化/難読化が必要です。

1つの案としてOpenSSLを使うものがあります。
~.dllとして外部でコンパイルし、それを暗号化して~.binに。これをアセットまたはwebに配置からの通信などを行い、ゲーム内で復号化して実行する。
読み込み部分はAssembry.Loadとリフレクションを使うことで可能になります。

やっぱりこちらもシグネチャの確認は定期的に行ったほうがよいようです。

・アセット
テクスチャやポリゴン、音声やBGMといったメディアだけでなく、上記のような暗号化されたスクリプトやデータベース、プラグインなど、すべてがアセットになります。
これはスクリプトと同様に、~.unity3dを暗号化するのが1つの方法としてあります。
具体的な読み込み方法に関しては特に触れてなかったかと思います。

 

まとめとして、
・APK自体のチェックを怠らない
・重要なコードは自分で保護する(暗号化/難読化)
・様々なアプローチを試行する
・ただしアプリケーションの保護に時間をかけ過ぎない。

この最後の点に関しては、そもそもGooglePlayにアップデートを定期的に早めにリリースするのが良いとされているようなので、
時間をしっかりかけて守るよりも、ぼちぼちな感じでアップデートの方に力をいれたほうがいいよねーみたいな具合でした。

 

◆ モバイル向けShuriken活用法

(これまたメモが凄いメモの役割を果たしていなかったのでさっくりと....)

1.本当にパーティクルが必要か
それはアニメーションテクスチャで出来ないのか。
もっとよい表現方法はないか。

2.そのパーティクルはどう構成されているか
例えば爆発なら火と煙と破片と根本と、4つ?いやいや2つでいけるのでは?
1つのパーティクルに内包されるパーティクルはすべて同じ力を加えなくてはいけない。=> コピペで色やテクスチャのみを変える

3.どのようにパーティクルは流れていくのか
EmitSharpは使わない!Speedも使わない!
-> 表現力が乏しい

ForceとVelocityのカーブを調整して表現する。
このとき、キーフレを追加して、曲線を自由自在に操ることができる。
基本的にはVelocityを使い、力が必要な場合(ex.爆発)でForceを使う

4.パーティクルと一緒にマテリアルを作る
炎のパーティクルを作るなら、火・煙のマテリアルを作りながら、適用しながら。

// 残りはパーティクル作成デモのような形でちょいちょい部分部分の説明があったかと思います。

 


長くなってしまいましたが、Unite Japan 2013 Day1で参加した講演はこのような具合でした。

Wii-UのAngryBotsが企業ブースに置いてありましたが、
まったく触れてなかったので、Day2で触ってみたいと思います。