これはドリコム Advent Calendar 2016 21日目です。

『ダービースタリンオン マスターズ』(以下ダビマス)ゲームエンジニアのリーダーを担当している西村です。

ダビマスでは、主に下記を担当しています。

  • レースロジック
  • UI制作フロー構築
  • 画面遷移制御
  • チュートリアル

今回は、ソーシャルゲームには必須と言える「チュートリアル」の実装手法についてお伝えします。

昔のように、取り扱い説明書を見ながらゲームをプレイする方は激減したと思います。代わりにゲームの最初は操作を誘導しつつ、実際にプレイしてもらって遊び方を知ってもらうという流れが主流になった時代とも思っております。

ダビマスをプレイされていない方は是非プレイすることをオススメします。すぐにこの記事と実際のチュートリアルが比較できると思います。

『ダービースタリンオン マスターズ(ダビマス)』公式サイト

ダビマスのチュートリアル

ダビマスのチュートリアルの画面です。


キャラクターが説明しつつ、ボタンを押す場所を指で示して教えていく流れです。

ここで気をつけておきたいことは、操作を知ってもらうことが大事なため、ゲーム中の画面遷移をそのまま使い、チュートリアル専用の画面遷移は作らないというところです。

チュートリアル専用というのはプログラムの話でも同じで、できる限り減らしたいところです。さらにコードに焦点を当てると、実装済みゲーム機能とチュートリアル機能の双方のコードが入り乱れてしまうと、バグの原因や作業の属人化につながるので、できれば避けたいところです。

そのため、ダビマスではチュートリアルの進行制御をデータ化して、コードレベルでの独立性を上げています。

チュートリアルデータ

上で貼ったチュートリアル画面を制御しているデータが下記です。記述した「コマンド」を上から順に実行します。

-- キャラクタウィンドウを表示して指定したテキストを表示
ShowCharaWindowMFront(2, 0, "調教をすることで 馬が強くなったり\n馬の調子が変わったりするから・・・")

-- 調教選択画面
AddObjMask("mask", 145, 370, 182, 128)                      –- 芝ボタンの矩形領域以外はマスクをかける
VisibleObj("SS_tap_next", true)                             -- 指を表示
SetObjPos("SS_tap_next", -120, -140)                        -- 指の位置を(-120, -140)に変更
WaitClick("UIStableHorseTrainHome", "Button_train_type_01") -– 調教UIのうち芝調教ボタンが押されるまで待つ

今回はluaファイルでデータを作成しておりますが、ファイルフォーマットは表現さえできればなんでも良いです。

仮にjsonで記述する場合は下記のようになるでしょう。

[{
  "command": "ShowCharaWindowMFront",
  "param1": 2,
  "param2": 0,
  "param3": "調教をすることで 馬が強くなったり\n馬の調子が変わったりするから・・・"
},
{
  "command": "AddObjMask",
  "param1": "mask",
  "param2": [145, 370, 182, 128]
},
{
  "command": "VisibleObj"
  "param1": "SS_tap_next",
  "param2": true
},
{
  "command": "SetObjPos",
  "param1": "SS_tap_next",
  "param2": [-120, -140]
},
{
  "command": "WaitClick",
  "param1": "UIStableHorseTrainHome",
  "param2": "Button_train_type_01"
}]

チュートリアル実装はコマンドを量産していくことが主作業です。上で紹介しているのは5つのコマンドですが、コマンド数は最終的に50種類ほどとなりました。

コマンドは主に下記に分類されます。

  • Wait系
    • 指定ボタンの押下や指定UIが表示されるまでなど動きが完了するのを待ちます。
    • 待つ間他の操作の導線を切ることが重要です。
  • Obj系
    • 画像、アニメーション、マスクの表示や位置変更をします。
    • ゲーム画面の手前に全て出していきます。
  • Show系
    • キャラクタウインドウの表示やUIを名前指定して表示します。
    • Obj系よりもっと大きな枠組みのものが対象です。
  • その他
    • ログの送信やレースの強制勝利などあります。

データ化による作業分担

プログラムでチュートリアルの流れを1つ1つ実装すると、エンジニアでしか作れなくなります。しかし制作時は座標変更やフロー変更などしばしば起きるものです。その度にエンジニアでしか直せませんとなると作業効率は下がってしまいます。

そこでデータ化することによって、エンジニアでなくプランナー/スクリプターの方に実装を託すことができ、作業を分散する効果が得られます。

今回のダビマス以外でもこのようなデータ化は行ってきましたが、私の経験上、実際にゲームを形にするという体感が得られますのでプランナーの方も快く作ってくれます。

しかし、エンジニアの予想を超えた実装や要望はよくあるので、エンジニアがしっかりとアフターケアをしていきましょう。

チュートリアルの復帰

スマートフォンだからこそ手軽にゲームをやめたり再開することができます。このときアプリがOSによって終了されることがしばしばあります。

チュートリアル中にアプリが終了している場合、再開時にプレイしていたある程度のところまで戻す必要があります。これについてもデータ化して管理をしております。

アプリを起動した際は下記のようなデータ駆動による進捗チェックを行います。

-- チュートリアルの進行チェック
CheckRaceEntry("EndRaceEntry", "")    -- レースに登録している場合”EndRaceEntry”ラベルへ。Noなら下へ。
CheckTraining("EndTraining", "")      -- 調教を終えている場合”EndTraining”ラベルへ。Noなら下へ。
NextTutorial("tutorial_training.lua") -- 進捗していないので調教のチュートリアルを実行する。

-- レース登録をしている
Label("EndRaceEntry")
NextTutorial("tutorial_advance.lua")  -- 日付変更のチュートリアルを実行する。

-- 調教が終わっている
Label("EndTraining")
NextTutorial("tutorial_entry.lua")    -- レース登録のチュートリアルを実行する。

進捗状況をチェックして、条件に合致した場合は指定したluaファイルでチュートリアルを動かすという流れです。

記載したデータのように条件分岐の機能があると複雑になりますが、利便性は上がります。(条件分岐が含まれる場合は難易度が上がるので、エンジニアが実装するのが良いです)

そしてデータをファイル分割しておくと、分岐や復帰がしやすくなるので、仕組みとしてあると良いです。(最終的には14ファイルに分割されています。)

データ化するということは配信ができる

ソーシャルゲームの運用指標としてよく「チュートリアル突破率」というのが挙げられます。しかし、測定してから対策を打つまでにバージョンアップを挟むため期間が空くことがしばしば起きてしまいます。

データ化するということはアプリのバージョンアップがなくともチュートリアルを変更することができますので、より良いチュートリアルをいち早く届けることができます。

また、データ配信はバグ修正にも有効な手段であります。ダビマスでは不覚にもチュートリアル時のバグが見つかってしまいましたが、データ配信によって修正し提供することができています。

まとめ

チュートリアルのデータ化による効果をまとめますと、

  • コードレベルでチュートリアル機能の独立性を上げてバグ発生や属人化を抑える
  • データ作成をエンジニア以外のプランナー/スクリプターに託すことでチーム全体としての作業効率を上げる
  • データ配信によって、バージョンアップを待たずに変更することもできる

このようにデータ化する話を書いていますが、これを容易に実現させるためには画面遷移の制御やUI系処理の共通化(ex.どのボタンを押してもコード上必ず通る箇所を作る)など、深い部分で必要なテクニックがあります。

が、それはまたの機会にでも。

©2016ParityBit