Chef実践入門を読んでいる 1
先週買ったChef実践入門のログを残すことにした。 www.amazon.co.jp
Chefは業務で使われているのでレシピを読んだり軽い修正のPRはしたことあるが、1から自分で書いたことはないのでやってみようと思った。サーバサイドに疎いし。
書いたものは下記のリポジトリにpushしていく github.com
所感を事細かに書いていった方が身につきそうだけど、きつくて続かなそうだから印象に残ったとこだけ書いていく
今日の進捗 2.7まで
- centos6.7(本は6.5だが最新)をインストールしたよ
- chef soloをvagrant上に入れてゲストOS上でレシピ書いていったよ
- ホストOSにknife solo入れて手元で構築するようにしたよ
- dstat、mysql、apacheのレシピを書いたよ
- ついでにServerspecも入れて上記の三つがインストールされているかのテストも書いたよ PR
特につまづくことはなかった。
actionで出てきた enable
start
がそれぞれ sbin下の chkconfig
service
の実行に相当すると知ったが、そもそもsbin下のコマンドを全然知らなかった。知見を得た。
Serverspecで今回はdstat、mysql、httpで三つテストファイル区切ったんだけど、どのくらいの粒度が良いのだろうかと気になった。ツールごとに区切っていくとかなり増えそう。
UnityWebRequestについてちょっと調べてみた
この記事はUnity 2 Advent Calendar 2015のエントリです。
UnityWebRequest
UnityWebRequestとはWWWに変わる新しいHTTP通信用のクラスである。
名前空間にExperimental
が含まれている通り、まだ実験的な機能なので今後も仕様が変更されていく可能性がある事をご了承いただきたい。
それでも、WWWと比較して十分使いやすくなってはいるので普通に活用して良さそう。
使い方
例えば、以下のコードはローカルホストにアクセスして、レスポンスをログに吐く
using UnityEngine; using UnityEngine.Experimental.Networking; public class HTTPTest : MonoBehaviour { // Use this for initialization void Start () { StartCoroutine(HttpRequest()); } IEnumerator HttpRequest() { var request = UnityWebRequest.Get("http://localhost:4567"); yield return request.Send(); Debug.Log(request.responseCode.ToString() + ":" + request.downloadHandler.text); } }
コルーチンで、通信終わるまで待つという点は今までと同じ。
WWWクラスの場合コンストラクタ呼び出したタイミングで通信しに行くが、UnityWebRequestの場合はSend
を呼び出したタイミングで通信する。
なので通信する前にSetRequestHeader
で諸々のヘッダ設定ができるようになった。
WWWと比較した時の違いを幾つか挙げるとこんな感じ
- RESTに対応
- データとHTTPのハンドリング部分が分離されている
- DownloadHandlerScriptでロギングや加工が便利
RESTに対応
多分これが一番大きな変更点。
ついにPUT、DELETEメソッドが実装された・・・。
PUTは引数にstringとbyte[]しか渡せない。 POSTはDictionaryが使用できるのでキーバリューペアでサクッといけるがPUTは自分で整形する必要がある。ちなみに文字列をバイト配列に変換する場合下記で行ける。
System.Text.Encoding.UTF8.GetBytes("foo=get")
引数を空文字列にした場合、以下のエラーが出る。
ArgumentException: Cannot create a data handler without payload data
因みにPATCHはないので、必要があればインスタンスのmethod
プロパティに直打ちしよう
request.method = "PATCH";
また、現状POST以外のメソッドはContent-typeが空になっている模様。 なので、そのままパラメータ付きでPUTしてもサーバ側によってはうまく受け取ってくれない可能性が高いので以下の感じでヘッダに組み込むのがいい
request.SetRequestHeader("Content-type", "application/x-www-form-urlencoded");
ここは修正されていくと思う、多分。
データとHTTPのハンドリング部分が分離されている
- 新しいHTTP通信は大まかに三つのクラスで構成されている
- UploadHandler
- DownloadHandler
- UnityWebRequest
UploadHandlerはリクエストを飛ばす際のパラメータデータ、DownloadHandlerはレスポンスのデータを保持する小さなクラスになっている。
その二つをUnityWebRequestが所有している。
UnityWebRequestはURLやヘッダ情報、リダイレクト回数の設定などHTTP通信に関する処理を扱う。
WWWと違い、データそのものと通信がしっかり分離しており扱いやすい。
UploadHandlerとDownloadHandlerは外部から流し込むことができるからだ。
UploadHandler
を外から設定する場合はUploadHandlerRaw
クラスを使う。
var request = UnityWebRequest.Get("http://localhost:4567"); var upload = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes("foo=get")); request.uploadHandler = upload;
コンストラクタの引数がバイト配列なので、変換が必要。 上記で書いたが、PUTはbody部分を空文字列にするとエラーになるので「適当な文字列を入れて初期化」->「uploadHandlerに流し込む」 という流れになった。もっといいやり方ありそう。
DownloadHandler
クラスそのものは流し込むことはできるがあまり意味はない。
むしろ、後述するDownloadHandlerScript
の時に役に立つ。
DownloadHandlerScriptでロギングや加工が便利
DownloadHandlerはダウンロード時の幾つかのタイミングでコールバックされる
ReceiveData
データを読み取った際に呼ばれるコールバックCompleteContent
読み取り完了した時に呼ばれるコールバックReceiveContentLength
ヘッダーからデータの長さを受け取った時に呼ばれるコールバック
データを読み取った各所でメソッドを呼ぶようになっており、Unityではそれをユーザ側でカスタマイズできるようにDownloadHandlerScriptというクラスを提供しています。
サンプルコードから抜粋
using UnityEngine; using System.Collections; using UnityEngine.Experimental.Networking; public class MyDownloadHandler : DownloadHandlerScript { // Standard scripted download handler - will allocate memory on each ReceiveData callback public MyDownloadHandler(): base() { } // Pre-allocated scripted download handler // Will reuse the supplied byte array to deliver data. // Eliminates memory allocation. public MyDownloadHandler(byte[] buffer): base(buffer) { } // Required by DownloadHandler base class. Called when you address the 'bytes' property. protected override byte[] GetData() { return null; } // Called once per frame when data has been received from the network. protected override bool ReceiveData(byte[] data, int dataLength) { if(data == null || data.Length < 1) { Debug.Log("LoggingDownloadHandler :: ReceiveData - received a null/empty buffer"); return false; } Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveData - received {0} bytes", dataLength)); return true; } // Called when all data has been received from the server and delivered via ReceiveData protected override void CompleteContent() { Debug.Log("LoggingDownloadHandler :: CompleteContent - DOWNLOAD COMPLETE!"); } // Called when a Content-Length header is received from the server. protected override void ReceiveContentLength(int contentLength) { Debug.Log(string.Format("LoggingDownloadHandler :: ReceiveContentLength - length {0}", contentLength)); } }
上記のコードは、コールバックの各所でログに吐くような処理をしています。 あとは、これをUnityWebRequestのDownloadHandlerに流し込むだけです。
var request = UnityWebRequest.Get("http://localhost:4567"); var download = new MyDownloadHandler(); request.downloadHandler = download;
これで、データ受信時にログに吐いたり、ゲーム用にレスポンスを加工したりなど痒いところに手が届くようになる。
まとめ
現状、content_typeの問題など、まだまだこちらでカバーしなければならない問題はありますが、WWWクラスと比較するとかなり改善されており、期待が持てるAPIっぽい
明日は @yaegakiさんのmruby on Unityです
Phaserメモ
PhaserというWEB向けのゲームエンジンがあるので最近触っているので忘れないように殴り書き
ブラウザゲーもUnityでなんとかしようと思っていたのだけど、WebPlayerはもう使えないしWebGL出力はそれなりのサイズになってしまうのでまだまだ軽量とは言い難い。 ということで最近結構賑わっているという噂のPhaserで作ってみようかと考えた。
ついでにtypescriptも始めて見た。jsすらあんまり書けないけど。
メモ
日本語の資料はほとんどない。唯一下記サイトがわかりやすいかなという印象
Phaser入門:HTML5/Javascript 2Dゲームエンジン - catch.jp-wiki
ただ、異常なまでにサンプルコードが充実しているのでそれをひたすら読み解くべし。 phaser.io
シーン設計
Unityなどにおけるシーンの役割は、Phaserでは State
というものが担う。
preload
メソッド内でリソース系のロード、 create
でそのstate内のデータの初期設定をしてくれという感じ。
サンプル見た感じ、Stateの設計は下記のパターンが多い
Boot
Preloader
Hoge
Fuga
Hoge,Fugaは実際に遊ぶであろうStateの部分。MainとかGameOverとか。
まずはBootStateを読み込ませて、create
内でゲーム上で使用するstateを全部読み込む係になっている。PreloaderとかHogeとかFugaなど全部読み込む。完了後にPreloderに遷移する
PreloaderStateの preloader
で画像、音声などのアセットを読み込む。
複数のサンプルでBootとPreloaderがいたから、これはPhaserのお作法っぽい。
アニメーション
xmlだとかspritesheetとか幾つかあったけど、jsonにした。
流れは以下
上から順番に、上、右上、右、右下、下、左下、左、左上の8パターンの歩行グラフィックをそれぞれ4枚持ってる。
- 各スプライトの情報を保持するjsonファイルを用意
texturepackerを使うと、画像をまとめるのとPhaser用Jsonファイル出力の両方ができる
使い方はこちら
https://www.codeandweb.com/blog/2014/12/17/creating-spritesheets-for-phaser-with-texturepacker
今回もそれで吐こうとしたが、TexturePackerですでに出来上がってるatlasに対してスプライトの情報を与えるやりかたがわからなかった。バラバラの画像をペタペタ貼っていくときはスプライトの情報が追加されていくけど、既存の1ファイルだと1つのスプライトとみなされてしまい、それの分割方法がわからなかった。
なのでjson生成スクリプト書いた https://gist.github.com/adarapata/c96048cd99f6ef7d9537 自分の持ってる画像はほぼほぼ上記のパターンなのでこれで生産できるようになった。
こんな感じ
this.game.load.atlasJSONHash("iku", "assets/images/chara_iku.png", "assets/atlases/iku.json");
アニメーションは、コード内で実装する必要がある。下記は上方向歩行モーションの設定
iku.animations.add("walk_up", ["up_0","up_1","up_2","up_3"], 10, true, false); iku.animations.play("walk_up");
単純に配列でスプライト名を指定していけばその順番で再生してくれるみたい。 スプライト名のルールを決めておけば同じフォーマットで複数キャラ対応できそう。 UnityでのAnimatorみたいな動きはできるかもしれない。
ちなみにチュートリアルでローカルサーバ立てるためにXAMPP入れようみたいなこと書いてるけど、多分sinatraが一番楽だと思う。
UniRX使ってOnRaycast的な処理を書く
小ネタ
OnTriggerEnterとかそういう感じで、レイにぶつかった瞬間、ぶつかっている間、レイから離れた瞬間を検知したいなという気持ち。
一案としてこのような感じ
using UnityEngine; using System.Collections; using UniRx; using UniRx.Triggers; using System.Linq; public class OnRaycastHit : MonoBehaviour { Subject<Unit> onRaycastStayStream = new Subject<Unit> (); public IObservable<Unit> onRaycastStayAsObservable { get { return onRaycastStayStream.AsObservable (); } } Subject<Unit> onRaycastExitStream = new Subject<Unit> (); public IObservable<Unit> onRaycastExitAsObservable { get { return onRaycastExitStream.AsObservable (); } } Subject<Unit> onRaycastEnterStream = new Subject<Unit> (); public IObservable<Unit> onRaycastEnterAsObservable { get { return onRaycastEnterStream.AsObservable (); } } private bool isOnNext; public void RaycastHit () { isOnNext = true; } void Start () { this.UpdateAsObservable (). Select (_ => isOnNext). Buffer (2, 1). Subscribe (list => { bool before = list.First (); bool current = list.Last (); if (!current && before) onRaycastExitStream.OnNext (default(Unit)); if (current && !before) onRaycastEnterStream.OnNext (default(Unit)); if (current) onRaycastStayStream.OnNext (default(Unit)); isOnNext = false; }); } }
Raycastで引っかかった時に RaycastHit
を呼ぶイメージ。
そのフレームだけisOnNextがtrueになり、Buffer(2,1)で前フレームとの値と比較してOnNextの対象を変える。
isOnNextが結構強引な気がしていて、まだ良い方法あるんじゃないかと考えてる
大きい蝿
母方のじいちゃんは自分が小さい頃に亡くなっていてどんな人だったのかも覚えていないんだけど、毎年お盆には じいちゃんのお参りに行っていた。まだ元気だったばあちゃんと親族とかが集まって軽い挨拶などするのが恒例だった。
そのばあちゃんの家は、ちょっと大きい蝿が一匹いた。おじさんはその蝿をこう説明していた。
「みんなが集まると、じいちゃんが蝿になって見に来るんだよ」
見に来るのはわかるけど、よりにもよって蝿になるとはおじいちゃんはどんな罪を犯したのだと思った。 蝶とかならまだ歓迎されていたと思う。
時は流れ母方のばあちゃんも二年前に他界して、昨日はその三回忌に行っていた。お墓にお参りしたあと家に行って軽く挨拶などしたりお菓子を食べたり。
話していると例によってちょっと大きい蝿が現れた。
しかも、今度は二匹で飛んできた。
「さいきんばあちゃんも連れてくるようになってな」とおじさんは楽しそうに話した。それはいいとしてなんでやっぱり蝿なのか。
うちの家系は蝿と何かの縁があるのか。蝿の王(ベルゼブブ)の血統なのだろうか。
映画の蝿の王は割と評価良いのでどなたか土日にでも観ていただきたい。僕は見たことないです。 movies.yahoo.co.jp
今日はまた別件で告別式に参加していた。父方の伯父さん(上記のおじさんではない)に不幸があったのだ。
伯父さんは非常に人徳があったようで、想定を超える数の弔問者が訪れていた。訃報はつらいことだけど、それでもいろんな人が駆けつけてくれたことはなんだか嬉しく思えた。入りきらないほどの花を詰め、大好きだったビールを少し口につけて出棺していった。
火葬を終えて遺骨も拾い、そのまま初七日を執り行った。親族、友人で伯父さんの遺影の前で食事をしながら思い出話などに花を咲かせていたら
飲んでた缶ビールに、大きい蝿が一匹止まった。
素振りをしている
8月入ったあたりから不健康がヒートアップしてきたので、一週間前くらいから木刀素振りを始めている。
木刀とは
こちらです
なぜ素振りなのか
ジョギング、筋トレ諸々やってみたけどどれもあまり長続きしなかった。
中学時代に剣道やっていたので木刀を持っており、素振りなら昔やってたしいけるかなと思って、始めてみた。
これが結構楽しい
内容は
- 前後素振り50
- 跳躍素振り30
- 片手素振り20
入部したての時くらいのメニューしかこなせないことがわかったので自分に甘くしている
メリット
外でできる
腕立て腹筋背筋を外でやると若干変な目で見られかねない。
しかし自分の部屋には冷暖房器具が存在しないので基本的にサウナ室になっており、やる気が起きない。そこで素振りである。
素振りは室内だとある程度の高さが必要なので屋外で行うことに何の違和感もない。ごく自然に、周囲に「己を鍛えています」アピールができる。「玉竜旗がんばってね」と言われるようになれば概ね成功と言えるだろう。
集中力が上がる
運動をした後は、若干集中力が上がるらしい。 ※出典なし
少なくとも、突然こんな記事を書くくらいには集中力が増す。
デメリット
通報される
一軒家で自分の敷地内であれば木刀を持とうが素振りしようが問題はないが、マンションやアパートなどであれば時間帯には気をつけたほうがいい。
22時に木刀を持った男が家から出てくる姿を見られると事案になりかねない。
しかし、これは相手の素性がわからないから事案になるわけで、入居時に挨拶、普段すれ違う際の対応、ゴミ出しルールの徹底など、そのコミュニティに所属するための人付き合いをしっかりしておけば回避できるものと思われる。
知った顔であれば、「あら、こんな時間に木刀なんか持って闇討ちかしら?」と気さくに声をかけられるくらいで済むと思う。
結論
ご近所付き合いというのは、非常に大事なのである
ArborのStateBehaviourを継承してUniRXを少し使いやすくする
無料期間中にArbor: State Diagram Editorを入手しました。
毎回statemachineを自前で書いてて面倒だと思ってたのでこれはありがたい。 昨日から触り始めているけど、特別引っかかることもなく使いやすいです。
なお、Arborの使い方とかはテラシュールブログさんが細かく書いてるのでそちらを参照すると良さそうです。 tsubakit1.hateblo.jp
これで作るスクリプト内部でUniRXをごにょごにょして、State遷移してから変更あるまでHogeHoge〜みたいな処理を書きたかったので拡張してみました。
こういう拡張どこに置くか悩んだので、とりあえず CustomArbor
名前空間を作って ObservableStateBehaviour
を作った。
using UnityEngine; using System.Collections; using Arbor; using UniRx; using UniRx.Triggers; using System.Linq; namespace CustomArbor { public class ObservableStateBehaviour : StateBehaviour { private Subject<Unit> stateBeginStream = new Subject<Unit>(); public IObservable<Unit> stateBeginAsObservable { get { return stateBeginStream.AsObservable(); } } private Subject<Unit> stateEndStream = new Subject<Unit>(); public IObservable<Unit> stateEndAsObservable { get { return stateEndStream.AsObservable(); } } public IObservable<Unit> updateAsObservable { get { return this.UpdateAsObservable(). SkipUntil(stateBeginAsObservable). TakeUntil(stateEndAsObservable). Repeat(); } } // Use this for enter state public override void OnStateBegin () { stateBeginStream.OnNext(default(Unit)); } // Use this for exit state public override void OnStateEnd () { stateEndStream.OnNext(default(Unit)); } } }
やってることは、状態の開始時と終了時にそれぞれストリームを用意して、通知しているだけです。
また、StateBehaviourの通常のUpdateは OnStateBegin
~ OnStateEnd
の間のみ走るので、代用としてupdateAsObservableを作ってます。
例
- StateAは、0.5秒ごとに
A!
と出力する - StateBは、1秒ごとに
B!
と出力する - キーボードのAを押された場合
State X Down
と出力して遷移する
public class StateA : ObservableStateBehaviour { public StateLink nextState; void Awake() { this.UpdateAsObservable(). SkipUntil(stateBeginAsObservable). Sample(TimeSpan.FromSeconds(0.5F)). TakeUntil(stateEndAsObservable). Repeat(). Subscribe(_ => { print("A!"); }); updateAsObservable. Where(_ => Input.GetKeyDown(KeyCode.A)). Subscribe(_ => { print("StateA Down"); Transition(nextState); }); } } public class StateB : ObservableStateBehaviour { public StateLink nextState; void Awake() { this.UpdateAsObservable(). SkipUntil(stateBeginAsObservable). Sample(TimeSpan.FromSeconds(1F)). TakeUntil(stateEndAsObservable). Repeat(). Subscribe(_ => { print("B!"); }); updateAsObservable. Where(_ => Input.GetKeyDown(KeyCode.A)). Subscribe(_ => { print("StateB Down"); Transition(nextState); }); } }
こんな感じになります。
n秒間隔で流すという処理が挟まるので、updateAsObservable
使わず SkipUntil -> Sample -> TakeUntil と書いてるけど、もっと綺麗なやり方ありそう。