Visual StudioをMicrosoft Azure管理ツールとして使う
AWSやMicrosoft Azureの両者共に言えることなんですがWebの管理画面の使い勝手がそれほど良くはありません。例えばストレージやキューにデータを手動で置いたり削除したりするのはとても面倒です。Azureのキューに至ってはデータを閲覧できません。
Microsoft Azureを使っていてWindowsを持っているなら、Visual Studioが管理ツールとして使えます。例えばファイルストレージならこんなふうに見たりアップロードしたりできるわけです。
(Browsing and Managing Storage Resources with Server Explorerより)
というわけで早速私も実践してみました
あらかじめインストールしておいたVisual Studio 2013を起動し、サーバーエクスプローラを開きます。すると、、、
ない!!
ストレージも仮想マシンも「Azure」の下にありません。さっきの画像は一体なんだったのか。
よく調べていくと、AzureのSDKを追加インストールしなければいけないということがわかりました。↓のページから、Visual Studioのバージョンに対応したものをダウンロードしインストールしましょう。
Download Azure SDKs and Tools | Azure
無事にできました
Visual Studioを起動すると、、、できてる!
ストレージ管理
ファイルやキューの管理ができるようになりました。Webのインターフェースよりは断然使いやすそうです。
仮想マシン管理
仮想マシンの設定変更やシャットダウン、イメージの作成などが可能のようです。
仮想マシンの作成もOK!!
Azureを使うならVisual Studioからの管理がオススメです。
Unity Cloud BuildでUnityのビルドやバイナリ配布を自動化しよう
お金を払ってProライセンスを使っている人に朗報です。Unityがベータ版として提供する Unity - Cloud Build を使えば、いわゆる継続的インテグレーション(CI)が簡単に行えます。
弊社では「レポジトリの特定のブランチを監視させ、変更があったらiOS版とAndroid版をビルドして配布」という用途のために使用してします。
そうです、TestFlightのような配布機能まで備えており大変便利です。ProユーザーはJenkinsやTestFlightを個別にセットアップする必要がなくなります。
下準備
iOS用ビルドやAndroid用ビルドをするためにはいくつか下準備が必要となります。
identifierの用意
Bundle ID的なものを用意しておく必要があります。iOS Developer CenterでApp IDを作ったりしてiOS向け、Android向けの設定を終えます。あとで必要になるのでビルド用のProvisioning等を用意しておきましょう。つまるところ、手元でビルドするのに必要な準備と大差はないと思います。
手作業による変更が要らない状態に
Xcodeプロジェクトの書き出し後に手作業による設定変更をしている人もいるかもしれませんが、Cloud Buildではそのようなことはできません。プロジェクトの書き出しからビルドまでを完全に自動で通す必要があります。
そこで前回のエントリーUnityでのXcode設定をUnityEditorのスクリプトだけで自動化する につながります。Xcode のプロジェクトを変更する必要がある人はこちらを参考に色々頑張ってみましょう。
Cloud Buildでプロジェクトの設定
Unity - Cloud Build ←まずここからProライセンスを支払っているアカウントでログインし、上部ナビゲーションバーからAdd New
を選択します。
するとこのような画面になるので、監視したいリポジトリのURLを入力しましょう。弊社ではbitbucketを利用しているのでgit@bitbucket:account/repository.git
のようになりました。
次にSSHキーを設定します。この画面で詳しく案内してくれるので特に問題はないでしょう。
どのブランチを監視するのかを決めます。ここで指定したブランチにあるコードを使ってビルドしてくれるようになります。
これまでに設定した内容の確認と、ビルドするプラットフォームを選びます。iOSとAndroidを有効にし、必要であればAuto-build
にもチェックしておきましょう。Auto-build
が有効になっていると、ブランチに対する変更を検知して自動的にビルド→配布を行ってくれます。
予め用意しておいたBundle IDやProvisioning Profile、p12などを入力、アップロードします。
長かったですね。これで自動ビルドのための準備ができました。
次のステップに進むと最初のビルドがスタートします。ビルド完了後は配布URL付きのメールが来ます。
運用例
弊社ではCloud Buildが監視するためだけのブランチを作成しており、区切りのいいタイミングでメインブランチからプルリクエストを作成してビルド用ブランチを更新するようにしています。BitbucketのWebインターフェースでプルリクエストを作ってマージするだけで自動的に実行可能なバイナリを作ってくれるわけです。
もっというとこのプルリクエスト作成→マージの部分はChatOpsな感じで動くようにしています。細かい話は後日書くかもしれませんが、予め登録しておいた命令をbot hogehoge
のような感じでSlackに投稿すると、あとはBotが勝手にマージしてくれるようにしています。
「そろそろメンバー全員に見せておくか」と思ったらSlackにちょっと書くだけで配布まで完了できるわけです。革命的ですね。
UnityでのXcode設定をUnityEditorのスクリプトだけで自動化する
Unityが出力したiOS用プロジェクトの手動編集をなんとかしたいと考えていたら、同じような人がやはり多いようでいろいろな方法がブログエントリで紹介されていました。
- UnityでXcodeのプロジェクト設定を自動化したい(c#でPostProcessBuildを書く場合) - Qiita
- A-Liaison BLOG: Unity の PostprocessBuildPlayer を使って Weak Framework を追加する方法
調べた感じではCodeEditor-for-Unity
やxcodeproj
というRubyのgemを使う方法が多くみられました。前者のライブラリは最近はメンテされていないようですし、後者の場合Rubyが必要になるということで広く導入しにくい(関係者全員にxcodeproj gem入れろとはいえない)ので別の方法がない限りできないかなーと思っていたら、なんとBitbucketにリポジトリを発見しました。
Unity-Technologies / XcodeAPI — Bitbucket https://bitbucket.org/Unity-Technologies/xcodeapi
Unity-Technologiesというアカウント名から察するに公式のツールだと考えて良さそうです。
このコードを使ってXcodeプロジェクト出力後にフレームワークを追加したり設定を変更するような処理を書いてみようと思います。
なお他の手段でできることがこのXcodeAPI
ではまだできないということがあるかもしれないのでその点は注意してください。
導入
準備はほとんど要らなくて、リポジトリからダウンロードしたファイルをUnityのプロジェクト内、Assets
以下の好きなところに突っ込んでおけば大丈夫です。
ビルド後の処理を書く
Assets/Editor
あたりのディレクトリに、例えばModifyXcodeProject.cs
という感じのスクリプトを配置します。
using UnityEngine; using UnityEditor; using UnityEditor.Callbacks; using UnityEditor.iOS.Xcode; // ←さっきいれたXcodeAPI using System.Collections; using System.IO; public class XcodeProjectMod : MonoBehaviour { // ちょっとしたユーティリティ関数(http://goo.gl/fzYig8を参考) internal static void CopyAndReplaceDirectory(string srcPath, string dstPath) { if (Directory.Exists(dstPath)) Directory.Delete(dstPath); if (File.Exists(dstPath)) File.Delete(dstPath); Directory.CreateDirectory(dstPath); foreach (var file in Directory.GetFiles(srcPath)) File.Copy(file, Path.Combine(dstPath, Path.GetFileName(file))); foreach (var dir in Directory.GetDirectories(srcPath)) CopyAndReplaceDirectory(dir, Path.Combine(dstPath, Path.GetFileName(dir))); } [PostProcessBuild] public static void OnPostprocessBuild(BuildTarget buildTarget, string path) { if (buildTarget == BuildTarget.iPhone) { string projPath = PBXProject.GetPBXProjectPath(path); PBXProject proj = new PBXProject(); proj.ReadFromString(File.ReadAllText(projPath)); string target = proj.TargetGuidByName("Unity-iPhone"); // システムのフレームワークを追加 proj.AddFrameworkToProject(target, "AssetsLibrary.framework", false); // 自前のフレームワークを追加 CopyAndReplaceDirectory("Assets/Lib/mylib.framework", Path.Combine(path, "Frameworks/mylib.framework")); proj.AddFileToBuild(target, proj.AddFile("Frameworks/mylib.framework", "Frameworks/mylib.framework", PBXSourceTree.Source)); // ファイルを追加 var fileName = "my_file.xml"; var filePath = Path.Combine("Assets/Lib", fileName); File.Copy(filePath, Path.Combine(path, fileName)); proj.AddFileToBuild(target, proj.AddFile(fileName, fileName, PBXSourceTree.Source)); // Yosemiteでipaが書き出せないエラーに対応するための設定 proj.SetBuildProperty(target, "CODE_SIGN_RESOURCE_RULES_PATH", "$(SDKROOT)/ResourceRules.plist"); // フレームワークの検索パスを設定・追加 proj.SetBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(inherited)"); proj.AddBuildProperty(target, "FRAMEWORK_SEARCH_PATHS", "$(PROJECT_DIR)/Frameworks"); // 書き出し File.WriteAllText(projPath, proj.WriteToString()); } } }
iOSプロジェクト書き出し後に[PostProcessBuild]
属性を付けたメソッドが呼ばれます。そこでXcodeプロジェクトの本体である.pbxproj
を編集するためのコードを書けばOKです。
上のコードでは
これらのことをやっています。
このコードもXcodeAPIもソース管理に入れてしまえば誰でも使うことができるので他の方法よりも良いかもしれません。
Rails+Sidetiqでお手軽定時処理 on Heroku(無料!)
Railsで定時処理をやろうと思って色々トライしました。Sidekiq+Sidetiqを使ってHerokuの無料分で動作させることができたのでその手順を紹介します。
Railsでの非同期処理
古いものから新しいものまでいろいろ選択肢があります。
そしてRails4.2で実装される(された)ActiveJobというアダプタのような仕組みがあります。
以前開発したのアプリケーションではResqueを使っていたことと、3つのgemのなかではSidekiqが一番新しいということでSidekiqを使いました。
Sidekiqでの定時処理
本来Sidekiqは非同期処理のためのgemなので、Sidekiq単体では定期的に処理を実行するような仕組みはありません。X時間後に実行とかはありますが。定時処理をするには別の方法と組み合わせる必要があります。
例えば次の2つのに代表されるgemは単体で定時処理を実現できるgemです。Sidekiqと組み合わせなくても定時処理はできますが、定期的に呼び出す処理の中でSidekiqにジョブをエンキューするという使い方もまあ可能です。
それに対して、Sidekiqに定時実行機能を追加するgemもあります。
この中では圧倒的にGitHubスター数の多いSidetiqを使ってみることにしました。
Prerequisites
- Herokuアカウント
- Rails環境
- Redis
RedisのインストールとHerokuアカウントが必要ですが、ここは省略します。
実装していく
SidekiqとSidetiqの準備
インストール
インストールはGemfileに書くだけでOK。generateとかはありません。
gem 'sidekiq' gem 'sidetiq'
$ bundle install
設定
config/initialiers/sidekiq.rb
にこんな内容を書きます。Herokuに関わる設定がありますが、それは後述します。
Sidekiq.configure_server do |config| if Rails.env.production? if ENV['REDISCLOUD_URL'] config.redis = { url: ENV['REDISCLOUD_URL'], namespace: 'sidekiq' } end else config.redis = { url: 'redis://localhost:6379', namespace: 'sidekiq' } end end
ワーカーの定義
そしてapp/workers
ディレクトリ以下に適当なワーカーを作ります(例えばHardWorker
)。
class HardWorker include Sidekiq::Worker include Sidetiq::Schedulable recurrence backfill: true do daily end def perform puts 'Doing hard work' end end
recurrence
で頻度を指定し、perform
で処理を記述します。daily
とかmonthly
、もっと複雑な指定もOKです。
ローカルで実行
$ bundle exec rake sidekiq
と実行するとワーカープロセス立ち上がります。さっきはdaily
と書きましたが、初めてテストのときはminutely
とかにした上でperform
にも適当なputs
あたりを書いておいて確認するのが安全かも。
ここまででローカルでの実行はできました。
Web UIの追加
SidekiqはRailsアプリケーションにジョブの管理画面をマウントすることができるため、ジョブの状態を簡単に知ることができて便利です。
使うためにはまずSinatraをインストールして、routes.rb
にちょちょいと書き加えます。
gem 'sinatra', '>= 1.3.0', :require => nil
# config/routes.rb require "sidekiq/web" require "sidetiq/web" Sample::Application.routes.draw do mount Sidekiq::Web => '/sidekiq' end
これで例えばhttp://localhost:3000/sidekiq
とかで管理画面をみられます。
Herokuで実行する
Redisアドオンを追加
$ heroku addons:add rediscloud # アドオンを追加 $ heroku config:set REDIS_PROVIDER=REDISCLOUD_URL # 必要な環境変数を追加
Unicornを使う
Unicornを使ってゴニョゴニョすることで1dynoでSidekiqを実行することができます。というわけでGemfileにgem 'unicorn'
を追記します。
そして、Unicornの設定ファイルを作ります。
herokuでRailsをUnicornに乗せる設定 | Workabroad.jpを参考にした上で、Sidekiqをspawnで起動させます。
# config/unicorn.rb timeout 15 preload_app true worker_processes 3 # whatever you had in your unicorn.rb file @sidekiq_pid = nil before_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn master intercepting TERM and sending myself QUIT instead' Process.kill 'QUIT', Process.pid end defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! if ENV['RAILS_ENV'] == 'staging' # Sidekiq関連はここ!【更新あり】 @sidekiq_pid ||= spawn("bundle exec sidekiq -c 2") Rails.logger.info('Spawned sidekiq #{@sidekiq_pid}') end end after_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT' end defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end
あとはこのconfigを使って起動するようにルートにProcfile
を作成してデプロイすればOKです。
# Procfile web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
本当に使う場合はWorker Dynoを立ち上げるべきでしょうが、ちょっとした確認などのためであれば1Dynoです。無料でやってしまいましょう。
Sidetiqによる実装は本当に楽で、この記事の手順を進めるのもUnicornの設定とかを書くほうが面倒なぐらいだと思います。Sidekiq+Sidetiqいいですね。以前使っていたResque+Clockworkよりも良さそうです。
jQuery の関数をオーバーライドする方法
今回は、jQuery を使って$('#hoge').hoge()
とした時に、元のhoge
の機能に加えて追加のコードが走るようにしたいですね、というお話です。
普通の JavaScript で関数をオーバーライドする方法
こちらは JSer なら常識ですね。
var orgHoge = window.hoge; window.hoge = function() { // TODO: 事前の追加のコード var result = orgHoge.apply(this, arguments); // TODO: 事後の追加のコード return result; };
なお、このコードを見て「処理が足りてないじゃないか」と言える方は、以降の話は全く必要ないかと思います。
jQuery の関数をオーバーライドする方法
では、jQuery で$('#hoge').hoge()
とした時のhoge
はどこで定義されているかというと、$.fn.hoge
です。これまた jQueryer にとっては常識ですね。
同様に、オーバーライドしてみましょう:
var orgHoge = $.fn.hoge; $.fn.hoge = function() { // TODO: 事前の追加のコード var result = orgHoge.apply(this, arguments); // TODO: 事後の追加のコード return result; };
簡単。試しに jQuery Activity Indicator を使い、具体例を作ってみました。
こちらがオーバーライド前。
真面目に書くと面倒なので必要最低限ですが、ON ボタンを押すと枠の中がくるくる回って、OFF ボタンを押すと消えます。
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script src="jquery.activity-indicator-1.0.0.js"></script> <style> #test { width: 100px; height: 100px; border: solid red 0.25em; } </style> </head> <body> <div> <button onclick="$('#test').activity()">ON</button> <button onclick="$('#test').activity(false)">OFF</button> </div> <div id="test"></div> </body> </html>
次に、くるくるが回り始めたら枠線を灰色にして、止まったら赤に戻すようにしてみましょう。
<script> $(function(){ var activity = $.fn.activity; $.fn.activity = function(){ if (arguments[0] === false) { $(this).css('borderColor', 'red'); } else{ $(this).css('borderColor', 'gray'); } return activity.apply(this, arguments); }; }); </script>
あれ……くるくるが出ない!!
どうして出ないの?
試しにスクリプトをデバッグしてみると、次のようなメッセージが出ます:
transform 属性のパース中に予期せぬ値 translate(NaN,NaN) が見つかりました。
el.setAttributeNS(null, k, v);
……よくわからん。
とりあえず Activity Indicator のソースをよく見てみると、次のような部分がある事に気付きます。
opts = $.extend({color: $this.css('color')}, $.fn.activity.defaults, opts);
どうやら、オプションのデフォルト値を$.fn.activity.defaults
に持っていて、ユーザーが指定していないオプションがある場合にはそこから値を取っているようです。
オーバーライドした$.fn.activity
はdefaults
プロパティを持っていないので、変なところにundefined
が入って先ほどのエラーが出たものと思われます。
なので、正しくはこうやって、各種プロパティをオーバーライドした関数に付け替えてやらねばなりません:
<script> $(function(){ var activity = $.fn.activity; $.fn.activity = $.extend(function(){ if (arguments[0] === false) { $(this).css('borderColor', 'red'); } else{ $(this).css('borderColor', 'gray'); } return activity.apply(this, arguments); }, activity); }); </script>
これで、想定通りに動くようになりました。
このように関数にデフォルトプロパティを持たせる方法は、jQuery プラグインでは多用されています。
まず、こんなコードを書かなければならない事を疑うべきだとは思いますが、万が一使いたくなった場合*1には憶えておいて損はないでしょう。
jQuery 以外の JavaScript に戻って
本当は、こういった「関数に動作設定用プロパティを追加してある」というやり方は、jQuery に限らず出てきます。
ですので最初の、jQuery ではない JavaScript のコードでも、同様の処理をしてやらねばいけませんね(「処理が足りてないじゃないか」というのはそれの事)。
*1:GreaseMonkey で既存サイトの動作を変更したい場合に、全く欲しくならないとは言い切れない……くらいですかね。
UnityのTranslateにご注意
UnityのTransform.Translate関数には、じつはちょっと注意が必要です。 簡単に言うと、transform.Translate(Vector3.right)とtransform.position += Vector3.rightは異なるというお話です。
手順1
まず、原点に球体を用意します。
手順2
次にInspector上でPositionをX方向に+2移動させると、当然赤い球体のようになります。
手順3
Inspector上でRotationをY軸中心に90度回転させると、向きは変われど、位置は変わりません。 これは、手順2と手順3を入れ替えても同じ結果になります。
手順4
さて、ここでもう一つ緑の球体を用意させます。 Inspector上でRotationをY軸中心に90度回転させます。
手順5
さあ、ここでソース上で下記のようにTranslateさせてみましょう。
void Start () { transform.Translate(2.0f * Vector3.right); }
あれ、手順3と結果が異なりますね。 Translate(Vector3)は、ローカル座標系をベースとした関数であるということがわかります。 ちなみに、Position.Xは-2.384186e-07という値になっております。
手順6
ここでソースを下記のように変更してみます。
void Start () { //transform.Translate(2.0f * Vector3.right); transform.position += 2.0f * Vector3.right; }
結果は、
完全に手順3と一致しましたね。 こちらはInspectorでの操作と同じ結果ということですね。
でもこれ実はTranslate関数でも同じことができて、
void Start () { transform.Translate(2.0f * Vector3.right, Space.World); }
とやれば良い。 デフォルトがローカル座標系になっておるのですね。
勘違いされている方もいるようですので、ご注意あれ。
UnityでOpenCVまとめ
Unityで画像処理と言うと、まだあまり需要がなさそうですが、Oculus Riftの流れ的にも、これからニーズが増えそうですなあ。 さて、弊社でもUnityでOpenCVを利用したくなったわけですが、現在パーフェクトな環境はまだなさそうです。 そこそこ調べたので、まとめておきます。
OpenCVSharp
かなーり苦労されている様子がわかりますが、Unity Editor上で使っている人は下記にいるようです↓
調べた感じ、iOS, androidで試してる人は見つからなかった。。。スマホ向けに利用するためには、プラグインの作成と、おそらくラッパーのソースもいじらないといけないでしょうな。無料なのは素晴らしいですが、ライセンスがLGPLなので、ソースをいじるとなると商用利用は少し大変でしょう。
Emgu CV
http://www.emgu.com/wiki/index.php/Main_Page
ライセンスがGPLなので、商用利用したければ基本は有償版が必要になるでしょう。 これはスマホ向けもあります。それもそれで別途有償で値段もそこそこする。。。
Unityへの組み込みは開発側がサポートしているわけではなさそうです。 Windowsへの組み込みで、ずいぶん苦労されているみたいです。Macも大変かもしれません。 ちなみにスマホ向けライブラリは、お金を払ってからでないと触れません。
OpenCV for Unity
Unity Asset Store - The Best Assets for Game Making
スマホ対応がばっちりできているので、今のところはっきりこれが一番だと思うわけですが、これはこれで難点があります。 まず、Unity Editorで利用することができません。つまりUnityからスマホに落とさないと動作を確認できない。これははっきり痛い。
また、CVAUX等一部APIが使えないようです。ラッピングの充実度という点では、先に上げた二つに劣ると思います。 CVAUXを使いたい時はどうしましょう。。。ちなみに先日私はこのアセットからCVAUXが利用できる夢を見ました。 下記APIが利用できます。
組み込みは割と楽チンです。
自作プラグイン
1関数利用したいだけ等、ごくごく限定された使い方をするのであれば、いっそのこと一からプラグインを作った方がコスパがいいのかもしれませんな。 トライしている人はたくさんいますので、これらを参考にされてはと思います。(あまりやりたくはありませんが。。。)
GitHub - thorikawa/unity-opencv-android: Unity+OpenCV+Android
それでは以上。