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

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

GitHubとCircleCIの連携について

GitHub CI

サーバーエンジニアの若原です。

今回は開発でも使っているCircleCIのGitHub連携について紹介させていただきます。 CircleCIとは継続的インテグレーションのためのクラウドサービスです。 GitHubと連携することができ、git pushなどをトリガーにビルドを走らせることができます。

1コンテナまでは無料で使用することが可能ですが、複数のビルドを並列で行うためにはコンテナを増やす必要があり、2つ以上のコンテナを使用したい場合は有料となります。プロジェクトの規模を考えて適切な量のコンテナ数を追加する必要があります。

サインアップ

CircleCIへはGitHubのアカウントでサインアップすることができます。

f:id:wp-wakahara:20170110020126p:plain

プロジェクトの追加

サインアップ直後にダッシュボードに遷移します。プロジェクトが存在しないため赤枠内の「Add Projects」からGitHubのプロジェクトを追加します。

f:id:wp-wakahara:20170110020026p:plain

追加したいプロジェクトの「Build project」からプロジェクトを追加します。

f:id:wp-wakahara:20170110020120p:plain

CI設定

CIの実行内容を記載する「circle.yml」を、追加したプロジェクトのrootディレクトリに設置します。

circle.ymlの以下サンプルは以下のとおりです。

machine:
  timezone: # タイムゾーン
    Asia/Tokyo
  python:   # 言語のバージョン指定(ruby,phpなど)
    version: 3.4.2
  environment: # 環境変数
    TEST_ENV: test

dependencies:
  override:
    - 依存ライブラリのインストールコマンドなど

database:
  override:
    - DBやテーブルを作成したり、サンプルデータを作成するコマンドなど

test:
  override:
    - テストを実行するコマンド
    
deployment:
  deploy:
    branch: master
    commands:
      - デプロイを実行するコマンド

他にも様々なカスタマイズが可能です。詳しくは公式サンプル をご確認ください。

作成したcircle.ymlをリポジトリにpushすることで自動的にビルドが走ります。

また、CIが不要なドキュメントのみ修正などをpushする際には、コミットコメントに[ci skip]と含めることでCIをスキップすることができます。

UIアニメーションについて

開発
新卒デザイナーの小久保です。
 
今回はゲーム内のUIアニメーションについてお話しします。
 
 
UIアニメーションとは
「ユーザーがアクションを起こした時に、視覚的に何が起こったのかを
よりわかりやすく伝える為のもの」だと私は考えています。
アニメーションで表現できるものは様々です。
UIアニメーションの主な役割として以下のものが挙げられます。
 
 
・見てほしいものを強調する
 アニメーションを加えることで画面を華やかにするだけでなく、
 プレイヤーを次の行動に誘導する指針になります。
 (例:イベントボタンにアニメーションを追加することで
    イベント開催中であることをユーザーに伝え、ページへ誘導することができます)
 
・情報をより伝えやすくする
 要素が何か変化する時にその過程を見せることで、
 より変化の因果関係が伝わりやすくなります。
 (例:ユニットの強化で強化素材がユニットに吸い込まれる演出を追加すると、
    ユニットと強化素材の関係をより強調することができます)
 
・見落としをなくす
 目まぐるしく変わるゲームの中では見落としがちな情報もあります。
 見落としやすい数字の変化などもアニメーションを追加し、
 視覚的変化を大きくすることで見落としを防ぐことができます。
 (例:獲得した経験値やコインを既存の数値に足していく演出などで
    どの数字がどこに追加されたのか一目でわかります)
 
・不安にさせない
 ボタンを押したときに何の反応もないとユーザーは不安になってしまいます。
 全ての動作に対して何らかの反応を即座に返すことで不安の防止になります。
 (例:全てのボタンに押したことがわかるような動きをつける)
 
 
アニメーション制作
上記を考慮してアニメーションを作っていきます。
私の所属するチームでは2つのアニメーション方法があります。
・デザイナーがアニメーションツール(SpriteStudio)を使用して作成するもの
・エンジニアさんがUnityで設定して動かすもの
この2つの使い分けは主にデザイナーでしか再現できないか否かと、
容量を割くべきかどうかの2点で判断されています。
f:id:kokubom:20170116011343j:plain
調節と実機確認を何度か繰り返します。
 
エンジニアさんがUnityで動かす場合でもデザイナーがサンプル動画を作成する場合もあります。
エンジニアさんにお願いする場合はコミュニケーションをとりながら、
データの作り方を相談して制作を進めます。
 
 
まとめ
UIアニメーションは画面作りの味付けのイメージがあるかと思いますが、
ユーザー様へ確実に情報を伝えるためにもアニメーションは必要不可欠な要素だと思います。
 今回のブログでアニメーションにも様々な意図があることを知っていただけたなら幸いです。
色々な制約はありますがその中でよりわかりやすくワクワクするものを作っていける様に、
これからも頑張ります。
 
途中に出てきたSpriteStudioについて詳しく知りたい方は
こちらの公式サイトをご覧ください。

www.webtech.co.jp

ユニットキャラクターが完成するまでの工程について

デザイナーの小嶋です。

 

今回のデザイナー記事はイラストが どのように完成するのか です。

以前の記事でキャラクター指示書についてお話ししたかと思います。

キャラクターのコンセプト、デザイン等イメージを固め、その指示書を元に外部クリエイター様がキャラクターを描き上げて行きます。

 

イラストの工程について

 

外注したイラストには全部で3工程存在します。

 

1、ポーズラフ工程

キャラクターのポーズ、武器の位置、エフェクトのイメージを大雑把なラフで描いたもの。

基本的に、顔や髪、衣装は描かなくても良いのですが、イラストレーター様によては描き込んで来られる方もいます。

この工程では、キャラクターのポーズが指示書に沿っているか、魅力的であるかをチェックしていきます。

イマイチな場合は再考及び修正、または当社にて直しを入れて行きます。

 

f:id:t-kojim1982:20161206143211j:plain

 

2、詳細ラフ工程

キャラクターの顔、髪、衣装、武器デザイン、エフェクト等、完成を想像できるレベルまで描き込んだ工程。

この工程では、キャラクターデザインは魅力的か、デッサンに狂いは無いか、指示書指定内容に沿っているか、エフェクトはキャラクターの魅力を損なわず入っているか、全体の配色は属性色をメインに使っているか等をチェックしていきます。

覚醒後のキャラクターの場合は覚醒前よりパワーアップ感があるか、より魅力的になっているかもチェックします。

指示書に沿っていない、デザインがイマイチな場合は再考、修正、または当社にて直しを入れて行きます。

この工程でほぼイラストの出来具合が決まります、非常に重要な工程です。

 

f:id:t-kojim1982:20161206143234j:plain

 

3、着彩工程

詳細ラフを元にレギュレーションに沿って仕上げまで描き上げられた工程です。

雑だった線、陰影、ハイライトは綺麗に整えられます。

この工程では、詳細ラフから大きく変化した所は無いか、アウトラインの配色はレギュレーション通りか、光彩の処理は大丈夫か、塗り忘れやはみ出しは無いか、ゴミが無いか等をチェックしていきます。

それらをチェックし、イラストが完成へと至ります。

 

f:id:t-kojim1982:20161206143259j:plain

 

以上がイラスト完成までのプロセスです。

指示書がクリエイター様に渡って完成に至るまでには様々な段階を踏んで行きます。

クリエイター様の素敵なイラストは社内の厳しいチェックを通り、皆様の前に登場しているのです。

これからもより魅力的なイラストでユーザー様の目を楽しませて行きたいと考えておりますので、今後登場する新キャラクターに是非ご期待下さい!

チーム開発するエンジニアがポモドーロ・テクニックを実践するためのアイデアとツールの紹介

開発

ネイティブアプリケーション事業部サーバエンジニアの桐島です。

先日、社内エンジニアLT会にて、ポモドーロ・テクニックについて発表したところ、 「自分はこんな感じでやってるよー」という意見が出たり、気になっているひとが結構多い感じだったので、ブログにも書いてみます。

ポモドーロ・テクニックとは

Francesco Cirillo さんが、1980年代後半に考案した、時間管理法です。

小休憩を細かく取ることで生産性を向上させる、という考えがベースになっています。

ポモドーロ・テクニックのやり方

具体的な実践方法は以下となります。

  1. やることを決める
  2. 25分後に鳴るようにタイマーを設定する
  3. タイマーが鳴るまでタスクを処理する
  4. タイマーが鳴ったら、短い休憩(3〜5分)をして、1に戻る(これが1ポモドーロ)
  5. 4ポモドーロしたら、より長い休憩(15-30分)をして、1に戻る

とてもシンプルですね。

とは言うものの、ポモドーロは個人の時間管理方法であり、会社組織でのチームワークのための時間管理方法ではないので、ある日突然自分の時間だけをポモドーロ単位で区切っても上手くいきません。

そこで、自分の仕事環境に合った形で実践してみることにしました。

自分流の実践方法

  • ポモドーロ管理対象タスクを絞り込む
    • 自分だけで完了するタスク(他のひとが絡まない範囲のタスク)
    • 今日中に終われば良いタスク(xx時xx分まで、という近々の〆がない)
    • 1ポモドーロ単位(25分)で完了するタスク
  • ポモドーロができる時間帯を確保する
  • ポモドーロの休憩 = 通知系の確認時間 とする
  • 1日の最後のタスクに取り掛かっていて、良い感じに集中しているときは小休憩は不要とする

一日に回せるポモドーロ数は少なくなってしまうのですが、 しばらくこのやり方で試してみようと考えています。

ポモドーロの効果

単純な仕掛けですが、新しいポモドーロを開始すると、このタスクはこのポモドーロ内でやり切るぞ、という心理が働きます。

残り時間が迫ってくると、タスクを完了させるために自然と全力が出ます。

夏休みが終わる前日に凄まじい勢いで宿題をやり切る、あのイメージです(僕は夏休みに入る前に終わらせるタイプでしたが)。

結果として、生産性は明確に向上していると思います。

タスクを25分単位で区切るやり方は初めてなので、まだ1ポモドーロの見積りが良い感じにできていないですが、 小さな休憩と集中を繰り返す方法は自分には合っていると感じています。

ポモドーロするためのサポートツール

Pomodoro Timer on BitBar

BitBarのプラグインです。 シンプルなポモドーロタイマーで、導入も使い方もとても簡単で素晴らしいです。 ポモドーロに取り組み始めるタイミングでは丁度良いツールかと思います。

KanbanFlow

しばらくポモドーロを実践していると、その実績・効果を管理・計測したくなってきます。 それを実現してくれるのがKanbanFlowというツールです。

KanbanFlowの簡単な紹介

一見するとTrelloの様なカンバンツールなのですが、ポモドーロ管理のための機能が揃っています。

例えば、以下の様に、ポモドーロタイマーを開始することができます。

f:id:s-krsm:20161130000032p:plain

開始したポモドーロを停止すると、その理由を設定することができます。 理由の項目は自分でも追加可能です。

f:id:s-krsm:20161130000221p:plain

もちろん履歴も確認できます(ブログを書くタスクが終わらない様子が伝わってきます)。

f:id:s-krsm:20161130000710p:plain

そして、タスク単位の履歴だけでなく、任意の期間での集計も行えます。

しばらく、このツールを使ってポモドーロ・ライフを送りたいと思います!

おまけ

「ポモドーロ」という名称ですが、 Cirilloさんが、時間管理のためにトマト型のキッチンタイマーを使用していたことが由来らしいです。 (トマトはイタリア語で「pomodoro」)

GatlingでWeb APIのシグネチャ検証に対応する

Scala

サーバーエンジニアの原 @zetta1985 です。

認証済みで使用されるWeb APIの多くは、リクエストURLやパラメータをベースに生成したHMACをHTTPリクエストヘッダーに指定することで、サーバーサイドでリクエストの改ざんを検知する仕組みになっています。

応用が効かない負荷テストツールでは、この手のシグネチャ生成をサポートするのが手間な事があるのですが、 GatlingではScalaによってシグネチャ生成処理を自由に書くことができます。

Gatlingは、Java製の非同期HTTPクライアントとして有名なAsyncHttpClient を使用しています。 AsyncHttpClientはシグネチャ生成のためのフック処理をサポートしており、GatlingにおいてもAsyncHttpClientが提供しているSignatureCalculator を実装することで、リクエストの直前にシグネチャを生成し、任意のHTTPリクエストヘッダーに値を設定する事が可能となっています。

SignatureCalculator は以下のような定義になっています。

public interface SignatureCalculator {
  void calculateAndAddSignature(Request request, RequestBuilderBase<?> requestBuilder);
}

第一引数の request には、Gatling DSLで構築したURLやリクエストヘッダー/ボディが設定されています。 この request の値を使用して、シグネチャを生成し、第二引数の requestBuilder に対してシグネチャ用のHTTPリクエストヘッダーを設定することになります。

以下に、一例を示します。SignatureCalculator はsingle method interfaceなので、ここでは関数として定義します。

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import com.hunorkovacs.koauth.service.Arithmetics

object Utils {

  // シグネチャ生成用秘密鍵
  val secret = sys.env.getOrElse("API_SECRET", "your secret")

  /** シグネチャ生成およびHTTPリクエストヘッダーへの設定 */
  def generateAndAddSignature(request: Request, rb: RequestBuilderBase[_]): Unit = {
    val token = request.getHeaders().get("Authorization").replace("Bearer ", "")
    val signingKey = s"$token&$secret"

    val method = request.getMethod()
    val url = request.getUrl()

    val encodedUrl = Arithmetics.urlEncode(url)
    // getByteDataでbodyのバイト配列が取得できないためボディの文字列からバイト配列を取得
    val body = Option(request.getStringData()).map(_.getBytes()).map(new String(_)).getOrElse("")
    val encodedBody = Arithmetics.urlEncode(body)
    val baseStr = s"$method&$encodedUrl&$encodedBody".toUpperCase()

    val mac = Mac.getInstance("HmacSHA256")
    val key = new SecretKeySpec(signingKey.getBytes("utf-8"), "HmacSHA256")
    mac.init(key)
    val signature = mac.doFinal(baseStr.getBytes("utf-8"))
    // bytes to Hex
    val sigHex = signature.map("%02x" format _).mkString
    rb.addHeader("X-Signature", sigHex)
    rb.addHeader("X-Signature-Method", "HMAC-SHA256")
  }

このgenerateAndAddSignature は、以下のようにして使用します。

  val getPlayerStatus = http("player status")
    .get("/v1/players/me")
    .header("Authorization", "Bearer " + authToken)
    .signatureCalculator(generateAndAddSignature _)  // eta-expansionでメソッドを値にして、signatureCalculatorメソッドに渡す
    .check(status.in(200 to 210))

まとめ

今回は、Gatlingでのシグネチャ検証にどのように対応するかをHMACの生成の一例とともにご紹介しました。

Scalaで自由にアルゴリズムを実装できるのは、Gatlingの強みです。 負荷テスト用にシグネチャ検証をバイパスするのではなく、シグネチャ検証も含めた負荷テストを実施するように心がけましょう。

遠隔地のメンバーと一緒に開発するためにやってること

開発

今回の担当はエンジニアの大橋です。 よろしくおねがいします。

唐突ですが、まず弊社のオフィス事情から……。
現在、弊社のオフィスは東京と名古屋の2箇所にあるのですが、
プロジェクトごとに東京か名古屋かで分かれているのではなく、
ひとつのプロジェクト内でも東京勤務の人と名古屋勤務の人で分かれている状況です。
自分が今担当しているプロジェクトのクライアント開発チームのプログラマーも
東京と名古屋で分かれています。

そのため、情報共有やコミュニケーションのしづらさが、とても大きな問題としてあります。
この問題を少しでも解消できないものかとチーム内でいろいろ試しているのですが、
まだまだ解消には至らないといった状況です。

ですが、今回の記事では、問題全体の解消には至らないまでも、
現在チーム内で取り組んでいることを書かせてもらおうかと思います。

グループチャット

チームメンバー全員が参加するチャットグループを作り、メンバー間でのやりとりをしています。
以前はChatWorkを使っていましたが、現在はSlackを使っています。
https://slack.com/

けれどもグループチャットにはいくつか問題があって、
これだけではコミュニケーション不足になりがちな印象です。

・文章で伝えづらいことが多々ある
・複数の話題が同時進行するとカオス
・会話の流れとは別のことを書きにくい

要所要所の連絡には十分かもしれませんが、 それ以上のことはなかなか難しい印象です。

毎日朝会

毎朝、東京と名古屋でビデオチャットを繋ぎ、メンバー全員で朝会をしています。
これはだいたい15分くらいのもので、
スケジュールなどの共有や、各メンバーごとに昨日やったことと今日やることの報告をしています。
また、それ以外にもメンバー全員に共有したほうがいいことはこの場で話します。
ビデオチャットにはZoomを使っています。
https://zoom.us/

これによってメンバーそれぞれが今何をやっているかある程度わかりますし、
口頭なので細かいニュアンスも伝えやすいいです。
ただ、次のような問題点も感じています。

・形式的になりやすい
・個々の細かい話題まで話せない(メンバー全員でやってるので)

気楽にビデオチャット

文章で伝えづらかったり書くのが面倒だったりすることや、込み入った話しになりそうなことは、
その都度、気楽にビデオチャットするようにしています。
ビデオチャットする前に会議室押さえて準備して、っていうような時間はかけたくないので、
たいてい自分のデスクや、デスクの島からちょっと離れたところで済ませます。
それほど大人数でなければ、ノートPC付属のカメラとマイクで十分ですので。

これにもZoomを使っています。
Zoomではチャット部屋のURLを伝えれば、それを踏むことでチャットに参加できるので、
チャットしたい人にURLだけ投げておいて、その人が入ってくるのを別の作業をして待つ、
というのが個人的にはいいかな、と思ってます。

気楽にビデオチャットをすることで、
チャットグループの「文章で伝えづらいことが多々ある」というのと、
朝会の「個々の細かい話題まで話せない」というのは解消されているのではないかなと思います。

timelineでつぶやく

ビデオチャットは強力ですが、基本的には何か必要があったときにするものなので、
今あの人は何をやっているんだろう?というのは、なかなかわかりません。
かといって、みんながグループチャットにいろいろ書き込みまくっては、
グループチャットがカオスになるだけです。
ということで導入したのがtimelineです。

Slackに個々のtimeline用チャンネルを作り、
今やってることとか、作業中に発生した問題とかを、それぞれ自分のtimelineにつぶやくようにしました。
また、誰かに質問したいことがあったときは、その人のtimelineで質問したりしています。

これによって、グループチャットだけだと問題だった
「複数の話題が同時進行するとカオス」「会話の流れとは別のことを書きにくい」
が、かなり解消された気がします。

オフィスに常時接続のビデオチャットディスプレイが設置されてる

オフィス内に1台、ビデオチャットで東京と名古屋が常時接続された大きめのディスプレイが設置されてます。
相手の人がチャットなどの呼びかけに気づく時間さえも惜しいときに、
この常設ディスプレイで呼びかけれれるので、普段はあまり使わないのですが、
たまに地味に役立ちます。

共有するという意識が必要

以上のようなことをチーム内でやってみてるのですが、
情報共有やコミュニケーションに関して少しずつ改善できているとは思いつつ、
まだまだ十分できているとは言えないというのが正直なところだったりします。

まぁ、いろいろやってみる中で思うのは、
結局はどんなことも意識的に共有しようとすることが必要という、
当たり前のようなことなんですが、
今の自分自身はちゃんとできてない気がするので、反省する毎日だったりします。

よくわからない反省文みたいになってしまいましたが、何かの参考になれば幸いです。

エラーにならなくなったLINQメソッド(Unity iOS)

Unity iOS

クライアントエンジニアの加賀です。

昔は何も知らずにLINQのメソッドを使うと、iOS実機で動かした時に以下のようなエラーが出ることがありました。

System.ExecutionEngineException: Attempting to JIT compile method

だいぶ前からですが、すこしずつ改善がされてきているので、現在の状況を一度纏めてみました。
※メソッドの実行結果が正しいかは、今回確認していません。
 あくまで、実行時にエラーが起きるかどうかを確認しています。

今回確認した環境は以下の通りです。

  • 2016/11/22
  • Unity 5.4.2f2
  • Mac OS X 10.11.6
  • iOS 9.2.1

検証結果を記載しますが、Result値の意味は以下のとおりです。

Result値 意味
o エラーにならない
x エラーになる

Average

エラーの条件

  • 引数に変換関数を渡すオーバーロード
  • TSource値型
  • TSource参照型(条件によってはエラーにならない場合もあり)

現在の状況

Scripting Backend Result
Mono2x o
IL2CPP o

Max、Min、Sum

エラーの条件

  • 引数に変換関数を渡すオーバーロード
  • TSource参照型

現在の状況

Scripting Backend Method Result
Mono2x Max
Min
Sum
x
x
o
IL2CPP Max
Min
Sum
o
o
o

FirstOrDefault、Last、LastOrDefault、Single、SingleOrDefault

似たメソッドとしてFirstがありますが、こちらは以前から問題ありませんでした。

エラーの条件

  • 引数に何も渡さないオーバーロード
  • TSource値型

現在の状況

Scripting Backend Method Result
Mono2x FirstOrDefault
Last
LastOrDefault
Single
SingleOrDefault
o
o
o
o
o
IL2CPP FirstOrDefault
Last
LastOrDefault
Single
SingleOrDefault
o
o
o
o
o

ToDictionary

エラーの条件

  • 引数にFunc<TSource, TElement> elementSelector渡さないオーバーロード
  • TSource値型

現在の状況

Scripting Backend Result
Mono2x x
IL2CPP o

ToLookup

エラーの条件

  • 引数にFunc<TSource, TElement> elementSelector渡さないオーバーロード
  • TSource値型

現在の状況

Scripting Backend Result
Mono2x x
IL2CPP o

または

  • 引数にFunc<TSource, TKey> keySelectorIEqualityComparer<TKey> comparer2つを渡すオーバーロード
  • TSource参照型
  • TKey値型

現在の状況

Scripting Backend Result
Mono2x x
IL2CPP o

Join、GroupJoin

エラーの条件

  • JoinGroupJoinのすべてのオーバーロード
  • TInner(相手のストリーム型)が値型

現在の状況

Scripting Backend Method Result
Mono2x Join
GroupJoin
x
x
IL2CPP Join
GroupJoin
o
o

または

  • JoinGroupJoinのすべてのオーバーロード
  • TInner(相手のストリーム型)が参照型
  • TKey値型

現在の状況

Scripting Backend Method Result
Mono2x Join
GroupJoin
x
x
IL2CPP Join
GroupJoin
o
o

OrderBy、OrderByDescending

エラーの条件

  • TSource値型

現在の状況

Scripting Backend Method Result
Mono2x OrderBy
OrderByDescending
x
x
IL2CPP OrderBy
OrderByDescending
o
o

ThenBy、ThenByDescending

エラーの条件

  • Func<TSource, TKey> keySelecterTKey値型

現在の状況

Scripting Backend Method Result
Mono2x ThenBy
ThenByDescending
x
x
IL2CPP ThenBy
ThenByDescending
o
o

enum配列のToArray

現在の状況

Scripting Backend Result
Mono2x x
IL2CPP o

まとめ

なんと、IL2CPPで出力した場合は、記事内の全てのLINQメソッドでエラーが起きませんでした!(全オーバーロードは流石に確認できていません)
また、Mono2xでも一部のLINQメソッドで改善が見られるようです。

iOSで64bit対応が必須になり、IL2CPPが使用され始めました。
その時点で、LINQはAOTエラーと決別出来ていたようです。

これで少しは安心してLINQを使うことができそうです。