ぷらこあ

ゆるふわゲームクリエイター / イベントオーガナイザーを目指してます

5月社内ゲームジャムの成果物「DrawBungeeRope」/ LineRendererで線描画する話

社内ゲームジャムにて

gyazo.com

  • バンジージャンプする人の紐を書いてあげるゲームです。
  • 今回は紐の描画にLineRendererを使ったので使い方を書きます。

LineRenderer

使い方

  • LineRendererは特定の座標間に直線を描画する。

  • 動的に描画しない / 描画してから動かない のであればインスペクタで座標を指定する

    • Positions->size に指定する座標の個数を入力する
    • Positions->ElementX に座標を指定する

gyazo.com

  • 動的に生成したい / 線を動かしたいのであれば、スクリプトで座標を指定する
    • 以下はドラッグ時に線を描画するサンプルコード

      using UnityEngine;
      using System.Collections;
      using System.Collections.Generic;
      using System.Linq;
      
      public class Rope : MonoBehaviour {
      
          public List<Vector2> drawRopePositionList = new List<Vector2>();
          private LineRenderer lineRenderer;
      
          void Start () {
              lineRenderer = GetComponent<LineRenderer>();
      
              // 線の描画を有効にする
              lineRenderer.enabled = true;
          }
      
          void Update () {
              if (Input.GetMouseButton(0)) {
                  Draw();
              }
          }
      
          void Draw () {
              Vector2 mousePosition  = Camera.main.ScreenToWorldPoint(Input.mousePosition);
      
              // drawRopePositionListは後にロープの長さの計算を行うため作成している
              // 線を描画したいだけであれば直接、LineRendererに座標を格納するので良い
              // ただし、余計な描画は避ける為に、最後と同じ位置であれば座標を格納しないようにしている
              if (drawRopePositionList.Count == 0 || (mousePosition != drawRopePositionList.Last())) {
                  drawRopePositionList.Add(mousePosition);
              }
              if (drawRopePositionList.Count > 0) {
                  // 座標の格納可能数を更新する
                  lineRenderer.pSetVertexCount(drawRopePositionList.Count);
                  Vector3 lineRendererPosiotion = new Vector3(mousePosition.x, mousePosition.y, -1.0f);
      
                  // 座標を格納する
                  // SetPosition(index, Vector3)
                  // 既にindexに座標が格納されている場合、更新される
                  // これを利用して毎フレーム毎に伸び縮みする線の描画等も可能
                  lineRenderer.SetPosition(drawRopePositionList.Count - 1, lineRendererPosiotion);
              }
          }
      }
      

描画する線の色や質感を変えたい

  • まず適当なMaterialを作ります
    • Projectビューより create -> Material
  • 作成した Material を LineRenderer -> Materials にて指定する

    • Size を変更することによって複数の質感を同時に適応することも可能
  • (1) Material 自体の色を変更するやり方

    • Material にて “Shader” を “Standard” に変更
    • MainMaps の “Albedo” の項目にて好みの色に変更する
    • 他のパラメータもよしなに変更する
  • (2) LineRendererのParamatersのStartColor/EndColorを変更するやり方

    • Material にて “Shader” を “Particle -> Additive(Soft)” に変更
    • LineRenderer にて Paramaters -> StartColor/EndColor をよしなに変更する
    • このやり方であれば、α値を変更することで線を透過させることも可能

gyazo.com

  • スクリプトからも変更出来るので線をフェードアウトさせることも出来る

    public IEnumerator FadeOut () {
        float a = 1.0f;
        while (a > 0) {
            Vector4 color = new Vector4(1.0f, 1.0f, 1.0f, a);
    
            // SetColors(StartColot, EndColor)
            // 線の先頭と末尾で同じ色を使用しているので同じ値を指定している
            // 先端から徐々にフェードアウトしたい、みたいなケースは個別に指定が必要
            lineRenderer.SetColors(color, color);
            yield return new WaitForSeconds(0.1f);
            a -= 0.1f;
        }
        // α値が0になったら線の描画自体をやめる
        lineRenderer.enabled = false;
        yield break;
    }
    

線がSpriteよりも後ろに描画される

gyazo.com

  • Material に Particle を指定している場合のみ。
  • LineRenderer に限らず Particle は同一の SortingLayer にて Sprite の背面に描画されてしまう。
  • Particle 専用の SortingLayer を用意して、その SortingLayer を前面に出すやり方が簡単。
    • SortingLayer は描画に関するレイヤー
    • Layer は物理挙動に関するレイヤー (異なるレイヤーであれば衝突しない、みたいな設定が出来る)
    • 以下のテラシュールブログさんの記事がすごいためになる。

tsubakit1.hateblo.jp

Unityのスプライトの描画順は「SortingLayer、Order In Layer、Z値」の順番で設定します。

  • レイヤーの追加

    • 上部メニューより Edit -> ProjectSettings -> Tags and Layers を開く
    • SortingLayersに適当な名前のレイヤーを追加する
  • レイヤーの指定(インスペクタ)

    • SpriteRenderer に SortingLayer を指定する箇所があるのでそこで指定する
  • レイヤーの指定(スクリプト)

    • LineRenderer のように SortingLayer の指定箇所が無い場合はスクリプトにて指定する

      private LineRenderer lineRenderer;
      void Start () {
          lineRenderer = GetComponent<LineRenderer>();
          lineRenderer.enabled = true;
          lineRenderer.sortingLayerName = "Particle";
      }
      

Unite2015Tokyo Day2メモ

  • ざっくり自分用メモ
    • uGUIパフォーマンスの話が特に参考になった
    • 英語や上級者向けの公演全然付いて行けなかった…
    • Urban Coaster死ぬかと思った…

Unityパフォーマンスチューニング

ゲーム作成時のオプティマイズ

  • FPS (30-60なら滑らか)

    • CPU: ゲーム挙動/物理挙
    • GPU: shader/drawwcall
  • Hiccups

    • Spikes (物理挙動のリビルド等)
    • Loading

Unityプロファイラ

  • プロファイラで見れるもの
    • CPU/GPU/Audio/Physics/Memory usage
  • Unity5はパーソナル版で誰でも使える様になってるよ

CPUプロファイラ

  • 時間がかかっている順に表示
  • ゲームが実際に動いている最中に表示出来る

CPUプロファイラ: タイムライン

  • 何が起きたか視覚的に把握出来る
  • 同期/何かが起きたときに中断が起きているなど

メモリプロファイラ

  • ヒープ用にかなりメモリを割り当てている
  • 詳細を見ることが出来るが負荷的にスナップショット的な活用が望ましい

LOADING DATA

  • データ種別
    • シーン
    • シーンが依存するアセット
    • リソース/ストリーミングアセット/WWW
  • 自分の好きなローディングパイプラインを作ることを可能

  • 非同期ローディング

    • Application.LoadLevel *Async
    • AssetBundle.Load* Async
    • 5.0: Resources.LoadAsync
    • Batch size still matters
    • 5.0: texture continue to load in background
  • シーンローディング: メモリの消費

    • 現在のシーンは新しいシーンがreadyになるまで取り込まれない
    • アセットに関しても同様
    • メモリスパイクが発生するときの対処
      • 空のシーン(loading)を用意し、古いシーンをpargeしてから新しいシーンを読み込む等
  • ローディング: シリアライゼイション

    • Unityのシリアライゼイションを高速である
    • 違うバージョンに関しても互換性がある
    • 元々はリフレクションをその場でやっていたので遅かった
      • Unity4.5以降で改善
    • 将来
    • ブロブ化する (mecanimが使用しているやり方)
  • ローディング: アセットバンドル

    • プレイヤーの再是の最適化
    • build timeの最適化
    • ローカル/Webサーバから高速データ取得
      • WWW.LoadFromCacheOrDownLoad();
      • 全てのデータをバンドルすることが出来る (WWW特有問題の解決)
  • UNLOADING

    • オブジェクトの削除作業のスレッド上での実施
    • Resources.unloadUnusedAssets / GC.Collect
    • 安全な仕組みが無い
      • 今使用しているアセットか否かを判断出来ない
  • GC パフォーマンス

    • GC.Collect によりスパイクが発生する
  • GC オプティマイゼイション

    • GCが起動しない様にする
    • GCを高速で動く様にする
    • リファレンスが密にパッキングするような設計が必要
    • classの代わりにstractにする (インラインになる)
  • REDUCE GC WORK

    • レファレンスするようなデータをパックする
    • メモリの移動量を減らす / メモリを消去する
  • RESULTS

    • GC for array length of 1,000,000 charactoets on MBP
    • Class with randomized memory locations: 35ms
    • Class with linear memory: 20ms
    • Struncts: 10ms
    • Strunct and no String: 0.18ms
  • MINIMIZING MANAGED ALLOCATIONS

    • Reuse temporary buffers
    • Allocate pools of reusable
    • Use structs instead of classed
    • OnGUIは使用しないで new UI System を使ってね

プール

  • GC chrun

    • Instantiate/Destroy overhead
  • プール方法

    • プールの中ではdictionaryは使わない、Listを使うのが良い
    • 事前に暖めておく
    • プールの中のオブジェクト
      • 使用するときにSetActive(true)
      • 画面外へ置いておく
    • 5.0 においては Instantiarion / actibvation のパフォーマンスが50%程度改善している
  • 一般的なパフォーマンス関連のコツ

    • GameObject.Find避けよう
      • 結果をcacheするのもいいだろう
      • GetComponent使うのもいいだろう
      • direct linkage or managers
    • 過剰なトランジションを避ける
    • 全てMonoBehaviorを使う必要が無い / 通常のC#Classを使う
    • GameObjectも必ず使う必要がない (transform等データ格納しておくといいだろう)
    • 階層の深い子オブジェクトの transhorm の変更は親に影響が及ぼすので避ける

将来的に

  • メインスレッドから処理をどんどん剥がして行く
  • ストリーミングの改善/最適化
  • GCを静的に
  • transformの階層化に対する負荷を下げる
  • 更ならプロファイリングツールを!

まとめ

  • 非同期ローディングしよう
  • メモリの利用パターンを意識しよう
  • データをレイアウトする際にゲームパフォーマンスを意識する
  • オブジェクトをキャッシュして再利用しよう
  • パフォーマンスの最適化のためにプロファイラを見よう

Unityのシーンを紐解き把握するには

  • 今回話す内容
    • プロジェクトをサクっと読む方法
  • 何故こんなことが必要になったのか
    • バグレポートの構造解析
    • サンプルシーンの解析
    • コード記載するの面倒
      • 昔作ったプロジェクトが読めない
      • シーンの構造やメタデータをごにょごにょする話し

シーン構築のルールを確認

  • プロジェクト>シーン>オブジェクト>コンポーネント
  • プロジェクト
  • コンポーネントはコールバックで動作する
    • 始点はコールバックから
    • Start/Update/FixedUpdate/OnCollisionEnter…
  • コンポーネント動かない条件
    • 非アクティブなオブジェクトは動かない
    • 参照もコールバックも無いと動かない
    • コンポーネントを持たないと動かない
  • オブジェクトへのメッセージ
  • コンポーネントへのメッセージ
    • event/UnityEvent/StartCoroutine
  • 参照手法例
    • GetComponent
    • GetComponentInChild/Parent
    • FindWithType/FindWithTag
  • オブジェクトを作る方法
  • オブジェクトの元を得る方法

ルールを基に情報を集める

  • コンポーネントの呼び出しの把握
    • どのコンポーネントがいつ動くのかが大事
      • コールバック (OnCollider/OnTrigger/OnMouse/SendMessage…) を持つか?
      • ランタイムで増減する
  • コンポーネントの列挙

    • コンポーネント一覧からからコールバック一覧を取得するエディタ拡張作るハック
  • IEventSystemHandler

    • IEventSystemHandlerを継承している場合はインスペクタで確認出来る
    • e.g) uGUI>button>InterceptedEvent
  • 文字列のメソッドコール

    • 任意のメソッド名で呼ばれる (AnimationEvent/SendMessage/EventSystem)
    • コールバックとして計上しておく
  • コンポーネント参照元の確認

    • 無理
    • オブジェクトを消したときのリスクが不明
    • 参照情報を元に被参照リストを作る
  • 三章先の座標の確認

  • handlerを使って矢印を貼ると紐付けを確認しやすい
  • 量が多すぎると混乱するのでストリップする仕組み

  • 以下を参照リストから削除する

    • オブジェクトの親子関係で構築した参照
    • オブジェクト内で自己完結している参照
    • 選択中のオブジェクト内での参照
  • どこからも参照されないオブジェクト

コンポーネントの依存関係

  • Monodevelopで検索 > シーンで使用されているかを特定出来ない
  • エディタ拡張書く

    • MonoScriptでMonobehaviourのコードを取得する
  • 参照関係をグラフ化

  • Model

どういうオブジェクトか

  • マネージャー系オブジェクト

    • オブジェクト総数が1つでコンポーネント的な参照が多い場合
    • 大抵シングルトン
    • 外部からのメッセージを受けて動作する方が多い
  • ギミック系オブジェクト

    • コライダー等で自己完結するオブジェクト
    • Playerへの参照があるかないかくらい
    • トリガーやアクションをマネージャーに通知するタイプも居る
    • ステージ系のゲームにありがち
  • Updateで頑張るドン

    • メインオブジェクト
    • 多くの参照を集めている対応でおおい
    • Updateやコルーチンで自発的に動く
    • コードを見れば処理が判る

そのオブジェクトがどうやって参照されるか

  • 参照先の状態 (パラメータ) を注目する
  • 自分で動くか管理されるかの似たく
    • 被参照が一つの場合管理されている可能性が多い
    • 被参照が多い場合、自分で動く可能性が多い
  • タグを保つ場合、FindWithTagが使われてる

    • 親子関係で検索される
    • 名前で検索される場合もある
  • 対マネージャー (シングルトン)

  • 何故参照を持つのか

    • 検索のキャッシュ? …
    • 判るような命名規則付けるのが一番ですね!

そのオブジェクトはどこから持って来たのか?

  • 生成コードの検索

    • シーン無いに最初から配置されているか?
    • シーン内でオブジェクトを生成するコードは検索する必要がある
      • Instantiate
  • 該当のプレハブを持つシーンを探す

    • LoadLevelAditiの場合、ロードするシーンを探す
    • 生成物がプレハブの場合、事前にシーン内の参照情報を保持しておく
    • ReferenceViewer (エディタ拡張マニアクス)
  • YAML変換してgrepしよう

    • UnityYAMLMergeが入って (smart merge) シーンやプレハブのマージが可能に

このシーンはどんな構造なのか

  • 実行時にシーンが持つコンポーネントを知る
  • オブジェクトの役割と参照関係を知る
  • オブジェクトが作られる条件を知る
  • コンポーネントの動くタイミングを知る
  • オブジェクトの動きを把握すると大体シーンの構造が判る

UnityGUI開発至難 (FAST UI BEST PRACTICE)

  • パフォーマンスの高いIF
  • Unity5のフレームデバッガ
  • バッチング処理

バッチ処理の基礎

  • 決まった順番でメッシュがレンダリングされる
  • 決まった筆が無いと描画されない (プロパティ毎に)
  • ステート変更に時間がかかる
  • 同じステートのメッシュは1つのバッチと捉えて、1回のdrawcallで描画される
  • オブジェクトをバッチにグルーピングする処理をバッチングという
  • テクスチャの変更は速い / マテリアルの変更は遅い
  • マテリアルの変更
    • シェーダの変更が入るのが遅い原因 (リビルドが挟まる)
    • SetPassCallはこの遅い変更のことを指す
  • Statuisticsを見るとバッチ数とSetPassCallが表示される

バッチング

  • バッチング vs バッチングしないケース
    • どう見た目が異なるかデモ
  • バッチをどのように計算されているか
    • 内部ルールで決まってくる
    • マテリアル変更/マテリアルプロパティが共有された/要素がオーバーラップされた場合

FrameDebuger

  • 何がバッチとしてまとめられるか見られる
    • Window>FrameDebuger
    • どのシェーダ/マテリアルプロパティ/頂点数
  • Canvas単位でBatch処理を行う
    • CanvasInCanvas は独自のバッチを生成
  • バッチ生成のルール

    1. 同じマテリアルである必要がある
    2. バッチが切れるのはテクスチャ/マテリアルが異なる/変更する場合
    3. エレメントが重複配置している場合はバッチが切れる場合はある
    4. バッチングソーティングの話
      • UISystem
    5. (Unity5.2) Canvasからの同一平面性が壊れる場合、ソーティングを切る
    6. 例えばzが異なる場合バッチンググループによって表示が崩れてしまうので
  • マテリアルの変更は最小限に抑える

    • 同じマテリアルを使う必要がある
  • 5.2: テキストとノーマルUI要素は同一のマテリアルとして扱う

  • テクスチャー

    • UIの中での変更を抑えよう
    • spriteAtlasなど一つのテクスチャーにパッキング居ておく必要がある
    • Textは動的変更なのでテクスチャは異なる = バッチングが異なる

サンプル

  • 25のDrawCallが発生するシーン
    • Canvasから離れている > 同じz座標へ
    • Textureが異なる > SpriteAtlas > パッキングタグを付けてSpriteEditorにてパックする!!

CanvasRenderer

  • スクリーン上に現れる全てのUI要素が所持する
    • texture / mesh / color を保持する
    • Text / Image を使うときには必ず付与される
  • 変更するとバッチングのし直しが発生する
    • バッチの計算し直し
      • マテリアル/テクスチャーの変更
      • 遅くも速くもないので出来れば避けたい
    • 階層の順番が変更されたとき
      • 親に対して子が追加された/子の順番が変更された
        • 遅いのでなるべく起きない様にしたいよね

PixelPerfect

  • スナップ処理
    • 矩形と大きさを合わせる処理
    • 遅いので出来るだけ使わない方にするのが良い
    • オブジェクトを動かすときだけON、動かし終わったらOFFにするなど工夫出来る
  • ScreenSpaceCanvasのみ機能する

Custom UI Elements

  • 独自のグラフィックを作成する
  • 独自のカスタムレイアウトを作成する

  • ICanvasElementという概念

    • いくつかのメソッドを付与する必要なある > Rebuild
    • rebuild callbacks
      • Prelayout
      • Layout
      • PostLayout
      • PreRender
      • LatePreRender
  • イベントのトリガー
    • CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild();
    • CanvasUpdateRegistry.RegisterCanvasElementForGraphicRebuild();
  • イベント処理のタイミング
    • [FIXME] スライド公開されたら見る
  • リビルドがトリガーされる例
    • OnRectTransformDimensionsChange
    • OnTransformParentChanged
    • OnTransformChildrenChanged (for layout group)
    • OnCanvasGroupChanged
  • ショートカットも用意されてるよ
    • 以下を継承する
      • Graphic
      • Selectavle
      • LayoutGroup

More Information

  • セッション: ロードマップ
  • 検索: フレームデバッガー
  • 検索: スプライトパッカー
  • コード: Unity UI bitbucket

白猫プロジェクトの裏側

開発フロー

  • プロトタイプ 2-3名 1ヶ月
  • アルファ版 10-13名 4ヶ月 (アクションの基礎が楽しめる完成度)
  • ベータ版 15-18名 4ヶ月 (ゲームサイクルが回せる程度)
  • リリース

  • 開発特徴

メモリ/パフォーマンス

  • 基本はキャッシュ

    • e.g) Instantiate
    • ダメージ表記: 処理落ち
      • Before: if (action.hit) { Instantiate(DamageNumber); }
      • CachedObjectManeger.Instance.OreCache(obj, num); // 生成個数
      • CachedObjectManager.Instance.Borrow(obj);
    • AudioClipキャッシュ
    • エフェクトのキャッシュ
      • 今回は断念
      • ParticleSystemをActiveにしたときに別の座標に表示されることがあった
      • ParticleSystem以外の制御も必要だった
      • キャッシュを前提にしたルール大事
  • GPU側のボトルネック

    • マップ画面で処理落ち
    • 海をキラキラさせるシェーダ
    • フラグメントシェーダーで波のアニメーション計算していた (sin使用)
      • バーテックスシェーダへ波の計算を移行した
      • 使っていない変数に計算値をセットしてフラグメントシェーダに渡す
    • シェーダーの一括変換
      • 必要の無いカラー計算をしているシェーダーを一括置換
      • PC用のシェーダー使用も一括置換
  • 起動時間の拘束か

    • タイトル出るまで Androidで25秒 / iOSで1分
    • AssetBundleは現在約3万種類 Caching.ready になるまでが遅い (12万ファイル数程度)
    • 独自のキャッシュシステムを作る
      • Cacheing.ready を待たずに起動速度を速く
      • WWW.LoadFromChaceOrDownLoad 使わない (コロプラのゲームではもう使ってないよ)
      • AssetsBundleのバージョン管理が出来る必要がある
  • 自前で用意したキャッシュシステム

    1. 起動時にAssetBersionListをダウンロード (path_versionNumber の形式)
    2. PlayerPrefに保存されているversionを比較
    3. 更新されていたらダウンロード
    4. ストレージへの書き込み
    5. PLayerPrefabsに新しいバージョンを入れる
    6. 1分から8秒に
  • ファイル読み込む数の問題

    • iOSで開けるファイル数は256個 (255個?)
    • カットシーンで大量のAssetsBundleをダウンロードしていた
    • バックグランドでのダウンロードを増やしたせいで引っかかった
      • 問題点として原因が特定しにくい
    • 1ファイルずつCloseしOnCompleteで何も行わない様にして解決

メモリとプラグラムサイズの最適化

  • 不必要なdll, コードの削除

    • AssetsStoreで購入した者のサンプル等は削除するかEditorフォルダに入れる
    • 同様の機能を行う者が既に入っているのにdllをリンクしてしまっているケースがあった
    • .jsがあると Boo.lang.dll がリンクされるので必要なければ消しておく (アセット内注意)
  • Stripinglevelの変更

    • UnityEngine以下の必要なコンポーネントまでStripされることがあった
    • Linkerシーンを作成
      • 必要なコンポーネントを持つオブジェクトをシーンに配置する (使っておく)
      • シーンの作成には自動でコンポーネントを抽出してGameObjectを生成
      • AwakeでルートをDestryoy
  • AssetsBundleのメモリリークの繻子エイ

    • 明示的にReleaseする必要がある管理方式
    • 特定のOwnerがDestroyされてAssetBundleが開放されない
      • Xcodeを使って調査した
      • FrameDebuggerでVRAMの中身をチェックして破棄されてなければならないテクスチャを調査

今後の改題

  • CharactorController使ってる
    • 重い / Unity5で挙動変わってる
  • UIの構築用ではない軽量な2Dアセットを探す / 作る
  • キャッシュで来て大量に表示出来るエフェクトシステム
  • ダメージパケットなど大量に送信する際のバッチング

リアルタイムサーバー

サーバシステム構成

  • [FIXME] そのうち画像上がるだろう

リアルタイム通信

  • host: 共闘で必要になるどー来データのマスターデータを持つ
    • ボスデータ
    • 自キャラ
    • ステージギミック
  • guest
    • 自キャラ
    • hostユーザからデータを貰う
  • (雑魚キャラは動きは同期していなくて生死のみ管理)

  • 通信保証データ

    • データが受け取れないと進行布野になるような重要度の高いデータは受け取り済みであることをコールバックする
    • コールバックがなかったら最初からリトライ
    • 接続の有無は定期的にpingを送信してサーバ側でpingがないユーザは切断判断する

クライアントサーバ注意点

  • クライアントのサーバのデータ不一致
    • サーバのデータをコピーしてクライアントが持つ場合不一致が生じる
    • リクエスト成功、レスポンスが無い場合
    • モバイルは通信環境によって接続される
  • データが不一致だとサーバ側でエラーが発生する
  • トークンを付与したリクエストを送る
    • トークンをキャッシュして、通信切れた場合に再度トークンを付与してリクエストを送る
  • DBの最大値を入れてテストする
    • MySQLではBigintで管理していた値をクライアントでは int (System.Int32) で管理して事故発生
    • DB側をintに合わせて対応した…

Unityで音を制す

CRIミドルウェア

  • CRI ADX2
  • CRI Sofdec2
  • ファイルマジックPRO

ゲームサウンドに求められるもの

  • データサイズを小さく
  • メモリ使用量を小さく
  • 気持ちのいいサウンド
    • 切り替えの滑らかさ
  • ゲーム情報としてのサウンド
    • ユーザ通知を判りやすく
  • キャラや世界の表現
    • ボイスや環境音/賑やかさ

ADX2が変えるワークフロー

圧縮コーデック

  • ADX/HCA/HCA-MX(これが一番ゲーム向け/多数再生向け)
    • 極端に圧縮率が劇的に変わる訳ではないので注意

イントロつきループ再生

  • ループポイント付き波形の圧縮/再生に対応

事例紹介

  • 乖離性ミリオンアーサー

    • SocialGameInfo 採用事例のインタビュー
    • 台詞再生時のBGM音量調整
    • BGMは微妙な増減程度 (BGM聞きたいユーザ向け)
    • 企画の方が音の調整していた
    • オプションの音量設定
      • データにカテゴリー情報を入れて、カテゴリへの音量指定
    • サウンドパックファイル: 1音1パックファイルに近い > ファイルマジックによるパック
    • ストーリーの音量は章毎に別途ダウンロード
    • チュートリアルプレイ中に追加データのダウンロード
  • 七つの大罪 ポケットの中の騎士団

    • 5人のボイスが一斉に
    • ストリームで再生しているので普通は合わせるの大変
    • プログラム側で再生紙
    • BGM26曲/SE25種/ボイス1800種
  • ファントムオブキル

    • フィールド曲とバトル曲のつなぎ込みに工夫
    • 同期再生して音量をインタラクティブに変化させてる
    • ボイスの圧縮 5800種 1500MB > 150MB
    • キャラボイスはキャラ毎 1キャラ100ボイスぐらい
    • 追加のBGMのみダウンロードしてくる

サウンド制作から組み込みまで

  • 通常のワークフロー
  • ADX2入れた場合
    1. 演出設定とプラグラムの分離
    2. サウンド担当者が演出設定まで担当する

開発支援

  • リアルタイムサウンド変化
  • 実行中のアプリで直接サウンド調整
  • 音ゲーの楽曲と踏めん表示のタイミング合わせを支援
    • プログラムによる楽曲再生とスピーカーからの発音の遅延時間の通知

Unityを利用したスマートフォン向けゲームアプリ開発へのアプローチ方法

会社紹介

  • SummerTimeStudio
  • 沖縄の会社だよ / 沖縄出身のエンジニアが多いよ
  • ココイチ戦争
  • 開発合宿

開発スタイルと特徴

  • スマートフォン/タブレットに特化

    • コンシューマー向けの3D技術活用
    • 全世界のユーザへスピーディにクオリティの高い3Dゲームの提供可
  • コミュニケーションン工藤開発

    • 会議フォーマットの撤廃
    • 問題点/疑問点をその場で解決する
    • 話した内容に付いてはすぐにメモして共有
    • 全員がフラットな立場で話し合う
      • 一人一人が主体性を持ったものづくり
    • 各プロジェクトに3名のメンバーをアサイン
  • 小数精鋭のスポード重視

    • プログラマ1名
    • 3Dアーティスト1名
    • 2Dアーティスト1名
    • プロジェクトの規模や開発フェーズに応じて柔軟に対応
  • 最小限のルールで柔軟に変化

    • 時代の流れや環境の変化に合わせた最良を追求

開発環境の構築プロセス

  • サマータイムスタジオに入る前のこと

    • 3Dゲーム開発を0からいろりおと構築してみた
    • AndroidSDK/Eclipse
      • OpenGL/GynamicFont対応/3Dモデルフォーマット設計/Mayaのネイティブプラグイン
      • これは一人では無理だ
    • 3Dの開発には必要な者が多すぎる
      • そんな時に思い出したのがUnity
      • あっという間にプロトタイプ完成した
  • 今までは自分が作ることが多かった

    • 動く者を作るのは楽しんでやれる
    • 自分で作れば自由に最適化出来る
    • 過去のノウハウで何とか乗り切れてしまう
  • Unityをそのまま使ってみる

  • 実感したUnityの弱み (3.x当時)
    • スマホ/タブレット向けに最適化が進んでいない印象
    • LoadLebelで画面が止まってしまう / 特定の端末で不具合
    • 2D描画弱い
  • ただしプラグイン/アセットで補完

    • ユーザが多く問題が解決されている
  • スマホ/タブレット向けの効率化

    • Unityの中で起きている問題は対応難しい
      • その機能を避ける
      • 実際はUnityのバージョンアップに伴い解決が進んで行った感じ
    • マルチプラットフォーム対応の効率化
    • Android/iOSでの差異を九州
    • アプリ内課金の実装
    • アチーブメント、リーダーボードの実装
    • モバイル向け広告の実装 … etc
  • タイトル固有部分以外の効率化と安定化

STFramework紹介

  • STFramework.Initialize()を呼び出す
  • InputManager
    • input.GetTouch() はエディタ上で動かない
    • UnityRemoteで動作進化あった
    • エディタ上でも気が売るに動作確認したかった
    • マウス入力をタップと同じフォーマットにして返すだけ
      • マルチタップはUnityRemote必須
  • SceneManager
    • Scene切り替えをスムーズにしたい
    • Sceneの遷移や管理を自動化
      • 初期化、破棄処理をコルーチンで実装
      • シーン遷移におけるコールバック処理
      • Scene毎にクラス定義が必要
  • UIManager & UI Components
  • PurchaseManager
  • XMLImporter
    • データテーブルの管理はベタよりExcelなどを使った方がよい
    • Excel -> XML出力して読み込む
    • ScriptableObjectに対応して余計なコンポーネントの作成を不要に
    • 一定の規則に従い暮らす/XMLを作成することでXMLインポートとデータの更新を自動化
  • その他

今後の課題

  • Unity5への対応・最適化
  • エディタ拡張の整備

Unite2015Tokyo Day1メモ

Unite2015とは

  • 年に1度のUnityのお祭りです
  • 以下、自分の取ったメモ
    • スライドが全公演に対して公開されるので一時的なものである認識

基調講演

http://pc.watch.impress.co.jp/docs/news/event/20150413_697587.html

UnityProfessionalEdition

  • チームラインセンス
  • パフォーマンスの速報 (PreView)
  • UnityAssetsStore Level11 Deals
    • AssetsStoreをとても得に使える仕組み
  • ロイヤリティ無しで使える

UnityPersonalEdition

  • Unity5エンジンの全ての機能を使えるようになったよ
    • 従来のPro版で制限されてた機能含む
  • ロイヤリティ無しで使えるよ
  • 100万の利用者

IncredisbleGraphics

  • 物理ベースレンダリング
  • グローバルイルミネーション
  • サンプル動画(3人/短期間)

REPUBLIQUE

http://www.camouflaj.com/

  • Unity5で物理ベースシェーダーによりリアルな質感を表現
  • これから作るゲームをもっと美しくなる
  • 感情を与えていい体験をしてもらう
  • 無料でプロダクト公開!

  • Lighting

  • Mechanim
    • Entry -> Exit が見える様になって判りやすいよね
  • AudioMixer
    • 3DサウンドかどうかはMixierでコントロールする様になった
    • MixerGroup (チャンネル) 単位で設定してよね
    • snapshotによって場面による音量設定など
    • ダッキング
      • 他の音を下げてね、等の調整が聞く

Unity5 feature

  • 64bit版のエディタ対応
  • PhysX 3.3 upgrade
  • animationシステムの刷新
  • AudioTools

マルチプラットフォーム対応

  • 6つのプラットフォーム対応大変だったよ、更にやってみよう
    • 21のプラットフォームを対応
    • 1からの作業だった
  • WebGLサポート
    • IL2CPP C# -> C++ -> WebGL
    • RaTraceBenchmark - iPhone6 MonoARMv7 -> IL2CPP (約8倍のパフォーマンス)
    • PATH FINDER 1023agent 14fps -> 40fps
  • IL2CPP
    • 全てのプラットフォームに対応させたい!!

Massive R&D

  • 300人あまりの開発者が関わってる
  • core / cloud / longer / R&D team
  • new ニンテンドー3DS 今年夏β : ブースでも触れるよ!!

VR (Oculus/パルマーさん)

  • GearVR で課金プラットフォームのリリース
  • VRはどんどん広がって行くよ!!
  • Unity 5.1 のインテグレーションデモ
    • 大前さん「こんなところに偶然DK2があったので」
    • VertualReality対応チェック入れるだけで視線追従
    • エディタとOculus側との表示が分かれる

クラウドサービス

  • パフォーマンスレポーティング
  • アナリティクス
  • CloudBuild
    • Buildに数分〜数10分掛かる
    • CloudBuild大絶賛 280,000builded 15万時間の節約
    • 無償版もある!! UnityProに内包されている Pro $25〜
  • UnityAds

ここが変わる! Unity5のスマホ開発 〜アセットバンドル、ブルド、プラグイン

AssetBundle

  • 今までの問題点

    • 複雑
    • ビルド時間が長い -どれをビルドすればいいのか不明でフルビルド
    • 面倒な依存関係
    • バージョン毎の互換性が無い
  • 解決方針

    • シンプル (ビルド/ランタイム)
    • 追加ビルド (ビルドを最小限にとどめる)
    • 依存性はUnityが解決する (ビルドして使うだけ)
    • 互換性を保持する
    • [注意] 混ぜるな危険 (4と5)

新しいAssetBundleビルド

  • AssetとAssetBundle間を結びつける

    • インスペクタから各Assetsに対してnameを記載する
    • ビルドするスクリプトを呼ぶ
  • 命名規則

    • 小文字のみ/同盟禁止/パス構成持てる(/)
  • Buildスクリプト

    • BuildAssetBundles(出力パス, BuildAssetBundleOption, 出力ターゲット)
  • Options

    • IgnoreTypeTreeChanges (NEW!!)
      • タイプツリーが変わっても虫 = ソースコード変更しても変化したと見なされない
    • DisableWriteTypeTree
      • タイプツリー遺体をサイズ削減用とで消す
  • 互換性

    • 5.1以降の互換性は保持される (5.0はバグで互換性持たない)
  • Manifestファイル

    • (Single) Manifestファイル -> 親玉/依存関係を解決出来る/ランタイムに読んで依存関係を解消しようとする
    • .manifestファイル -> インクリメンタルビルドにだけ関係する
      • CRC / アセット名 / 依存関係 / Hash / ClassTypes
  • Variant

    • ランタイム時に読み込むアセットバンドルを変更出来る
    • フォルダ/シーンなどに適応出来る
    • AssetBundle名の隣に指定する
    • LoadVariantsでsd/hdのどちらを呼び出すか指定するような感じ

サンプル

  • サンプルプロジェクトを使おう

  • スクリプト

    • AssetBundleManager.cs (マネージャークラス)
      1. 基本ロードの仕組み : AB名を受け取ってLoadAssetBundleが走りWWW発行してキューがリクエストを返す -> GetAsset
      2. 依存性の干渉: LoadAssetBundle内部でAB名を貰ってinitでAssetBundleManifestを読み、依存ABをロード
      3. エディタシミュレーション: GetAssetPasssFromAssetBundleAndAssetName
      4. Variants を使った切り替え: Variantに関する名前を呼び出して、一致する名前を呼び、最後の名前を付け替える (sd->hd)
    • BaseLoader.cs (基本ローダー)
    • デモ

ビルド

  • マルチプロセスビルドHack

    • 複数のプロジェクトを用意してビルドすると早いのでは!?
    • シンボリックリンクを使うよ Library/ProjectSettingsをリンクする
    • Unity側はバッチを作れば良いよ
    • [注意] 未来永劫使えるとも限らない
    • [注意] UnityのAssetBundleビルドがマルチスレッド化すればいいのでは…
  • IL2CPP

    • Before: unity -> Xcode -> ArmV7iOS アプリ
    • Current: unity -> c++出力 -> Xcode -> ArmV7iOSアプリ / Arm64iOSアプリ
    • Future: unity -> c++出力 -> Xcode -> Arm64iOSアプリ (V7 iphone5 までのものはいずれ無くなる)
  • UnityEditor.iOS.Xcode

Plugin

  • Pluginの設定の変更

    • インスペクタで設定出来る様に         
    • 依存するフレームワークを選択可能 / コンパイルオプションを設定可能に
    • Xcodeプロジェクトを直接変更しなくてよい方向に
    • インポート時にPlugins/iOS/ に置けば自動認識される
  • NativeCodePlugin

    • Unityからネイティブの関数を呼び、CからObjCを呼び出し…
    • NativeCodePlugin: 直接ObjCを直接呼び出す
      • [注意] 引数が使えない…

Unityではじめる徹底企画講座!を考える

  • 大野功二さん
    • 3Dゲームを面白くする技術
    • unityではじめる3Dゲーム作り

こんな経験はありますか?

  1. 凄い企画思いついた
  2. Unityあるよ!作ろう
  3. あれ作れない、何か違う、思った様に操作出来ない
  4. ゲームが完成しない、諦める 「こんなはずじゃなかった!!」

企画を完成させられない問題

  • プランニングの問題

    • 「企画を完成させられるかどうか」「企画は完成させられているか」
      • 企画 ≠ アイデア
      • 企画 ≠ 思いつき
    • 企画はゲームを作る為の「出発点」と「ゴール地点」および開発の方向性を指し示すもの
  • 企画の出発点 = ハイコンセプト/コアアイデア

    • いつ/どこで/誰が
    • どんな遊び方で/どんな体験をさせて
    • どんな感情を抱かせて
    • どうおもしろがらせるのか
  • 企画のゴール地点

    • ルック & フィール (第一印象) が大事
    • そのゲームをプレイすることでプレイヤーの心や生活や人生にどのような影響を与えるか
  • 企画の方向性

    • おおまかなゲームデザイン (ルール/システム/操作性)
    • 1回のプレイ時間 / ボリューム
  • 時代とともに変わる企画手法 (答えはない…)

    • 新しいシステムを作れば売れる時代とか
    • ゲームを出せば売れるからとにかくはよな時代とか
    • ターゲットユーザがこまくて状況にあわせて企画の手法そのものがちがう
    • お笑いと同じ!!!!!!
  • ゲームの企画を料理に置き換えてみる

    • [ミッション] 彼女/彼氏を家に招待することが出来たので、料理でもてなそう!
    • 勝利条件(目的)を考える
      • 満腹に / 技術力を見せつける / 楽しい時間を演出して好感度上げる … etc
      • 勝利条件の為に企画(プランニング)する!
      • 身近な人をイメージした勝利条件を (開発チームの4/5人を満足させる)
    • 方法は条件による
      • 相手の好きな者を作る (自分が嫌いな場合は自分が楽しくなれないので好きになる努力が必要)
      • 自分の好きな物を相手にも好きなってもらう (相手がそれを好きになれる要素があることが必要)
      • 自分も相手も、見たことの無い者を作る
    • 自分が好きなものは彼女も好きに違いない!!という発想だけじゃ弱い
    • おもてなし
      • 相手をイメージすることが大事
      • すなわちリサーチ… 「どんな食べ物が好きですか? いつ? 時間は? どんな時に心の距離を縮めてくれるか?
  • 調理とゲーム要素は似ている

  • 料理の失敗例

    • ゲーム機で実現出来ないほどの量の仕様を一度に並べようとしていませんか?
    • ちょうど良い量を出していますか?
    • ゲームが提供するアクションの順番は適切ですか?
    • ゲームで扱うネタは新s年ですか?
    • ゲームで表現したいことに対して、そのインターフェイスは適切ですか?
  • プレイヤーのどんな顔が見たいですか?

    • 人の顔を想像するには現実の経験値が必要
    • ゲーム以外の情報や引き出しを作ることが大事

仕様の問題点

  • 仕様: ゲームをXXXを実現する為にアイデアを設計やメカニクスレベルまで分解したもの
  • ゲームのおもしろさを引き出す要素は以下の組み合わせとバランス

    • アクション: 反射神経
    • パズル: 正しい順番や意味を見つける
    • リソース: 制限/時間
    • 官能性: 操作するだけで気持ちがいい
    • 運:プレイヤーが介入出来ない要素
  • 仕様作成

    • 新しい仕様を作る (センス/挑戦した回数)
    • まねる (知識の数/まねた数)
  • 仕様の基本

    • ゲームを数多く見てどう読み解くかを研究する
    • ゲームデザイナは実現したいゲームに対して、必要なパーツ(基礎仕様)をプログラマに渡して、一緒に最終仕様を作る

実装の問題

  • 挫折原因

  • ゲームエンジンには特性がある

    • Unityの特性を作ろう
    • 頑張ればどんなゲームでも作れます!!
    • けど作りやすいゲームや作るのに時間がかかるゲームは当然あるよ
  • 短時間で作りやすいゲーム

    • 複雑な辺り判定や物理演算が必要なゲーム
    • 単純なアニメーションのゲーム
  • 初めて作ると時間がかかるゲーム

    • 複雑な当たりや物理演算の結果が勝敗を決めるゲーム
    • 複雑なアニメーションのゲーム
    • 理由
      • Physicsを使いこなせていない
        • 高校レベルの数学と物理の知識が必要
        • 3D:PhysX / 2D:Box2Dと異なる
        • e.g) 四角いcoliderだと段差に引っかかるが、足下に丸いcolider入れておくと上れるよ
      • Mecanimを使いこなせていない
        • アニメーションの基礎知識
        • Unity5ではStateMachineBehaviors / AutoMachineAuthoring など
        • 企画をUnity (の特性) に寄せる / Unityを知り尽くして頑張って実装する
  • 作りやすいゲームの共通点

    • PhysicsやMecanimのこんポーメントやプロパティ編集だけで実装可能
    • ゲームのノウハウの公開の有無
  • まずはアセットストアのコンプリートプロジェクトのテンプレートを参考に仕様

    • CompletePhysicsPlatformKit
      • こういうことが出来るよ!出来ないよ!の説明
    • アドベンチャー: 宴
    • 2Dゲーム:ninja slasherX

調整の問題

  • ゲームの面白さは調整で決まる
  • 調整は一人では出来ないのでテストプレイヤーこそが重要な鍵
  • ちゃぶ台返し -> 何回できるかが鍵
  • 開発中は未来のプレイヤーの顔を想像しよう!

Unity5 グラフィクス使いこないガイド

  • 基礎以外はWorkshopで
  • Workshopの内容も後日配信するよ!

Lightingの新機能

  • AmbientLightの強化

    • 3つの方式から選択出来る様になったよ
    • Window -> Lighting
    • Skybox
      • Skyboxに該当している空が映り込む
    • Gradient
      • グラデーション/色を指定する
  • SkyBox

    • ProceduralSkyBox
      • パラメータから空を作れる!
        • SunSize: 太陽の大きさ変更
        • AtompsheteThicknes: 層の厚さ
      • 太陽の光源を設定すると連動する (光源の角度に合わせて太陽が現れる)
    • CubemapSkyBox
      • パノラマ画像から作れる!(hdri とかで検索するといっぱい出てくる)
      • .exr / .hdr という形式のファイルを読み込める様になる
        • cubemapに指定してapplyする
        • skybox -> cubemap に指定する
        • 物体の表面に影響
        • 光源が柔らかいのでDirectionalLight1個追加して太陽を追加すると良い
    • CAST SHADOWS OPTION
      • MwshRender -> CastShadows
        • 両面の影 (TwoSided)
        • Shadows Only (影のみが落ちて見た目は消える)
    • PCF SOFT SHADOW
      • 綺麗になっただけでなくパフォーマンスは上がっている
      • モバイルでは使えないので注意
    • BAKED SOFT SHADOW
      • 半影の開き具合を調整出来る様になった
    • SHADOW BIAS
      • NORMAL BIAS方式を光源で指定する
      • 縮めるようなバイアスを掛けてアーティファクト(ノイズ)を削除出来る
      • 複雑なモデルでは影に隙間が出来るのでBIASとの使い分けが大事

RealtimeGIの基礎 (グローバルイルミネーション)

  • 間接光の表現を使うことが可能なもの (IndirectLight)
  • Lighting -> GeneralGI

    • 物体を動かしたり / 光源が動いたりしても反映される
    • (Unity開けない) 「死ぬかと思った…」
    • (Defuse反射する) 固形物のものにstaticフラグを建てて当てる必要がある
      • staticオブジェクトに関しては自動で間接光が伝搬される
      • 間接照明の効果が現れる
    • 動き回るオブジェクトには勝手にGIは有効にならない
    • LightProbeGroupを指定してあげる必要がある
      • エリア内の動作を計算してくれる
    • Supecularの入ったオブジェクトに対しては ReflectionProbeを指定する必要がある
      • 意図せず発行していたらSkybox映り込んでいるな….
  • DirectionalMode

    • NonDirectional: 追加情報無し
    • Directional: どの方向から代表的な光が入り込んでくるかを近似で定める
    • DirectionalSpecular: 直接光/間接光の持つ情報を持たせる
    • [注意] 計算量やデータ量が増える / 代表的な光源一つだけを考慮しているので複数の光は危うい表現になりがち
      • RefrectionProbeを指定してあげると解決する
  • RefrecrionProbe

    • Probe同士のつなぎ
      • MeshRendererのblendOption
    • 反射の更に反射
      • 映しているものは黒く表示されてしまう
      • RefrectionBounces: 反射回数を指定出来る
      • Bakeするときの処理が重くなるのでまあ2くらいまでは…
    • リアルタイム反射
      • 動いている者に関してはRefrecrionProbeには映り込まない
      • EveryFrameにするとリアルタイムで映り込む
      • InvisibleFaces: フレームレートを落とす(1/10?)により処理を軽くする
      • リアルタイムだと画質も落ちるので注意
    • BoxProjection
      • ある決められた範囲に映り込ませるよ
      • 処理負荷も重くてモバイルでは使えないよx

Render Massive Amount of Objects in Unity

  • (ちょっとシェーダのこと全然知らない自分だったので以下用語に不備あるかも / スライド待ち)

  • @i_saint

    • 社内ゲームエンジンを作っていた
    • グラフィック周り(CandyRockStarの床とか担当)
    • CPU & GPU を全力でぶん回して美しいインタラクションを実現する
    • CPU使用率グラフ見て興奮する感じ

本公園の目指すところ

  • Unityでいろんなトリックを用いて1万以上のオブジェクトを効率的に描画 & 更新する
  • 検証はPC上 PS4/XBoxOne程度

レンダリング

  • 前提

    • 1つ1つGameObject化する: 現実的ではない
    • GameObjectなしにMeshを描く手段が必要
  • Graphics.DrawMesh

    • Meshを描画するリクエストをrender queueに詰むAPI
    • ただしbatchingは効かない
    • drawcallは比例して増える
    • drawcallを抑える手段が必要

疑似インスタンシング

  • 1つのMeshに多数のモデルを格納する手法
    • 元の頂点データを繰り返す
    • 何番目のモデル化という情報を付与
  • 65,000 / モデルの超点数を1回のdrawcallで描ける限界
  • Cubeは24両点なので 65,000 / 24 = 2708個
  • インスタンスの情報をGPUに送り、頂点シェーダモデル変更
    • TRS行列等
  • 必要なbatchの数だけMaterialを用意する
    • 各MaterialにインスタンスIDの開始番号を付与する
    • e.g) Cubeを10,000個か来たい場合、 10000 / 2708 = 4つ
  • 必要個数を超えたモデルは頂点シェーダで画面に出ない様に工夫
    • Materialに今Activeなのはいくつというものを保持する
    • 1個でも描きたい場合は格納されているモデルの数分の処理する
  • GPUインスタンス情報を送る
    • テクスチャにプラグインから書き込む
      • RenderTextureを使用する必要がある (texture2DはFloatのフォーマット使用不可)
      • データ書き込むプラグインを用意
        • texture.GetNativeTexturePtr() でテクスチャオブジェクトを取得
        • ネイティブAPIを用いてデータを書き込む
          • OpenGLのglllTexSubImage2D など
    • テクスチャにMesh経由で書き込む
      • データ転送用シェーダの用意
      • データ用 Rendertexture をレンダーターゲットに指定する
      • Meshにインスタンス情報を書き込む
      • Graphics.DrawMeshNow()
      • 遅いがとてもポータブル
    • ComputeBuffer
      • Direct3D11 / PS4 のみ対応
      • 任意のデータ構造を格納出来る
      • データの更新は ComputeBuffer/SetData() を呼ぶだけ
      • 環境を選ぶが速くて簡単

ハードウェアインスタンシング

  • 1回のdrawcallで1つのモデルを複数各機能
  • 頂点シェーダの入力にインスタンス別のデータが加わる (TRS行列等を輪sつ)
  • 環境を選ぶ e.g) OpenGL 3.1〜 / WebGL 2.0〜

  • Unity: Graphics.DrawProducedural()

    • Direct3D11 / PS4 のみ使用可能
    • Meshをそのまま掛けない
      • 頂点シェーダの入力は頂点IDとインスタンスIDのみ
      • [対応] ComputeBufferに頂点データを格納する
      • [対応] 頂点シェーダで頂点IDとインスタンスIDから実データを参照
    • Unityのrender queueに載せることができない
      • 読んだ辞典で即描画
      • [対応] 独自のRenderTexture
    • surface shaderが使えない
    • [対応] defettedであればG-Bufferさえ生成すればライティングは共通処理で使える
  • Unity5.1でCommandBuffer/DrawProcedure() が追加

    • render queueに載せることが出来る
    • G-Bufferの精製/ ライティングしないオブジェクトには必要十分
  • Graphics.DrawProcedureIndirect()

update

  • オブジェクトをUnity上でどう扱い/どう更新するか
  • オブジェクト群を管理するマネージャをGameObjectとしてもつ
    • Objectのデータはstructの配列として持つ
    • 原始的だけど高速
  • UnityのColliderとのインタラクション等は独自に実装

  • ネイティブコード (=プラグイン化)

    • 数値計算C#苦手
      • ネイティブコードので適切に実装すれば10倍以上速くなる
    • マルチスレッド化
    • SIMD化 (データ構造の最適化 SoA化)
    • C/C++ 以外のHPC向け言語
    • 描画用データをRenderTextureに格納する
      • Texture.GetNativeTexturePtr () でテクスチャオブジェクトを取得
      • glTexSubImage2D() などでテクスチャにデータ書き込む
    • MonoのAPI
    • C++ -> C# のUnityEngineのAPI呼ぶ
  • GPGOU / ComputeShader

    • PC / PS4 / CBoxOneでは有力
      • unity5.1でOpenGL系の環境も対応
    • ゲームロジックに影響しないエフェクトに最適
      • GPUで完結出来ればOK
    • ゲームロジックに盈虚する者は不向き
    • 何に当たったかCPUへのデータ転送がロス
    • リッチな表現
      • G-Buffer を利用したスクリーンスペース衝突判定
      • プロシージャル精製 trail
  • C#でがんばる

    • struct配列で持つしかない
    • class参照しない書き方にする
      • class参照は結構な負担
    • 大きなデータのコプーは避ける
    • ThreadGroup.QuueueUserWorkItem() による並列化
    • いわゆるタスク並列
    • [注意] Unityの機能の大部分はメインスレッドから触れない
    • IL2CPPにより数値計算の高速が見込める (将来的には…)
    • 最新の.NETでもある程度の改善が行われている

結論

  • 現状大量描画は疑似インスタンシングが有力
  • ハードウェアインスタンシングはUnity5.1以降にご期待ください
  • アップデート処理は可能な限りC#は避けて自力で頑張る

Unity For Newニンテンドー3DS

  • Newニンテンドー3DSをUnity5ベースでサポート
  • Newニンテンドー3DSの登録Developerであれば利用可能
  • サポートを求める声は貰っていた
  • 8ヶ月くらい調査した
  • 市場のiOS/Androidのアプリをいくつか選んで移植可能性を検討
    • 8割以上のゲームはそのまま移植して動作するのでは!

3DSは?

  • 議寿的サポートは可能
  • メモリ/CPUの両面から制限がある
  • 選んだタイトルのうち3割くらいが可能性あった

リリースは?

  • 2015年夏: 認定堂に提出可能なβ版をリリース

調査研究と考え方

  • 市場で現在出ているUnity利用のゲームを調査
  • ハードのパフォーマンスを比較検討
  • ユニティ・ゲームス・じゃお案で扱っているゲーム等は実際に移植してみてデータ取る
  • 画面にキューブ出す/テクスチャ出す/スクリプト/物理エンジン
  • サンプルプロジェクトで検証する
  • 3タイトルくらいの移植のチャレンジ

Wind-upKnight2 ねじ巻きナイト2

  • RobotInvaderの傑作アクションゲーム
  • WiiU版をユニティ・ゲームス・ジャパンで担当

ゲーム移植開発した話

  • 3Dへのゲーム移植時の課題

    • メモリ容量が他のプラットフォームより少ない
    • シェーダ制限
    • 画面が2つ / 立体視対応で3回の描写
  • 最初にやったこと

    • オリジナルのゲームはUnity4.3 -> 5.1にアップグレード
    • 問題なく動作した
  • テクスチャ最適化と調整

    • Retina用に高解像度のテクスチャを仕様 -> 3DSの解像度 (400x240では不要)
    • とりあえずテクスチャを64x64に下げる -> 汚いけど動く
    • 画面の見た目の悪い部分のテクスチャサイズを512x512まで上げて対応
  • スマホとのメモリの使用量比較

    • 大体50-60%くらいのメモリ使用量に、4割以下になるものも
  • Unityのスクリプト実行速度

  • エンジンの最適化/描画

  • エンジンの指摘か/Z-Buffer更新On/Offee

    • Z-Bufferの必要ないゲームでは更新をオフにする設定を追加
    • メモリ/GPUバンドに作用
  • ねじまきナイト2

    • 2画面対応
    • 3画面(上両目/下)を描画して60fps維持
  • シェーダーの実装

  • ピクセルシェーダー対応

    • ShaderLabを使った一般的な解決方法をチャレンジ中
    • 結構大変なので最初は別なやり方で対応するかも
  • スクリプト対応

    • il2cpp (=AOT) のみ対応
    • AndroidのようなJIT対応のプラッットフォームから移植する場合
      • テンプレート+動的コード精製を使用するようなコードで移植に問題になる
      • JSONのライブラリ等でよくぶつかる問題
    • Androidのビルドでは一部コードを変更
    • IOSのゲームセンター関連の参照を無くす
    • 動作!! (コード殆ど触ってない!)
  • オーディオサポート

    • iOS/AndroidではラインタイムではOggVorbisフォーマット
    • エディタ上でビルド時に3DS用のフォーマットに変換
    • 圧縮してメモリ内に配置
    • ストリーム再生に設定

実機デモ

  • カメラ: 上画面と下画面選択出来るような感じ
    • UpperLCD / LowerLCD
  • 任天堂のソフト開発Kitの一部の機能を使用出来る
  • buildの時間は長い
  • ジャイロもちゃんと動作しているよ

今後の改題

  • エンジンの最適化

    • ゲームは毎フレーム再描画が必要
    • UIは更新があるとき飲み描画したい
    • 3DSフレームバッファを再利用出来る
    • 書き直さないオプションの使用検討
  • 2Dモードの改善

    • 3Dボリュームはオフに出来る
    • 2画面になるとして、CPU/GPUともに出る空きをどう使うか

まとめ

  • Newニンテンドー3DSをサポートするUnityをリリースするよ
  • ミドルレンジのスマートフォンをターゲットにするようなゲームならサポートは一考の価値あり
  • 2015夏にβ版出すよ
  • UGJが選考してたいとリリースすることでエンジンの完成度を高めるよ

質疑応答

  • NativePluginのサポート予定ある?
  • ネットワークは繋がる?
    • uNETをベースに使用して繋がるようになる
    • ローカルの通信に関してはまだあんまり決めてない
    • NativePluginを通じてニンテンドーの提供している通信機能へのアクセス
    • 3DSが出来ることはUnityFor3DSでも出来る予定 / 専用のAPIを用意する保証は出来ない
    • マイルストーンとしては速度、メジャーな機能から順番に着手してβリリースを目指す
  • New3DSの開発ライセンス以外の枠で開発できる?
    • New3DS自体の開発が必要なので基本的にライセンスは必須
  • ねじまきナイト2でのbuild時間
    • ビルドから転送まで5分程度

Unity 5オーディオ新機能の真髄

AudioClip

  • データと分離したよ

    • AudioClip側にはメタデータを持つことでサウンドのスケジュールを組むことが出来る
    • メモリの削減
  • Loadの仕方も使用出来る

    • PreloadAudioDataのチェックを外すとオンデマンドで動的にロード出来る
    • AudioClip.LoadAuioData(); / AudioClip.UnLoadAudioData
    • Load in backgroundにチェックすることで非同期ロードも行ける
  • Audioのメモリの使用量の改善

  • Platform毎のoverrideな設定

    • コーデック/サンプルレート等の設定
  • 圧縮形式

    • PCM
    • Vorbis (mp3より優れた圧縮率)
    • ADPCM (CPU/メモリ/圧縮のいいバランス) : 呼ぶ回数の多いものが良い、SEなど
      • ノイズが加わることもある
      • ADPCMはマニュアルのサンプルレートも加わることもある
  • 複数選択/編集に対応

AudioSource

  • 3Dセッティングの設定を外した

    • SpatialBlend で2D/3Dのハイブリッドが可能
  • StereoPanの設定を良いにアクセス出来る様にした

  • ReverbZoneのパラメータを追加

    • 2Dのサウンドでも動作する
    • ナレーションボイスにリバーブを付けるなど
  • 距離に応じてパラメータの設定が出来る

  • pauseの機能

    • AudioSource.Pause() / UnPause()
  • Audioプロファイラ

    • どのAudioClipが再生されているか判る

AudioMixier

  • デモファイル

  • 階層的なmixierになっている

  • Player/Weapon/Amibience/Weather…etc などのAudipGroup
  • インスペクタでステータスを変更出来る

    • VU-meters: 音量
    • Solo/Mute
    • エフェクトの追加
    • サイドチェーンはダッキングに使用する
      • 特定の音がなっている場合、他の音を下げることが出来る
    • Wet/Dry Mixtureが可能
    • カスタムGUIに対応
    • スナップショット (設定の場面による出し分け)
      • 環境音をはっきり出す、武器の音だけを出す… 等のケース
  • リアルタイムでプレイ中に変更出来る

    • Edit in Play Mode をクリックするとゲーム中にステータス変更が出来る
  • snapshotの変更の仕方
    • AudipMixierSnapshot snapshot; snapshot.TrandformTo(1.0f); // sec
  • スクリプトからステータスの操作が可能
  • [DEMO] Unityでマスタリングしてる
  • [DEMO] sliderによるsnapshotの遷移 / pauseボタンによるlowpassの適応

Horizontal rescheduling

  • AudioSource.PlayScheduled();
  • 再生タイミングのスケジューリング
  • ピアノロールみたいなデモ

NativePlugin