読者です 読者をやめる 読者になる 読者になる

Visual StudioをMicrosoft Azure管理ツールとして使う

AWSMicrosoft 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からの管理がオススメです。

WindowsAzure エンタープライズクラウドコンピューティング実践ガイド

WindowsAzure エンタープライズクラウドコンピューティング実践ガイド

無料ではじめるWindows Azure×WordPress超入門

無料ではじめるWindows Azure×WordPress超入門

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キーを設定します。この画面で詳しく案内してくれるので特に問題はないでしょう。

どのブランチを監視するのかを決めます。ここで指定したブランチにあるコードを使ってビルドしてくれるようになります。

これまでに設定した内容の確認と、ビルドするプラットフォームを選びます。iOSAndroidを有効にし、必要であればAuto-buildにもチェックしておきましょう。Auto-buildが有効になっていると、ブランチに対する変更を検知して自動的にビルド→配布を行ってくれます。

最後にAndroidiOSの設定を行います。

予め用意しておいたBundle IDやProvisioning Profile、p12などを入力、アップロードします。

長かったですね。これで自動ビルドのための準備ができました。

次のステップに進むと最初のビルドがスタートします。ビルド完了後は配布URL付きのメールが来ます。

運用例

弊社ではCloud Buildが監視するためだけのブランチを作成しており、区切りのいいタイミングでメインブランチからプルリクエストを作成してビルド用ブランチを更新するようにしています。BitbucketのWebインターフェースでプルリクエストを作ってマージするだけで自動的に実行可能なバイナリを作ってくれるわけです。

もっというとこのプルリクエスト作成→マージの部分はChatOpsな感じで動くようにしています。細かい話は後日書くかもしれませんが、予め登録しておいた命令をbot hogehogeのような感じでSlackに投稿すると、あとはBotが勝手にマージしてくれるようにしています。

「そろそろメンバー全員に見せておくか」と思ったらSlackにちょっと書くだけで配布まで完了できるわけです。革命的ですね。

Unityではじめる2Dゲーム作り徹底ガイド スマートフォンでも遊べる本格ゲーム開発に挑戦

Unityではじめる2Dゲーム作り徹底ガイド スマートフォンでも遊べる本格ゲーム開発に挑戦

UnityでのXcode設定をUnityEditorのスクリプトだけで自動化する

Unityが出力したiOS用プロジェクトの手動編集をなんとかしたいと考えていたら、同じような人がやはり多いようでいろいろな方法がブログエントリで紹介されていました。

調べた感じではCodeEditor-for-Unityxcodeprojという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>&emsp;<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.activitydefaultsプロパティを持っていないので、変なところに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 のコードでも、同様の処理をしてやらねばいけませんね(「処理が足りてないじゃないか」というのはそれの事)。

JavaScript 第6版

JavaScript 第6版

JavaScript逆引きレシピ jQuery対応 (PROGRAMMER’S RECiPE)

JavaScript逆引きレシピ jQuery対応 (PROGRAMMER’S RECiPE)

*1:GreaseMonkey で既存サイトの動作を変更したい場合に、全く欲しくならないとは言い切れない……くらいですかね。

UnityのTranslateにご注意

UnityのTransform.Translate関数には、じつはちょっと注意が必要です。 簡単に言うと、transform.Translate(Vector3.right)とtransform.position += Vector3.rightは異なるというお話です。

手順1

まず、原点に球体を用意します。

f:id:cflat-inc:20141028105357p:plain

手順2

次にInspector上でPositionをX方向に+2移動させると、当然赤い球体のようになります。

f:id:cflat-inc:20141028105412p:plain

手順3

Inspector上でRotationをY軸中心に90度回転させると、向きは変われど、位置は変わりません。 これは、手順2と手順3を入れ替えても同じ結果になります。

f:id:cflat-inc:20141028105421p:plain

手順4

さて、ここでもう一つ緑の球体を用意させます。 Inspector上でRotationをY軸中心に90度回転させます。

f:id:cflat-inc:20141028105450p:plain

手順5

さあ、ここでソース上で下記のようにTranslateさせてみましょう。

   void Start () {
        transform.Translate(2.0f * Vector3.right);
    }

f:id:cflat-inc:20141028105632p:plain

あれ、手順3と結果が異なりますね。 Translate(Vector3)は、ローカル座標系をベースとした関数であるということがわかります。 ちなみに、Position.Xは-2.384186e-07という値になっております。

手順6

ここでソースを下記のように変更してみます。

   void Start () {
        //transform.Translate(2.0f * Vector3.right);
        transform.position += 2.0f * Vector3.right;
    }

結果は、

f:id:cflat-inc:20141028110745p:plain

完全に手順3と一致しましたね。 こちらはInspectorでの操作と同じ結果ということですね。

でもこれ実はTranslate関数でも同じことができて、

   void Start () {
        transform.Translate(2.0f * Vector3.right, Space.World);
    }

とやれば良い。 デフォルトがローカル座標系になっておるのですね。

勘違いされている方もいるようですので、ご注意あれ。

ゲーム作りのはじめかた Unityで覚える企画からレベルデザインまで

ゲーム作りのはじめかた Unityで覚える企画からレベルデザインまで

UnityでOpenCVまとめ

Unityで画像処理と言うと、まだあまり需要がなさそうですが、Oculus Riftの流れ的にも、これからニーズが増えそうですなあ。 さて、弊社でもUnityでOpenCVを利用したくなったわけですが、現在パーフェクトな環境はまだなさそうです。 そこそこ調べたので、まとめておきます。

OpenCVSharp

かなーり苦労されている様子がわかりますが、Unity Editor上で使っている人は下記にいるようです↓

調べた感じ、iOS, androidで試してる人は見つからなかった。。。スマホ向けに利用するためには、プラグインの作成と、おそらくラッパーのソースもいじらないといけないでしょうな。無料なのは素晴らしいですが、ライセンスがLGPLなので、ソースをいじるとなると商用利用は少し大変でしょう。

Emgu CV

Emgu CV: OpenCV in .NET (C#, VB, C++ and more)

ライセンスがGPLなので、商用利用したければ基本は有償版が必要になるでしょう。 これはスマホ向けもあります。それもそれで別途有償で値段もそこそこする。。。

Unityへの組み込みは開発側がサポートしているわけではなさそうです。 Windowsへの組み込みで、ずいぶん苦労されているみたいです。Macも大変かもしれません。 ちなみにスマホ向けライブラリは、お金を払ってからでないと触れません。

OpenCV for Unity

Asset Store

スマホ対応がばっちりできているので、今のところはっきりこれが一番だと思うわけですが、これはこれで難点があります。 まず、Unity Editorで利用することができません。つまりUnityからスマホに落とさないと動作を確認できない。これははっきり痛い。

また、CVAUX等一部APIが使えないようです。ラッピングの充実度という点では、先に上げた二つに劣ると思います。 CVAUXを使いたい時はどうしましょう。。。ちなみに先日私はこのアセットからCVAUXが利用できる夢を見ました。 下記APIが利用できます。

Generated Documentation (Untitled)

組み込みは割と楽チンです。

自作プラグイン

1関数利用したいだけ等、ごくごく限定された使い方をするのであれば、いっそのこと一からプラグインを作った方がコスパがいいのかもしれませんな。 トライしている人はたくさんいますので、これらを参考にされてはと思います。(あまりやりたくはありませんが。。。)

thorikawa/unity-opencv-android · GitHub

それでは以上。

詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識

詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識

Unity4入門 最新開発環境による簡単3Dゲーム制作

Unity4入門 最新開発環境による簡単3Dゲーム制作