KLabGames Tech Blog

KLabは、多くのスマートフォン向けゲームを開発・提供しています。 スマートフォン向けゲームの開発と運用は、Webソーシャルゲームと比べて格段に複雑で、またコンシューマゲーム開発とも異なったノウハウが求められる領域もあります。 このブログでは、KLabのゲーム開発・運用の中で培われた様々な技術や挑戦とそのノウハウについて、広く紹介していきます。

初めに

この記事は KLab Advent Calendar 14日目の記事です。

こんにちは、クライアントエンジニアの norm81 です。

初登場です、よろしくお願いします。  

経緯  

Unityでナビメッシュのベイク情報をプレハブにしたい、そしてアセットバンドルで運用したいという要望がありました。

既存のA*アセットなどを検証していたところ、Unity5.6からNavMeshBuilderが強化されたのでそちらで実現可能か検証しました。 

静的にベイクしたデータを用いたサイトをあまり見掛けなかったので今回纏めてみようと思います。  

検証に用いたUnityバージョンは5.6.3f1です。

結論

いきなり結論になりますが、上記の要望は対応できました。  

但し、制限があります。  

今回の方法において注意点も見つかりましたので、併せて下記に記載しています。  

導入

下記をクローンし、対象のプロジェクトに入れます。

https://github.com/Unity-Technologies/NavMeshComponents/

Assets/NavMeshComponents/フォルダをコピーしてねと書かれてますが、  

今回はAssets/Examples/フォルダも用います。  

手順

基本的には既存にあるナビメッシュの作成の通り、設定を行なっていきます。  

但し、Bakeは別途行うのでこのタイミングでは行いません。  

  

ヒエラルキーでナビメッシュの対象にするRendererコンポーネントを持つオブジェクトの親に、一つ空オブジェクトを作成します。  

そしてAssets/Examples/フォルダに入っているNavMeshPrefabInstanceコンポーネントをAddComponentします。  

01

そのオブジェクトを含むプレハブを保存した後にインスペクタのSelectボタンを押す、或いはプロジェクトウィンドウから保存したプレハブを選択すると、入れ子にあるオブジェクトが表示されます。

そのままNavMeshPrefabInstanceコンポーネントを持つオブジェクトを選択して、インスペクタのNavMeshPrefabInstanceコンポーネントのBakeボタンを押します。  

するとプレハブにNavMeshが追加されます。

確認 

Navigationウィンドウを開き、Show NavMeshを有効にした状態でWalkableのメッシュが表示されていれば成功です。

02

表示されていない場合、追加されたNavMeshを確認してみてください。Source BoundsのExtents値が(0, 0, 0)だと失敗している可能性が高いです。

03

下記の注意点を確認いただき、再度上記のBakeを試みてください。

成功した後は、このプレハブをアセットバンドルにすればそのまま運用可能です。

具体的な挙動については、上記NavMeshComponentsのソースコードを参考されることをオススメします。

注意点

NotWalkableを反映したナビメッシュがBakeできない。

従来のNavigationウィンドウでのBakeとは異なり、差集合のベイクがなされないです。  

対案としてMeshColliderを併用して目的座標に対して上空からのRayCastで判定を行い進入可能か調べる様なような二段構えの対応を検討しています。

FBXなどModelImporterを介するMeshを扱う場合、Bake前にRead/Write Enableを有効にする必要がある。  

04

プレハブに保存した後に無効に戻すのは問題なかったです。  

まとめ

現時点の外部データ化するメリットは、

  • ランタイムでベイクしなくて良いので処理コストが軽減できる。  
  • 1つの背景データと複数の外部データ化したナビメッシュを組み合わせることで、クエスト進行度などに併せてナビメッシュを切り替える運用ができる。  

といったところで、デメリットは注意点で記載したとおりになります。  

今回紹介した機能は折角の標準搭載された機能なので使い倒してみたいと思います。

以上

この記事は KLab Advent Calendar 2017 10日目の記事です。

こんにちは。このブログでは4度めまして、kakkun61 です。

この記事では、10月22日に開催された同人誌即売会技術書典3に KLab の有志で作った同人誌を頒布しましたので、その報告をします。

頒布した同人誌は電子版が無料で、この記事の下部にダウンロード用のリンクを張っています。

技術書典とは

技術書典は、プログラミングについての同人誌を作成しているサークル TechBooster達人出版会が主催する技術・科学系同人誌即売会で、今回含めナンバリングイベントが3回、超会議での超技術書典が1回開催されています。

今回は秋葉原のアキバ・スクエアで開催され、ユニークの来場者数では2750名とかなり大規模なイベントとなっています。

なぜ参加することにしたか

発案は筆者で、筆者は技術書典1と技術書典2そしてその間のコミックマーケット91とで Haskell の同人誌を頒布して同人誌を作る楽しさみたいなものを感じていたことと、KLab のアドベントカレンダーは過去2度ともすぐに枠が埋まってしまっていたので、社内に書きたいと思っている人がある程度いるのではないかと思い、会社に相談し会社として参加することになりました。

どう作ったか

TechBooster の『技術書をかこう!』にしたがって Re:VIEW を使い、GitHub 上で Pull Request 運用で作っていきました。

各章を1人で担当し、章ごとに PR を作成しレビュー後マージという運用をしました。ふだんのソースコードの開発と似せた方が分かりやすいかと思いこのようにしました。

どんな同人誌になったか

表紙

7名で執筆し、校正の協力に1名、表紙の協力に1名という体制のメンバーになりました。

内容は下記です。

  • 物理ベースレンダラーを Rust 実装して、表紙絵をレンダリングした話
  • Sprache を CPS 変換
  • Emscripten で動画再生する
  • テキストマクロプロセッサ「M4」のチューリング完全性
  • FPGA 初心者が試行錯誤しながら疑似乱数生成回路を作る
  • 家庭内ネットストーカーシステムを作った
  • とある KLab のスマホアプリのビルド事情

特にジャンルなどは指定せずみなが書きたいことを書いてもらったのですが、直接しごとと関係あるものは「とある KLab のスマホアプリのビルド事情」のみで、他は各々好き好きな内容になりました。

参加してどうだったか

さいわい印刷した冊数の7割ほど頒布することができました。印象としては KLab だからというよりは、内容で購入してくれていたように思いました。どれもコアな内容なので一部の人には刺さっていたようでよかったです。

メンバーでのふりかえりで、一般にも役に立ちそうなことを下記に抜粋します

ぱっと見てどんな内容の本か分からない

雑多な内容でタイトルに何も情報がないのでどんな本か分からなかったのは失敗でした。表紙に概要を書いたり、内容を書いたものを机に立てるなどしようと思います。

カラーのフェルトペンがあるとよかった

上の項目にも関連して、現地で札などを立てることになったときに黒ペンしかなかったので、見栄えが悪かったです。

人だかりができると立てたものは反対に見にくい

宣伝に札を立てたりしたのですが、人が近くで立って机を見たら上から見下ろすことになるので、そのときは紙を置く形の方がよかったです。机の前に人がいるいないで立てと寝かせとをうまく変えられるとすごくいいと思いました。

レビューに PR を使うことについて

今回は GitHub で PR を作る方式にしたのですが、いくつか問題に感じることがありました。

  • 書きかけの状態で全部の章を合わせてビルドするのが PR 方式だとやりにくい
    • マージしたブランチを作成しないといけないため
  • レビュワーが PR 上で指摘するのはリードタイムが長くなるので、明らかに問題のない修正はレビュワーが直接書きかえたかった

次回は、著者が直接 master にコミットし、レビュワーも直接コミットして訂正する方法を試そうと思います。

余談

調査不足でブースが隣りの Wantedly の書籍と名前かぶりしていました。「Tech Book ください」と言われて「どちらの?」となることがありすみませんでした。あちらの方が技術書典1からその書名を使っていらしたのでこちらがかぶせてしまいました。

電子版

ダウンロード

この記事は KLab Advent Calendar 2017 8日目の記事です。

こんにちは knsh14 です。 Unity で AnimationClip Editor を作った話をします。

KLab では様々な演出などで AnimationClip を使っていますが、Unity 標準の AnimationClip のエディタはどうにも使いづらいものになっています。

  • 各オブジェクトの並べ方が幅優先表示になっていて非常に見づらい
  • ショートカットがほとんど無い
  • 編集にじゃまなパーツを折りたたんで非表示にできない

などなどあります。 既存のアセット等でも対応できなさそうだったので、今回内製でエディタを作成することになりました。

実際の画面

sample

機能

エディタというのは単純だと思っていてもいろいろな機能があります。

エディタとしての機能

  • 新規作成、読み込み
  • 前回保存分を再開する
  • AnimationClip の情報の編集
  • AnimationCurve への KeyFrame の追加削除、値の編集
    • 変更はその場で反映される
  • キーのコピペ
  • キーを範囲選択して左右へ移動させる
  • 操作の Undo/Redo
  • データの保存

AnimationClip を編集するための機能

  • 今の状態を自動でプレビューできるようにする
  • シーン側でオブジェクトを動かしたりしたらエディタのキーフレームに反映される

基本設計

クラスやプロジェクト構成などは Clean Architecture を参考に作成しました。 Unity Editor 拡張で説明するより、 iOS/Android で解説されている資料のほうがより詳細にかかれていてわかりやすいと思うので、そちらを参考にしていただくのが一番いいと思います。

以下のような構成でできている仕組みです。

  1. Presentation 層

    1. View
      • UI を構築します。
      • UnityEditor.EditorWindow を継承し、アプリケーション全体の起動も担当します。
    2. ViewModel
      • Data 層の Entity を View で表示するためのクラスです
    3. Presenter (Controller)
      • View から受け取ったイベントを UseCase に流して処理してもらったり、データを取得したりする。
      • 本来なら Controller がイベントを受け取り UseCase に流す、 Presenter がデータを取得するという役割分担までするのですが、一旦まとめて実装しました。
  2. UseCase 層

    1. UseCase
      • 固有のロジックを実装します
    2. Translator
      • Entity を受け取り、Presentation 層で使う ViewModel に変換します。
      • Presentation から受け取ったものを Entity で扱えるようにしているところもあります。
  3. Data 層

    1. Repository

      • UseCase と DataStore の遣り取りをするための薄いインターフェース
    2. DataStore

      • Entity の集合で CRUD を実装します
      • DataStore をシリアライズして JSON に保存することで前回の状態から作業を再開できるような仕組みも実装できます。
    3. Entity

      • コアのデータ定義をします。
      • 例えば GameObject の ID、アニメーションするプロパティ、AnimationCurve のセットやショートカット名と実行するキーの組み合わせなどです

こうすることで以下のようなメリットがあります。

  1. UI と裏側のロジックを完全に分離できる

    • 特に Unity EditorWindow のイベントハンドリングは中々癖が強いので出来る限り一元管理できる仕組みにできたほうが都合がいいです。
  2. テストしやすい

    • 操作を UI から切り離しているので、操作ごとにテストを走らせるなんてこともできます
    • このエディタは一人で作っていたので簡単にテストできる仕組みは動作を安定させるために必須項目でした
  3. コードの再利用がしやすい

    • ショートカット機能では利用者が好きなようにショートカットの割当をできるのですが、これは別のウィンドウで行います。
    • そのために似た実装が増えるのは大変だし、共通化することでどちらかでバグが出たらすぐに気づけるようにしました。
  4. 実装にブレが出にくい

    • この領域では何をするかが割りときっちり決まっているので、実装にブレが出づらいです。
    • また後でメンテナンスする場合にも読みやすさが高くなります。

デメリットもあって、次のようなものです。

  1. ちゃんと理解してないとどこに何を書くのかわかりづらい

    • これは MVC などでも言えることだと思いますが、設計をしっかり理解してからじゃないとうまくかけないのはちょっとハードルが高いです。
  2. 当然ですがコードが長くなる

    • 強いて言えば程度のデメリットですが、当然たくさんコードを書かないといけません。

エディタを実装する

全ての機能を紹介するのは大変なので一部だけ抜粋してどのように実装したか紹介します。

Undo/Redo

Undo/Redo は自前で実装するのは結構たいへんですが、Unity には割りと簡単に Undo をサポートする仕組みがあります。 Undo したいオブジェクトをシリアライズされる状態にして、UnityEngine.Object から辿れるようにします。 UnityEditor.Undo.RecordObject(UnityEngine.Object obj, string title) で操作を記憶してやると、その操作が Undo スタックに乗って、Unity のショートカットで Undo/Redo することができます。

範囲選択してコピペ

エディタといえばコピペですね! ペーストは clipboard にあるものを取り出してキーを追加する操作をすればいいので簡単なのですが、意外と大変なのがコピーです。

コピー操作はキーフレームを clipboard に入れることで実装できます。 ただコピーと一口に言ってもいろいろなコピー対象があります。

  • パーツについてるプロパティのキー全体をコピー
  • パーツについてるプロパティのキーの一部をコピー
  • パーツについてる一部のプロパティのキー全体をコピー
  • パーツについてる一部のプロパティのキーの一部をコピー
  • フレキシブルに選択した範囲をコピー

この種類を全部対応するのは大変そうだったので、最後の「事前に範囲選択をしてからその領域にあるキーフレームをコピー」だけを実装することにしました。 編集する対象によってこの辺は変わることが多いと思うのでどの仕組みにも対応できるように作っておけると楽になると思います。

ショートカット

ショートカットは利用していただいてるデザイナの方にも非常に好評で作ってよかった機能です。

仕組みは簡単で

  1. View にショートカットに対応しているメソッドを用意
  2. キーイベントからキー入力と突き合わせて一致したメソッド名を取得
  3. リフレクションで実行

というフローになっています。
ただこれには問題点があって、これだと1発のキー入力しかショートカットに登録できません。
Ctrl-X Ctrl-O のような2段階ショートカットに対応するには、一旦キー入力をキューに保存するなどの工夫が必要になります。

苦労したところ

UIレイアウトがなかなか直感的に書きづらい

全部 C# で書けるのは割りと楽なことも多いのですが、HTML で書いてこの要素にイベント仕込むだけならもっとUI作成も楽なのになあと思うことも多少あります。 またレイアウトではどうしても右寄せ左寄せなどの配置が難しいので、キーフレームの描画などは苦労することもありました。

またいろいろなデータを描画しようと思うと描画順で頭を悩ませることもありました。
処理的にはここでひとまとめに書くのがシンプルなんだけど描画を考えるとあとでわざわざ描くといった苦しいコードになることもありました。
depth 欲しいです。

Unity Editor 拡張のイベントハンドリングは辛い

Unity のイベントハンドリングは UnityEditor.Event.current を見てハンドリングするのですが、個別のUIに操作を割り当てるのがかなり苦手な感じを受けました。   ボタンやUIの値が変更された場合は割りと簡単に個別のハンドリングができるのですが、ドラッグやショートカット用のキーイベントなどになると途端にシンプルに書きづらくなるので、注意する必要があります。

終わりに

今回は Unity の Editor 拡張でエディタを作るという、Unity を使っているだけならなかなかやらないような話をしました。   ちゃんとしたエディタを一通り作るのは Unity の力を借りてもかなり大変でした。 普段は何気なくやっている操作も色々試行錯誤がある上にできていると思うと有り難みもましてきます。 世の中のテキストエディタなどを作っているエンジニアの方々の苦労が忍ばれます。
この文章を書いている Vim のコントリビューターの方々には尊敬の念を禁じ得ません。

Unity 2017 では標準の Timeline がかなり便利なので、そちらの UI を手軽に Unity 5 系でも使えたら嬉しいなあと思います。

明日は9日目です。hohean さんの記事です。お楽しみに

↑このページのトップヘ