UnityでScriptableObjectを用いて設定管理
拡張エディタやImporterの設定ファイルとして、ScriptableObjectが使用できる。
tsubakit1.hateblo.jp
例えば今回は、画像ファイルをUnity上にインポートする際に、特定のフォルダ配下の場合はTrue color にしたりmip mapをOFFにするといった自動設定を行うため、下記のようなScriptableObjectを用意する。
[CreateAssetMenu(fileName = "TextureImporterConfig")] public class TextureImporterConfig : ScriptableObject, ISerializationCallbackReceiver { public List<TextureSetting> textureSettings = new List<TextureSetting> (); public Dictionary<string, TextureSetting> textureSettingsDic; public void OnAfterDeserialize() { textureSettingsDic = new Dictionary<string, TextureSetting> (); foreach (var item in textureSettings) { if (textureSettingsDic.ContainsKey(item.targetPath) == false) { textureSettingsDic.Add(item.targetPath, item); } } } public void OnBeforeSerialize() { } } [System.Serializable] public class TextureSetting { public string targetPath; public TextureImporterType importType; public bool mipmapEnabled; public TextureImporterFormat importFormat; public string packingTag; }
CreateAssetMenu属性を付随すると、Asset Menuでこのclassのオブジェクトを生成できるようになる。
ただし、ScriptableObjectはDictionary型を直接シリアライズできないので、List型で一旦保持しておき、ISerializationCallbackReceiverのOnAfterDeserialize()の中でDictionary型へ変換するようにした。
これでUnity Editor上でも設定を変更できるようになったのだが、Editor上での変更が一向にassetファイルに反映されなかった。
調べてみると、自分で SetDirty をして変更通知をしてから asset を 保存するのが必要だった。
docs.unity3d.com
というわけで下記クラスを追加し、Editor上で Save Asset ボタンを押すと変更内容がassetファイルに反映されるようにした。
[CustomEditor(typeof(TextureImporterConfig))] public class TextureImporterConfigEditor : Editor { public override void OnInspectorGUI() { DrawDefaultInspector(); if (GUILayout.Button("Save Asset")) { TextureImporterConfig configTarget = target as TextureImporterConfig; EditorUtility.SetDirty(configTarget); AssetDatabase.SaveAssets(); } } }
UnityでFBXファイルをインポートした時のデフォルト設定を自動化
Maya等で作成した3Dモデルが含まれるFBXファイルはUnity上にドラッグ&ドロップするだけでインポートが可能だが、デフォルト設定では色々とまずいので設定を変える必要があったりする。
インポートするファイルの数がたいしたことなければ問題ないが、100を超えるような物量に毎回同じ設定変更を行うのは効率が悪いので、スクリプトで自動化する。
Unityでは、AssetPostprocessorというクラスを継承すれば、インポート時のパイプラインにフックして特定の処理を行うことができる。
docs.unity3d.com
例えば、UnityとMayaでスケールの設定が異なっているため Modelのscale sizeを1から100に変更したいような場合は OnPreprocessModel() で値を変更すればおk。
void OnPreprocessModel () { var modelImporter = assetImporter as ModelImporter; modelImporter.globalScale = 100; }
Importで生成された Materials に対して、特定のshader 割り当ておよび、パラメータ設定を行いたい場合は、OnPostprocessModel で生成されたMaterial に対して変更すればおk。
void OnPostprocessModel (GameObject gameObject) { foreach (Transform item in gameObject.transform) { if (item.gameObject.GetComponent<Renderer> () == null) { continue; } foreach (Material material in item.GetComponent<Renderer>().sharedMaterials) { // shader を変更 material.shader = Shader.Find ("HogeHogeShader"); // shader のパラメータを変更 material.SetFloat ("_HogeHogeParam", 0.1f); material.SetTexture ("_SampleCube", Resources.Load ("sample_texture") as Texture); } } }
Unity上ですでにimport済みのファイルをReimportした場合もこの処理は走るので、せっかく設定したカスタム値を上書きしないように制御する必要があるので注意。
Monodevelop ショートカットメモ
とりあえず使いそうなのメモ
コードスニペット: 予約語を入れて tab 2回
定義へジャンプ: 変数を選択して cmd + y
参照先リストアップ: cmd + shift + y
リファクタリング: Cmd + r
指定行へ移動: Cmd + L
コメント挿入: ///
矩形範囲選択: option + マウスドラッグ
ファイルのタブを左移動: cmd + shift + {
ファイルのタブを右移動: cmd + shift + }
左にインデント: cmd + {
右にインデント: cmd + }
ファイル内検索: cmd + f
複数ファイル対象検索: cmd + shift + f
ビルド: cmd + b
ファイル名検索: cmd + shift + D
Phoenixでcrud操作できるところまで
昨日に引き続き、elixir と Phoenixを軽く触ってみる。
Phoenix は default で postgreSQL を使うので、それをローカルのmacに環境構築する。
参考にしたのはこちら。qiita.com
$ brew install postgresql
$ initdb /usr/local/var/postgres -E utf8
$ postgres -D /usr/local/var/postgres
これでデータベース一覧が取得できれば成功
$ psql -l
だが、自分のmacではエラーになった。どうやらバンドルインストールされたのがあるらしく下記対応で起動できるよういなった。
$ curl -o fixBrewLionPostgresql.sh http://nextmarvel.net/blog/downloads/fixBrewLionPostgres.sh
$ chmod 777 fixBrewLionPostgresql.sh
$ ./fixBrewLionPostgresql.sh
これでおk。
.zshrc
あたりに下記の設定をしておけば
$ export PGDATA=/usr/local/var/postgres
今後は下記のコマンドで起動停止できる。
$ pg_ctl -l /usr/local/var/postgres/server.log start
$ pg_ctl -l /usr/local/var/postgres/server.log stop
今回のphoenix アプリ向けに postgresにユーザ作成
$ createuser -P -d postgres
default では password も postgresになっている。
phoenixのtestで使うDB の設定は config/test.exs に書かれている。
# Configure your database config :phoenix_training, PhoenixTraining.Repo, adapter: Ecto.Adapters.Postgres, username: "postgres", password: "postgres", database: "phoenix_training_test", hostname: "localhost", pool: Ecto.Adapters.SQL.Sandbox
以下のコマンドでデータベースが作成される。
$ mix ecto.create
データベースを確認する。
$ psql -l
phoenix_traning_devが作成されていることが確認できる。
List of databases Name | Owner | Encoding | Collate | Ctype ---------------------+----------+----------+-------------+------------- phoenix_traning_dev | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8
下記のようなコマンドを実行すると、User CRUDの各ファイルが作成される。
$ mix phoenix.gen.html User users name:string email:string bio:string number_of_pets:integer
ファイル生成後、
Add the resource to your browser scope in web/router.ex: resources "/users", UserController
とあるので、router.exに定義を追加する。
その後、
Remember to update your repository by running migrations: $ mix ecto.migrate
とあるので、migrateを実行する。
サーバを起動して、localhost:4000/users でアクセスすると User の CRUD アプリが動く。
user crud のために自動生成されたソースは下記の通り。
https://github.com/kidooom/phoenix_training/commit/336236aee52c95b2daf18ee9d80c589d862df876
elixir と phoenixを軽く触ってみる
elixir の wikipedia
Elixir (プログラミング言語) - Wikipedia
Elixir (エリクサー)は並列処理、関数型に対応した、Erlangの仮想環境(BEAM)上で動作する汎用プログラミング言語である。ElixirはErlangで実装されているため、分散システム、耐障害性、ソフトリアルタイムシステム等の機能を使用することができるが、拡張機能として、マクロを使ったメタプログラミング、そしてポリモーフィズムなどのプログラミング・パラダイムもプロトコルを介して実装されている
elixir のインストール
$ brew update
$ brew install elixir
これでok.
iex でインタラクティブシェルが立ち上がる。
$ iex
文字列の連結は + じゃなくて <> を使う。
iex(1)> "hello" + " world" ** (ArithmeticError) bad argument in arithmetic expression :erlang.+("hello", " world") iex(1)> "hello" <> " world" "hello world" iex(2)>
rubyと同様に#{}によって式展開
iex(2)> "10 + 20 = #{10+20}" "10 + 20 = 30"
リストとタプル。
リストは Linked list に対し、タプルは要素を連続したメモリ上に保存している。
リストの更新や追加に比べて、タプルの更新は要素全体をコピーして生成するのでコストが高い。
変更されないようなデータをタプルにした方がよさげ。
iex(4)> %{hoge: 100, huga: 200} %{hoge: 100, huga: 200} iex(5)> nil iex(6)> map = %{hoge: 100, huga: 200} %{hoge: 100, huga: 200} iex(7)> map.hoge 100 iex(8)> %{map | hoge: 300} %{hoge: 300, huga: 200} iex(9)> map.hoge 100 iex(10)> map = %{map | hoge: 300} %{hoge: 300, huga: 200} iex(11)> map.hoge 300 iex(12)>
実際にelixirプロジェクトを作成する。
$ mix new
で空プロジェクトが作成される。
$ mix test
でとりあえずtestが通れば問題無し。
hello world を出力する
defmodule Hello do def world do IO.puts "Hello World" end end Hello.world
defmodule Fib do def fib(0) do 0 end def fib(1) do 1 end def fib(n) do fib(n-1)+fib(n-2) end end IO.puts Fib.fib(10)
Railsライクな web framework の Phoenixもとりあえず動かしてみる。
install
$ mix archive install phoenix
new project
$ mix phoenix.new .
launch
$ mix phoenix.server
これで、localhost:4000 でアクセスできる。
ひな形プロジェクトに対し、/hello ページを追加する。
変更したコードは下記の通り。
https://github.com/kidooom/phoenix_training/commit/801f9039014d4d629dafbf5772826ff73140ebbe
これで、localhost:4000/hello
で動く。簡単。
gruntでjshintとjscsのlintをタスク化
jshintのチェックルールを.jshintrcに、jscsのチェックルールを .jscsrc とかで用意しておき、下記をGruntfile.js に追加する。
grunt.initConfig({ jshint: { files: [ 'lib/**/*.js', 'test/**/*.js', '*.js', ], options: { jshintrc: '.jshintrc' } }, jscs: { src: [ '*.js', './**/*.js' ], options: { config: ".jscsrc", } } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks("grunt-jscs"); grunt.registerTask('lint', ['jshint', 'jscs']);
これで grunt lint を実行すれば OK.