Weitere ähnliche Inhalte
Ähnlich wie Unity初心者が初めてHTC ViveでVRゲームを作ってみた (6)
Unity初心者が初めてHTC ViveでVRゲームを作ってみた
- 8. 2回のブレストで見えてきたゲームの方向性
HTC Viveを使った立ったまま行うゲーム(立ちゲー)
音楽に合わせて玉を打ち返して得点を競うゲーム→音楽に合わせるは無くなった
世界観的には近未来、宇宙をイメージ
イベント利用を考え難易度は低め、ルールも簡単で理解しやすく
短時間(1分〜1分半程度)で楽しめる→最終的には3分弱に
どうしてテニス型にしたのか
シューティングが面白いのはわかっていた
もともとのコンセプト(誰でも遊べる、ネガにならない)を考えると血生臭くなる可能性
Viveの特性を考えると立ちゲーはマスト
Audioshieldのつまらなさは、やっている人の動きの地味さにある
動きを派手にするには?ボクシング?テニス?と考えて、最終的にはテニスに落ち着いた
企画(2)
- 10. グラッフィク検証(1) – 暗くする
C4Dのモデルをステージに配置した直後の
状態、デフォルトのDirectional LightをOffに
しても暗くならない。
Main CameraのClear Flagsを黒に、
Lightingで環境光を消してC4Dの太陽ライ
ト位置にDirectional Lightをアタッチ、完
全に真っ暗にするには環境光の反射の設置
も0にする必要があるが、0にすると暗す
ぎたので反射だけは少し調整した。
すべてのライトを無効にしてもシーン全体が暗くならない
Main Camera-Inspector-Clear Flags:オブジェクトが配置されていない部分の塗りのデフォルトを指定する
SPACE TENNISでは宇宙空間にしたかったので、Assets Storeで星空のSky Boxを購入した。
購入したSky Box
Skybox Simple Nebula(https://www.assetstore.unity3d.com/jp/#!/content/8453)$1,95
Window-Lighting-Ambient Intensity:環境光の強さの設定
下記のブログ記事を参考に環境光を調整した。
http://tsubakit1.hateblo.jp/entry/2015/03/26/011351
- 12. Viveコントローラーの使い方
私がよく参考にしたのは「フーレムシンセシス VR開発メモ」
フーレムシンセシス VR開発メモ
https://framesynthesis.jp/tech/unity/htcvive/
RightController.csをつくり、Controller (right)に追加
RightController.csのStartでTrackObjectを取得
trackedObj = GetComponent<SteamVR_TrackedObject> ();
RacketのモデルをImportして、ViveのControllerのModelと同じ階層に追加
元のModelは非Activeに
CGのボタンと実際のコントローラーのトリガー位置を同期する
button = GameObject.FindGameObjectWithTag ("Button");
var device = SteamVR_Controller.Input((int)trackedObj.index);
float value = device.GetAxis (Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger).x;
float diff = defaultTriggerValue - value;
if (button != null)
{
Vector3 position = defaultTriggerPositionValue;
position.z = defaultTriggerPositionValue.z + diff;
button.transform.localPosition = position;
}
これから初めてViveで開発する場合、Viveのセットアップやコントローラーの使い方について
は、すでに良くまとまっているブログ記事があるのでこれらを参考にすれば良いと思う。
- 13. 手に持ったラケットでボールを打つ検証
RacketのモデルをViveのControllerのModelと同じ階層に追加、元のModelは非Activeに
ボールとラケットに当たり判定用のBoxColliderを追加
ラケットとボールに張ったBoxClliderに設定したPhysic Materialで跳ね返りをほぼ最大(0,99)に、
Bounce CombineもMultiplyに
それ以外のDynamic FrictionとStatic Frictionも検証したが、摩擦系は玉の跳ね返り方にそれほど影響し
ない(玉の質量にしそうだが検証しきれなかった)
BoxClliderはモデルより厚めにしないとラケットを早く打った時にすり抜けてしまうのでラケットの厚
さの3倍程度まで大きく(リアリティは薄くなるがすり抜けるよりはマシ)
玉にRigidbodyを追加、Collision DetectionをContinuousに設定
Gravityは検証時は使ってなかったが、直線的な玉の動きは予想がしやすく面白みが無いので後ほど
Gravityを使うように変更した
その他、調整に使ったのはEdit-Project Settings-PhysicsManagerのSleep Thresholdの値あたりだが、劇
的に当たり判定がよくなることは無かった
最終チェックでラケットを早く振ったプレイヤーの玉が前に飛ばないで後方に飛んでしまう問題が多発
して調整しようとしたが、Expo本番までに時間がなく修正しきれなかった
Unityでボールを打つデモを作るのは簡単だったが、当たり判定と跳ね返
り方の調整には実際にプレイしながらでないとわからないので時間がか
かった
- 14. 物理エンジン
AngleXとAngleYにHMDを起点に上下左右にずらす距離を指定。
//Viveの目線に合わせる
Vector3 target = new Vector3 (Camera.main.transform.position.x, Camera.main.transform.position.y + gap, Camera.main.transform.position.z);
var heading = target - this.startPositon.transform.position;
var distance = heading.magnitude;
var direction = heading / distance; // This is now the normalized direction.
this.transform.position = direction;
//ボールを上下左右にちらす
transform.Translate(Quaternion.AngleAxis(this.AngleX, Vector3.up) * this.transform.position );
transform.Translate(Quaternion.AngleAxis(this.AngleY, Vector3.right) * this.transform.position);
Vector3 force = this.transform.position;
GameObject ballObject;
ballObject = Instantiate (Resources.Load ("ThrowBall", typeof(GameObject)), this.startPositon.transform.position, Quaternion.identity) as GameObject;
ballObject.transform.LookAt(target);
Rigidbody rigidbody = ballObject.GetComponent<Rigidbody> ();
rigidbody.AddForce (force * this.Speed, ForceMode.VelocityChange);
SpaceTennisは毎回ランダムな位置にボールが飛ぶように設定した
ボールを飛ばすスクリプト
ボールGameObjectにRigidbodyコンポネートを追加
RigidbodyをAddForceで力を加える
AddForceの第一引数に渡すベクトルはターゲット位置、投球位置、左右に散らす距離を
利用して求めた
Unity – スクリプトリファレンス
http://docs.unity3d.com/ja/current/ScriptReference/Rigidbody.AddForce.html
- 16. Unityでのイベント処理の方法
UnityのGameObjectにはSendMesssageがあるが、
FlashのEventシステムに較べて以下の問題があると思う。
SendMesssageの問題点
送信先のオブジェクトの参照を持っていないといけない
メッセージを伝播する仕組みがない
Space Tennisでは
SteamVRのソースを真似てUtils.Eventクラスを作った。
使い方
1. イベント発行時に実行したいメソッドを定義
Private void onIntroEnd(params object[] args)
2. AwakeでイベントをListen
Utils.Event.Listen (Utils.Events.INTRO_END, onIntroEnd);
3. 適当なクラスからイベントをSend
Utils.Event.Send (Utils.Events.INTRO_END);
public class Event
{
public delegate void Handler(params object[] args);
public static void Listen(string message, Handler action)
{
var actions = listeners[message] as Handler;
if (actions != null)
{
listeners[message] = actions + action;
}
else
{
listeners[message] = action;
}
}
public static void Remove(string message, Handler action)
{
var actions = listeners[message] as Handler;
if (actions != null)
{
listeners[message] = actions - action;
}
}
public static void Send(string message, params object[] args)
{
var actions = listeners[message] as Handler;
if (actions != null)
{
actions(args);
}
}
private static Hashtable listeners = new Hashtable();
}
イベント管理用のUtils.Eventクラス
- 17. 2Dアニメーション
2DのアニメーションにはSpriteStudio 5を利用。
SpriteStudio 5 Player for Unity
https://www.assetstore.unity3d.com/jp/#!/content/22916
自分が元FlasherなのでSSのUIはFlashに近いので割りと馴染みやすかった。
カウントダウンの文字を512 x 512で作ってImportしたら大きすぎたのでScaleを0.01にして使った。
ひとつのプロジェクトファイル(sspj)で複数のアニメーションをさせる方法
ひとつのプロジェクトファイルで複数のアニメーションをさせることが可能。
Space Tennisでは得点の表示アニメーションをひとつのファイルにまとめて行った。
ssaeに複数のアニメーションを追加
StartAnimの引数に渡す番号は上からのインデックス
値になる。
anim.StartAnim (0);
とした場合は、右の0_point100のアニメーションが実
行される。
- 20. 汎用メッセージ(Message)
ゲーム中に汎用的に使えるメッセージビューを作成した。
1. メッセージ表示用のMessageItem.csを作成、Messageゲームオブ
ジェクトに追加
2. Message制御用のMessage.csを作成
3. MessageItem.csのStartでMessageに自身を登録
4. メッセージを表示するタイミングでMessageを通してshowMessage
をコール
Message.GetView(0).showMessage (Glossary.GAME_END_COMPLETE,
showMessageCompete);
第一引数に表示する文言、第二引数にコールバック用のdelegateメソッドを指定。
public class MessageItem : MonoBehaviour {
public int messageNum;
void Start ()
{
Message.SetView(this, messageNum);
〜省略〜
}
}
using UnityEngine;
using System.Collections;
using System.Timers;
namespace Quadra
{
public static class Message
{
public static MessageItem View0;
public static MessageItem View1;
public static MessageItem GetView(int number)
{
if(number == 0) return View0;
if(number == 1) return View1;
return null;
}
public static void SetView(MessageItem view, int number)
{
if(number == 0) View0 = view;
if(number == 1) View1 = view;
}
}
}
MessageItem.cs
Message.cs
- 21. 3Dアニメーション
private void move()
{
System.Random rand = new System.Random ();
int num = rand.Next(POSITIONS.Count);
float y = this.gameObject.transform.position.y;
Vector3 pos = POSITIONS[num];
iTweenExtention.SerialPlay (this.gameObject
,(iTweenAction)iTween.MoveTo, iTween.Hash ("y", y+0.5f, "time", 1.5f, "easeType", iTween.EaseType.easeInOutSine)
,(iTweenAction)iTween.MoveTo, iTween.Hash ("y", y-0.5f, "time", 1.5f, "easeType", iTween.EaseType.easeInOutSine)
,(iTweenAction)iTween.MoveTo, iTween.Hash ("y", y+0.5f, "time", 1.5f, "easeType", iTween.EaseType.easeInOutSine)
,(iTweenAction)iTween.MoveTo, iTween.Hash ("y", y-0.5f, "time", 1.5f, "easeType", iTween.EaseType.easeInOutSine)
,(iTweenAction)iTween.MoveTo, iTween.Hash (
"position", pos
,"time", 1
,"easeType", iTween.EaseType.easeInOutQuint
,"oncompletetarget", this.gameObject
,"oncomplete", "onMoveComplete")
);
}
3DオブジェクトのアニメーションはFlashのTweenerに似ているiTween(無料)を採用。
Space Tennisではラスボスの動きなどに使用した。
iTweenExtention(有料$2)のSerialPlayを使うことで連続したアニメーションが簡単に記述できた。
iTween
https://www.assetstore.unity3d.com/jp/#!/content/84
iTween Native Extension
https://www.assetstore.unity3d.com/jp/#!/content/18391
LastBoss.cs
- 22. 音楽の使い方
Unityでは3Dサウンドが利用可能。
利用方法は簡単で、音を発生させるGameObjectに追加したAudioSourceのInspectorでSpatial Blendのつまみを
3Dに向けるだけ。
AudioSource-Inspector-Spatial Blend(3D エンジンがオーディオソースに影響を与える度合い)
その他、Min DIstanceとMax Distanceなどで聞こえる距離を設定したり、Rolloffの設置を行った。
Space Tennisの場合、ボールが近づく感じを音でも迫力を持たせたかっため、Volume RolloffをLogarithmic
Rolloff(オーディオソースに近ければサウンドは大きいが、オブジェクトから遠くなるとサウンドは急速に小さ
くなる。)にした。
音のフェイドアウトはiTweenのonupdateを使った。
下記はカウントダウン開始と同時にBGMをフェイドアウトさせるところ。
private void onCountDownStart(params object[] args)
{
iTween.ValueTo (gameObject, iTween.Hash (
"from", defaultVolume
,"to", 0
,"time", .5f
,"onupdate", "SetVolume"
,"easeType", iTween.EaseType.linear
));
}
private void SetVolume(float value)
{
audioSource.volume = value;
}
- 24. VR Expo Akiba当日
プレーヤーの向く方向の調整ができなかった→プログラムで変更できるようにし
ておこう!
プレイ中に壁に振った手などを当てる人が出た→HMD起点にボールが投げられる
仕様が裏目。本番は固定位置を起点にボールを投げれば自然に元の位置に戻るは
ず。
現場の思いつきで背面に投影するためのプロジェクターを接続したこと原因で
ゲームが何度もフリーズを繰り返す→現場の思いつきでシステムを変更すること
はやめよう。だいたい問題が起きる。
運営にプレイ時間を短めに報告していたため、ファストパスに行列→正しいプレ
イ時間を運営には報告しよう!
などなどありましたが、開始の10時半から終了の17時まで列が切れず好評で終わり
ました。総勢50名ぐらいの方にプレイ頂けたと思います。
ご来場頂いた方には大変ありがとうございました。
Hinweis der Redaktion
- Viveの開発環境は「フレームセンシシス」などを参考にセットアップ
フレームセンシス Unity+HTC Vive開発メモ
https://framesynthesis.jp/tech/unity/htcvive/