KLabGames Tech Blog

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

カテゴリ: VR

この記事は、KLab Advent Calendar 2016 の17日目の記事です。はじめまして、morikenです。

昨日はjukey17さんのVRのゲームを作ってみて気をつけたことでした。

2016年はVR元年

さて、2016年は年始から盛んに「今年はVR元年だ」と言われていましたが、確かに一気にVRが普及したように感じます。

家庭用のVR機器がいくつも発売され、またVRを体験できる場所や機会も増えたことにより、VRの魅力を知った方も増えたと思います。

私自身も、VR ZONEでVRを体験してその魅力に取り憑かれ、PlayStation®VRももちろん購入し、日々バーチャル空間でサイリウムを振ったり、家庭教師の仕事をしたりして楽しんでいます。

ところで、面白いゲームをプレイすると、自分でも作ってみたくなるのがゲーム開発者の性です。そこで、VR元年が終わる前に、自分でもVRのゲームを作ってみることにしました。

VRゲームを作る前に

今回は初めてということで、普段から慣れ親しんだUnityで、スマートフォン向けVRゲームを作ることにしました。

ところが、スマホ向けのVRゲームを作る上で、ある問題に直面しました。それは、プレイヤーにどのようにゲームを操作させるか、です。

というのも、スマホVRでは専用のゴーグルにスマホをセットし、それを覗いてコンテンツを楽しみます。そのため、タッチパネルによる操作はほぼ行うことができません。

それゆえ、VRコンテンツの開発者たちは、ゴーグルに磁石を取り付けてスイッチ代わりにしたり、視線でUIを選択できるようにしたり、首を縦横に振る動きを利用したりと、色々工夫をしてきました。しかし、これらの操作方法では、複雑な操作をさせることは難しいです。

そんな時、自宅にむかし購入したBluetoothのキーボードがあることを思い出しました。Bluetoothなので、スマホとも接続できるはずです。キーボードを使うことができれば、プレイヤーに複雑な操作をさせることができます。

そして、キーボードを使ったゲームと言えば、思い浮かぶものは1つしかありません。

そう、タイピングゲームですね。

VRタイピングゲームの作成手順

手順は以下の通りです。

  1. タイピングゲームを作ります。

  2. 1.で作ったものをVRに対応します。

以上の2ステップです。簡単ですね。

タイピングゲームの作成

今回は、フィールドの中心にいるプレイヤーに向かって、周囲から襲いかかってくるモンスターをタイピングによって撃退するという、ベーシック(?)なタイピングゲームを作成しました。

プレイヤーを定点カメラにするのは、VRのデモ作品などによくある形式ですね。この形式は、周囲を 360° 見渡せるためVRと相性が良く、またカメラの移動がないため酔いづらい、というメリットがあります。

リソースにはUnity Technologies製のアセット、Survival Shooterを利用しました。

非VRのタイピングゲーム

VR対応

タイピングゲームがあらかた完成したら、次はVRに対応させます。

VR対応には、Google VR SDK for Unityを使用しました。Googleは以前、Google Cardboard SDKというSDKを配付していましたが、今年の8月に発表されたDaydreamに対応され、リニューアルされたようです。

VR対応はとても簡単で、UnityにインポートしたSDKに含まれるGvrViewerMain.prefabというPrefabをシーンに配置するだけです。これだけで下の画像のように、ゲーム再生時に自動で右目・左目用のカメラを配置し、VRゴーグルを通して見ることで、ゲーム内のオブジェクトが立体的に見えるようになります。

VR対応のデモ

VRでのUIの注意点

さて、VRゲームでは、非VRのゲームとは少しUIを変えなければいけません。

というのも、非VRゲームと同じようにUIを配置しても、UIが適切に表示されないためです。

例えばこのように、ゲーム内テキストと体力ゲージを模したUIを配置します。

オーバーレイのUI

ところが、これを再生すると、下のようにUIが左目、右目の領域にはみ出して表示されてしまいます。

オーバーレイのUI再生時

この問題を解決するため、カメラ画像にオーバーレイさせていたUIを、3D空間上に配置しましょう。

CanvasコンポーネントのRender Modeは、デフォルトではScreen Space - Overlayになっていますが、これをWorld Space に変更します。

Canvasコンポーネントの設定

すると、Canvas以下のUIコンポーネントが通常の3Dオブジェクトと同じようにワールド空間上に配置されるようになり、左目用・右目用の両方のカメラに描画されるようになりました。

VR対応されたUI

完成

こうして、無事にVRタイピングゲームが完成しました。

VR対応されたゲームのGIF

実際にプレイしてみた

さて、実際にプレイする上で、いくつか必要なものがあります。

まずは、Bluetooth接続できるキーボードです。このゲームはタイピングゲームなので、キーボードは必須です。

キーボード

次に、プレイ中はVRゴーグルを手で支えることができません。そのため、頭に固定できるタイプのものを用意する必要があります。

VRゴーグル

またモンスターは360°さまざまな方向から襲いかかってくるため、素早く周囲を見渡せるよう立ってプレイするのが最適です。その際にキーボードを手元に固定できるように、画板のようなものがあると便利です。

画板のようなもの

全て装備するとこのようになります。(本当は某ゲーム機を背負いたかったのですが、怒られそうなので諦めました。)

装備した様子

プレイしている様子です。遊んでいる本人はVRの世界に没入できてとても楽しいのですが、周りからは不審な目で見られるので、人目がないところでプレイするのが良さそうです。

プレイの様子

終わりに

ゲームのクオリティはさておき、VR対応ゲームはこのように簡単に作ることができます。興味を持たれた方はぜひチャレンジしてみてください。

一緒にこれからのVR業界を盛り上げましょう!

KLab Advent Calendar 16日目の記事です

はじめまして、jukey17です
Advent Calendarを書くのは初めてです
よろしくお願いします!

この記事に書いてあること

この記事では、jukey17がVRゲームを初めて作ってみて、気をつけた内容を簡単にまとめています

これからVRのゲームを作ってみようと思っている方の参考に少しでもなってもらえれば幸いです

VRのゲームを作ろうと思ったキッカケ

VR元年と言われた2016年 、個人でも楽しむことができるVR製品が次々に発表・発売されていき「VR製品買いました」「VR楽しい!」「VR凄い」という声が開発仲間の周りから少しずつ聞こえてくるようになりました

私自身全く興味がなかったわけではなく最初は体験ブースなどを見つけたら軽く遊んでみる程度の興味はありました
が、今一歩踏み込めないままでいました

そうこうしているうちについにはゲーム開発とはゆかりのない仕事をしている友人からもVRの話題が聞こえるようになってきてやっと ちょっとこれは実際に作ってみたほうがいいのでは? と思うようになりました

気がついたら今年も残りわずか、 このまま踏み込まないまま1年が終わってしまうのも勿体無い! と思い、VRゴーグルを購入しゲーム開発をはじめました

作ったゲーム 『World Jab VR』

image

正面から飛んでくるジャブ(パンチ)を左右に避けるゲームです
少し昔、TVで話題になっていた某ボクシング3兄弟の父親が行っていた練習の1つをモチーフにしました

このゲームは Google VR SDK for Unity(※以下SDK)を使ってUnityで作りました

ジャイロセンサーを使用して横の傾きを検出し、プレイヤー自身を左右に動かしてジャブを避けます
何回連続で避けられるかを競うゲームとなっています

初めてのVRゲーム開発だったのですが、実際に開発を進めていく中で気をつけたことの中でやってよかったと思った内容がありました

以下にその内容を紹介します

気をつけて良かったこと

先にUnityEditor上で遊べるようにした

私はまず初めに VRのゲームを作ろう! と勢い良くSDKのサンプルシーンを起動し、実機に転送して遊んで見るところからスタートしました

しかし、プロジェクトをビルドして、端末にバイナリを転送し、起動した状態で端末をVRゴーグルに装着して…
というのを 開発中に何度も繰り返すのはとても大変 だとすぐに気づきました

そこでまずはSDKの導入は一旦せず、UnityEditor上のみで動作が確認できるように開発をはじめました

とはいっても、SDKは簡単にゲームのVR対応ができるように GvrViewerMain.prefab をシーン上に配置するだけでVR対応が済むような構造になっているので、この対応は非常に簡単です

初めはUnity上で開発を進めていき、 ある程度遊べるようになってきたら対象のプレハブをひょいとシーンに置けば良いのです

但し、今回作った World Jab VR はゲームの仕様上プレハブの設置とセットでジャイロセンサーの入力機構も実装しなければなりません

ある程度遊べるようになってからも膨大な微調整の時間がかかるのは容易に想像できます

そこで更にもうひと工夫することにしました

入力操作方法を切り替えられるようにした

今回は3つの入力操作方法を切り替えられるようにしました

  • キーボード操作

PC(UnityEditor)想定
※先程のgifアニメーションがPC操作

  • ジャイロセンサー

スマホ(VR)想定

vr_play

  • タッチ操作

スマホ(非VR)想定

touch_play

最後のタッチ操作はキーボードとジャイロセンサーの出し分けを作ったときに「幾らでも新しいパターンが追加できるな」と思い、サクッと作ってみてしまった副産物です

この3つの入力操作方法は実行前に設定を切り替えられるようにしました

これのおかげで下記のような対応がとてもしやすくなりました

  • VRで遊んでいる間に問題が発覚!
    1. UnityEditorで動作を確認と問題を修正の繰り返し
    2. 修正が完了したらVRで再度遊ぶ
  • 新しい機能を追加したい!
    1. UnityEditorで機能の実装と微調整の繰り返し
    2. 実装が終わったらVRで最終チェック

一度VR対応したせいで細かい動作確認が億劫になり、開発スピードが落ちていく…なんてことは防げるはず!
(モチベーション維持は大事です)

今後の展望

UI上からのパラメータ調整・設定切り替え

いわゆるデバッグ機能です
現在はUnityEditor上のインスペクタから設定できるようにしています

しかしこれだと実機で動作確認したときに微調整をするために一旦UnityEditorに戻らなければなりません
大きな問題の修正や新機能の追加などプログラムを書き換えなければならない内容では仕方ないことですが、パラメータの調整やオプションの切り替えだけで済む内容なのであればなるべくUnityEditorに戻りたくありません

VRゴーグルを装着しているときは 視点ポインターで選択 できるようにしないといけないため歯応えがありそうな内容です

追加したい機能のアイデアももう思い浮かんでおりドンドンと実装をしたいところ...
もあるのですが、こういった 何度も繰り返し時間の掛かる部分は積み重なっていくとかなりの時間を消費していて開発スピードを下げる原因になる ため、足回りの部分の整備も怠らずに進めていきたいところです

ジャブを繰り出す側もプレイヤーにしてしまう

現状はAIが繰り出すジャブをひたすら避けるゲームになっていますが、通信機能を使って2人で遊べるように したら見栄えも含めてもっと面白くなりそうです

避ける側はVRゴーグルを装着、ジャブをする側はスマホにフリック操作してジャブを繰り出す

フェイント機能 などがあると駆け引きが増えて盛り上がりそうです

(※操作方法は暫定)

最後に

初めてのVRのゲームを作ってみましたが、どんな内容のゲームをつくるかを考える際に『どんな場所で遊ぶのか』『遊んでいる人は外から見てどのように見えているのか』など、 ゲームの内容の外側のことも気にしたりしながら作ったので予想以上に難しく・そして楽しかったです

今回は開発を始めていく中での気をつけておくと良いことを紹介しましたが、今後はそういった空間を含めたゲームデザインや新デバイスならではの技術に触れるような内容にもチャレンジしたいと思いました

以上です

バーチャルリアリティーは漢のロマン

昔、私が高校生くらいの時にもVRブームがあり、バーチャルリアリティエキスポなるイベントで、 筋斗雲的な何かに乗ったり、高速に上下するLEDアレイディスプレイで三次元を表示するゲームなどに、 ワクワクしたことを思い出します。

そして、ここ数年、再びバーチャルリアリティー(VR)が盛り上がっています。 Oculus Riftや SCEのProject Morpheusといった ヘッドマウントディスプレイも格段に進歩し、 コンピュータグラフィックスやGPUなどの技術の進歩のおかげで、 非常にリアルな仮想現実没入体験が、簡単に手の届く領域にきています。

そんななか、私がもっともワクワクしているのが、 Googleの「Cardboard」です。 なぜなら、非常に安く手軽に手に入れ使うことができ、特にユーザーに身近なものになりうるからです。

本稿では、Cardboardを使ってVRでロボットに搭乗して操縦するデモを作成したことを紹介します。

Cardboardを使ってみる

CardboardはGoogleが公開した段ボールでできたスマフォ用VRアタッチメントです。 設計図も公開されているので、100円ショップで買ったルーペのレンズと、 段ボールと、テープと工具があれば自分で作ることができます。

fig1

簡単!Cardboardを自作する

実際にGoogleが公開しているデータで、 Cardboardを二つほど作ってみました。 レンズは、100円ショップで手に入るルーペを分解すると手に入ります。 私は、ダイソーで写真のルーペを買いました。なんとレンズが二つ入っていて、 一つ買うだけで両目分のレンズが手に入ります。

fig2

レーザーカッターがあれば簡単なのでしょうが、残念ながらないので、 プリントアウトした型紙を段ボールに貼り、 地道に普通のカッターで切り抜いて組み立てます。

純正のCardboardには、頭に固定するバンドがないので、 手芸用のゴム紐とマジックテープで簡単な固定用バンドを追加しました。

以下が実際に自作してみたものです。

fig3

UnityでCardboard(Durovis Dive編)

最初に試したのが、このDurovis Diveです。 リンク先の開発者ページにあるSDKをダウンロードし、 unitypackageをインポートして使います。

インポートしたDive/Prefabs/にあるDive_CameraというPrefabを、 シーンに追加すると、ヘッドトラッキング付両眼カメラになります。 このカメラをメインカメラにすることで、非常に簡単にCardboardなどの スマフォ用VRアタッチメントに対応させることができます。

UnityでCardboard(CardboardSDK編)

次に、Google Cardboard公式のUnitySDKを試してみましょう。 Cardboard Developper Page(Unity)を見ると、Download and Samplesからunitypackageをダウンロードできます。 プロジェクトにインポートすると、Cardboardフォルダができます。

Durovis Diveと同様に、 Cardboard/Prefabs/にある、CardboardMainというPrefabをシーンに追加することで、カメラになります。 これだけで、Cardboardに対応させることができます。

どちらにしたのか

今回は、両方とも実装してみての確認は行いましたが、 詳細な評価と比較はできていません。 実際のアプリではDurovis Diveを使いましたが、 これは作り始めた初期の時点でCardboardのUnity対応SDKがリリースされてなかったという理由によります。

どうやって操作するの?

スマフォVRアタッチメントを使用する場合、大きな問題となるのがユーザーインターフェースです。 Cardboardでは、これを磁石とスマフォの磁気センサーでスイッチを作って解決しています。 磁石二つの位置関係による磁力の変化を、スマフォの磁気センサーで検出することで、一ボタンに対応する入力を実現しています。 非常に面白い仕組みです。 Ver.2のCardboardでは、導電性の布とレバー機構を使うことで、ボタンを押すと画面にタッチされる機構が作られています。これも面白い仕組みですね。 一方で、どちらの入力方式でもアクション性の高いゲームに利用するには入力の少なさと、反応速度と操作しやすさから難しいです。

そうだ、スマフォ二台使おう

ここで、私が考えたのが、スマフォの加速度センサーやタッチパネルをコントローラーとして使えないかということでした。 スマフォの普及率が爆発的に増加した昨今、二つくらい前に使っていたスマフォが机の引き出しの中に眠っていたりしないでしょうか。 そうです、それらをコントローラとして使えばいいのです!!

そうなると、表示用と左手用右手用の都合三台のスマフォが必要です。 我が家には、幸い私と妻が以前使っていたiPhone4とiPhone4sが余っていました。 これをコントローラーとして使えるようにしてみましょう。

無線で本体とコントローラーをつなぐ

では、どのように表示+ゲーム実行用の本体スマフォと、コントローラー用スマフォをつなげばいいのでしょうか。 ここで今回は、WebSocketを使ってみました。 サーバーを介して、本体とコントローラをWebSocketでつないでみました。

fig4

クライアント側のUnityでは、WebSocketSharpのUnity対応のためのKLab改変版を使って、以下のような受信用プログラムが動いています。

using UnityEngine;
using System.Collections;
using WebSocketSharp;

public class WebSocketClient : MonoBehaviour {
    public const int RIGHT = 0;
    public const int LEFT = 1;
    public const int B1 = 0;
    public const int B2 = 1;
    public Vector3[] accel = new Vector3[2];
    public bool[,] button = new bool[2,2]{{false,false},{false,false}};

    private WebSocket ws;

    // Use this for initialization
    void Start () {
        ws = new WebSocket ("ws://URL/chat/test");
        ws.OnMessage += (object sender, MessageEventArgs e) => {
            string [] message = e.Data.Split(new char[]{':'});
            int controllerNo=RIGHT;// Default Right it is not good
            switch(message[1]){
            case "R":
                controllerNo = RIGHT;
                break;
            case "L":
                controllerNo = LEFT;
                break;
            default:
                break;
            }
            switch(message[2]){
            case "AC":
                accel[controllerNo] = new Vector3(float.Parse(message[3]),
                                                  float.Parse(message[4]),
                                                  float.Parse(message[5]));
                break;
            case "B":
                button[controllerNo,int.Parse(message[3])-1] =
                    (message[4].Equals("DOWN")) ? true : false;
                break;
            default:
                break;
            }
        };
        ws.Connect ();
    }

    // Update is called once per frame
    void Update () {
    }
}

Playerのコントロールスクリプトなどで、このクラスから情報を取得して操作します。

一方で、コントローラーは、HTMLファイルで作りました。ブラウザで表示するだけでコントローラーになります。

<!DOCTYPE html>
<html><head>
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
</head>

<body style='user-select: none; -webkit-user-select: none;'>
<script type="text/javascript">
document.addEventListener('touchmove', function(e) {
  e.preventDefault();
},false);

var ws;
ws = new WebSocket("ws://URL/chat/test");

function send(message){
  ws.send(message);
}

window.addEventListener("devicemotion",function(evt){
  var x = evt.accelerationIncludingGravity.x; //横方向の傾斜
  var y = evt.accelerationIncludingGravity.y; //縦方法の傾斜
  var z = evt.accelerationIncludingGravity.z; //上下方向の傾斜
  send("1:L:AC:"+x+":"+y+":"+z);
},false);
</script>
<div style="width: 100px; height: 100px; background-color: red; margin: 20px; float: right;" ontouchstart="send('1:L:B:1:DOWN')" ontouchend="send('1:L:B:1:UP')" ></div>
<div style="clear: right;"></div>
<br>
<br>
<div style="width: 100px; height: 100px; background-color: blue; margin: 20px; float: right;" ontouchstart="send('1:L:B:2:DOWN')" ontouchend="send('1:L:B:2:UP')" ></div>
</body></html>

このHTMLをコントローラーの識別番号を変えて左手用と右手用の二つ作ります。

中継用サーバーは、単純なWebSocketで届いたメッセージを接続しているクライアントにブロードキャストするだけのサーバーです。 clojure-aleph-chatを参考にしました。

バーチャロンへのオマージュ

二本のスティックでロボットを操作すると言えばあれですね。 加速度センサにより、端末の傾きをとることにより、 左手右手の両方のスティックを前に傾けると前進、 後ろに傾けると後退、前後に互い違いに倒すと回転、 横方向に同じ方向に倒すと横移動、 横方向に開くと上昇、閉じると下降という操作体系です。 皆さん、よくご存じですよね。

コントローラー画面には、攻撃ボタンとブーストボタンを表示してみました。 タップするとそれぞれの動作をします。

fig7

写真にあるように、ブラウザでコントローラー画面を表示させます。 赤が攻撃ボタン、青がブーストボタンです。 AndroidとiOSのどちらでも動きますが、AndroidとiOSで加速度センサーの軸が違っているので気をつけましょう。

プレイ風景・・・

遊んでいるところ(筆者近影)

fig5

実際の画面のスクリーンショット

fig6

まとめ

今回の実験は、三台のスマフォが必要というネックがありますが、 最近のスマフォの普及率を考えると意外と何とかなるのではないでしょうか。 実際我が家には、iOSだけで、3GS,4,4s,5,5s,6,初代iPadがありますし、 AndroidはHTC AriaとKindle Fire HDとKobo Arcがあります。 3台くらいきっとなんとかなりますよね。

また、WebSocketで一回サーバーを介するレイテンシも、プレイしてる分にはあまり気にならず、 作り方次第で十分隠蔽可能なのではないかという感想です。

そして最高ですね。この没入感、飛翔感。楽しいです。文章ではこの楽しさが伝わらないのが残念です。 今回は、搭乗して操縦する体験を目標にしたので、ゲーム性は皆無に等しいのですが、 今後ゲームとして成り立たせる方向も模索したいと思います。


oho-s

↑このページのトップヘ