もぐりの日記

雑日記

技科大祭展示VRゲーム製作記録

adventar.org

TUT-AdC 2日目の記事です。 「UnityでVRをとりあえず動かした話」改め、「技科大祭展示VRゲーム製作記録」です。
本年度技科大祭のコンピュータークラブで展示していたVRゲームの製作記録になります。
開発環境はWindows10、Unity5、Oculus Rift + Touchです。

つくったもの

杖と盾で戦うVRシューティングゲームを作りました。 敵を倒し尽くせばゲームクリアという単純なものです。


UnityでVRをとりあえず動かした話

製作記録

大まかなスケジュール

製作は、4人グループで行いました。大まかな流れは、

  • 5月:企画決定
  • 6,7,8月:モックを作りつつ、仕様を詰める
  • 9月:完成させる

です。この記事では、8-9月中に行われたVR対応機能の実装について触れていきます。

VR対応

対応させる段階別に、それぞれ見て行きます

  • ヘッドトラック
  • 手の表示
  • 触る/握る/使う
  • 握られる/使われる

ヘッドトラック

UnityはVRをサポート*1していて、ヘッドトラックはチェックボックス一つで実現できます。
客注リンク先の「VR サポートを有効にする」を参考に“Virtual Reality Supported” オプションを有効にすると、VRヘッドセットに合わせて、メインカメラの回転とポジションが上書きされるようになります。

手の表示…の前に

Touchコントローラーを使っていくために、Oculus Utilities for Unity*2,Oculus Avatar SDK*3,VRTK*4というアセットを導入します。
前者2つはOculus developersのサイトから、VRTKはアセットストアから入手できます。

インポートできたら、VRTKについているサンプルシーンや、ドキュメントなどを参考にセットアップをしていきます。

手の表示

  1. 空のシーンに、空オブジェクトを2つ作成
  2. 一方の子要素に、Oculus Utilities と Avatar SDK からインポートした、OVRCameraRigとLocalAvatarをおく
  3. OVRCameraRigにアタッチされている、OVR Manager の Tracking Origin TypeをFloor Levelに変更
  4. 2.で子要素を追加したオブジェクトに、VRTK_SDKSetupをアタッチ,Quick SelectをOculusに設定
  5. 2.で選ばなかった方のオブジェクトに、VRTK_SDKManagerをアタッチ,Auto Populateを押す

これでコントローラーに追従する手が表示されるはずです。

触る/握る/使う

前項で表示した手に、握る/使うといったアクションができるようにしていきます。

  1. 前項で、VRTK_SDKManagerをアタッチしたオブジェクトの子要素に、Left,Rightという名前で空オブジェクトを作る
  2. それぞれを、VRTK_SDKManagerのScript Aliasesに設定

ここまでの作業でヒエラルキーはこのようになります。ここでVRTKがSDKManager、VRPlayerがSDKSetupをアタッチしたオブジェクトです。
f:id:sumogri:20171202022554p:plain

ここで追加した、Left,Rightに手で行えるアクション機能を乗せていきます。
たとえば、触る/握る/使うの機能を乗せたLeftのInspactorは f:id:sumogri:20171202023516p:plain
となります。

ここまでの設定で、手の側の設定が一通り完了します。試しに、サンプルシーンの16番にある剣をもってきてみると、握れるはずです。

握られる/使われる

最後に、サンプルシーンにあるような、握れる/使えるオブジェクトを作っていきます。
例として、今回作ったゲームの杖にアタッチしたスクリプトを見てみます。

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using VRTK;

public class IntaractableStick : VRTK_InteractableObject{
    [Header("Stick Option")]
    [SerializeField] private int magicIndex = 0;
    [SerializeField] private Transform magicGeneratePoint;
    [SerializeField] bool followToEnemy = true;
    private Raycaster raycaster;
    private VRTK_ControllerReference controllerReference;
    private MagicManager magicManager;

    protected void Start()
    {
        raycaster = gameObject.GetComponent<Raycaster>();
        magicManager = AurorPlayerController.PlayerObject.GetComponent<MagicManager>();
    }

    public override void StartUsing(VRTK_InteractUse currentUsingObject = null)
    {
        var magic = Instantiate(magicManager.MagicPrefabs[magicIndex],
            magicGeneratePoint.position,
            magicGeneratePoint.rotation);

        if (followToEnemy) FollowToEnemy(magic);

        VRTK_ControllerHaptics.TriggerHapticPulse(controllerReference, 0.5f, 0.5f, 0.01f);

        base.StartUsing(currentUsingObject);
    }

    public override void Grabbed(VRTK_InteractGrab currentGrabbingObject = null)
    {
        controllerReference = VRTK_ControllerReference.GetControllerReference(currentGrabbingObject.controllerEvents.gameObject);
        VRTK_ControllerHaptics.TriggerHapticPulse(controllerReference, 0.7f, 0.25f, 0.01f);
        base.Grabbed(currentGrabbingObject);
    }

    public override void Ungrabbed(VRTK_InteractGrab previousGrabbingObject = null)
    {
        controllerReference = null;

        base.Ungrabbed(previousGrabbingObject);
    }
}

肝心なのは、VRTK_InteractableObjectを継承している点です。 これを継承し、StartUsingやGrabbedといったメソッドをオーバーライドすると、それらに対応したアクションがなされたときに実行されます。

inspectorから見てみると、こんな感じになっています。 f:id:sumogri:20171202025254p:plain
掴みについての設定や、使えるタイミングなど設定できることが見て取れます。
これ以外の機能、たとえば、左手でつかんだものをそのまま右に持ち変える、持った時の手とオブジェクトの位置関係を調節するなどは、別のスクリプト(VRTK_SwapControllerGrabAction等)をアタッチすることで実現していきます。

このようにして、もろもろ実装していくと、とりあえず動くものが出来上がります。

まとめ

長々と Oculus Rift + Touch でとりあえず動かす話を書き連ねてきました。
VRTKにはすぐに使えるサンプルが多数収録されているので、それらを見て行くことでもいろいろできることがわかっていくと思います。
VRというと、ハイスペックPCとお高いHMDが欲しくてなんとなく敷居が高いイメージかもしれません。 しかし、このように気軽に動かすものが作れるとなると、ちょっと近くに感じませんか?感じますよね? Oculus Rift + Touchも当初の価格から随分値下げされ今では5万円とお手頃(?)になっているので、これを機に買ってみるのもいいかもですね!
といったところで、記事を終えたいと思います。

ちなみに、今回紹介したゲームを含めた技科大祭展示作のゲームCDを、コミックマーケット93[金曜日 東地区 "ク" 34a]とよぎぃそふとにて頒布します!どうぞよろしくお願いします!

明日は@naruhodo2015さんによる、「JRA銀行から出金する方法について(中京2日目11R)」です! お楽しみに!
果たして昨年の預金を引き出せるんでしょうか!?私気になります!

TUT-CCのマスコットキャラを目立たせたかった

TUT-CCのマスコットキャラ

TUT-AdC、14日目の記事です。
TUT-ConputerClubのマスコットキャラを、Blender初心者が3D化している話です。

www.adventar.org

TUT-CCのマスコットキャラとは

遡ること1.5年前、コミケに参加することになった幣サークルは、サークルカットを募集しました。
次々と投稿されるシンプルで、洗練されたデザイン。採用という狭き門をくぐり抜けるための血で血を洗う死闘があったかどうかはわかりませんが、 出来上がったロゴには、なんともかわいらしいキャラクターが描かれていたのでした。

f:id:sumogri:20161214001154p:plain

マスコットキャラ認知されてない疑惑

ところで、このマスコットキャラは一般に、どころかサークル内でも認知されてない気がします。うっかりすると新教務システムのマスコットキャラの方が有名です。これはいけません。可愛いものは愛すべしです。
認知度を上げるにはどうすればいいでしょう。それは人前に出ることです。サークルのロゴとして技科大祭のパンフレットに出演する奥ゆかしさも捨てがたいですが、この子にはもっと前に出てもらいましょう。
幣サークルにはゲームを作成しているグループがあります。このゲームは新入生歓迎会や技科大祭で展示するほか、コミックマーケットでも頒布されます。ここを活躍の場にできれば、この子はより有名に、愛されるようになるでしょう!

ました工法

ということで、作製中の3Dモデルがこちらになります。  

GitHub - sumogri/mascot: TUTコンピュータクラブのマスコットの個人的3Dモデル化

球とかキューブとかの組み合わせでさっくり作ってあるので、モデリングについてのあれこれは割愛します。ラティスモデファイヤはいいぞ。

このモデルには、ヒューマノイドリグを設定してあります。なので、fbxなりを経由してUnityにエクスポートすればUnityちゃんのモーションのようなヒューマノイド用モーションが適用できます。

使用例

せっかくなので、Blender上でポーズさせてみようと思います。

f:id:sumogri:20161214005355p:plain はい。

まとめのような言い訳

同じポーズを取らせてみるとひしひしと感じるのですが、足のサイズ感とか顔の縦横比率とかお尻のもっちり感とか可愛かった部分がうまく再現できてませんね。すみません許してください。
きっと来年のAdCまでには元気に走り回るマスコットくんの姿が見られるでしょう。

次回は@NU_Panさんの「DTMか音楽関連」の記事です。お楽しみに!

使用ツール

3Dモデリング:blender 2.77
テクスチャ :GIMP 2

参考

Unityマニュアル,BlenderとRigify の使用https://docs.unity3d.com/jp/current/Manual/BlenderAndRigify.html

今日の天鳳.3

1日休めば取り戻すのに3日かかるのだったら30日休んだんで3ヵ月くらいかかりますね(確信)
もともと感覚で打ってるのに拍車がかかってて笑えないじぇ
ターツ優先度とかオリとかどっか飛んでってるとしか……

1局目

牌譜:http://tenhou.net/0/?log=2016040500gm-0089-0000-8fc01e14&tw=2

東場 特になし
南1
11巡目
234577m67p468s ポン自風 打8s
ここで下家が竹染って気づいてないし警戒もしてない
6mドラ受したいのはわかるけどそれも打2mで何とかなる
ここで竹切りは下家にエサやるだけだし順目も巡目だし67p落としでよかった(?)
14順目
3457777m67p6sポン自風 ツモ8m 打7m
打7mではなくツモ切りor降りて67p切り

2局目

牌譜:http://tenhou.net/0/?log=2016040612gm-0089-0000-2bb6a530&tw=3

東1
5-6順 45s切り
9-10順 9s対
南4
n順目 23s切り
まあ運がよかったとしか
オーラスとか1-4sで十分なのに聴牌とらなかったり
1-4sだったら出てなかったっぽいのは結果論かなぁって

まとめ

勝てないからつまんないじょ~

今日の天鳳.2

忙しいし一戦だけ
現在:R1515 二段

一戦目

牌譜:http://tenhou.net/0/?log=2016022700gm-0089-0000-45bb6398&tw=0

総括

前回とは打って変わってチャンスまみれのドラまみれ。
リンシャン出来なくてもドラ増やせるしカンしていこうぜ。ただし乗るのは他人の手牌だけどな。
結果論だけど東場の下家に上がられなくてよかったなって。

東1/2/3二本場/4一本場

牌譜見るまで染めに気づけないのどうにかしたい。
一段目で二色の456とか切ってくれないと染めって気づけない。まあ切ってても気づけないときあるけど。
東4一だったら10順目手出し東とかでおや?っと思っとくべきなんだろうな?どうなんだろ。
東1の白対子落としとかもタイミング違う感ある。結果的に対面染めじゃなかっただけであれ染めだったら普通に危険な切り方だよなって。

おわり

安直なカンはしないほうがいいって教えたはずです。
f:id:sumogri:20160227020939p:plain

今日の天鳳.1

オンライン麻雀でのあれこれ。
やっとこさ上卓で打ち始めたところ。
R1499で二段、まあ初心者だし多少はね?
伸び悩むのも嫌なので何か書く。
本日は2戦。

一戦目

牌符:http://tenhou.net/0/?log=2016022500gm-0089-0000-f5a1118c&tw=1
ファイヤロー。
東4局とかのリーチとか、南3の嶺上ドラドラ投げ捨てとかなるべくしてなってる感。

二戦目

牌符:http://tenhou.net/0/?log=2016022500gm-0089-0000-e03977d1&tw=2
ぎりセーフな感じ。ことごとくチャンスがつぶれて行ってる。運なのか牌理の結果なのか。
南1とかなんなん?って言いながら打ってた。

おわり

麻雀って楽しいよね!(血涙)f:id:sumogri:20160225020139j:plain

JavaのSocketを使ったストリームとかで躓いたところ

Javaアプリケーションで遊んでた時に躓いたメモ。自分の備忘録的なあれ。

とりあえずサーバーから投げたものをクライアントが受け取れるかやったら躓いた。

 

構成

サーバー⇔クライアントでsocketを使って通信。Serializableなクラスを投げあう形。

サーバー側

ObjectOutputStreamでオブジェクトを投げる。

//InfomationBase:Serializableなクラス
public void send(InfomationBase _info){
 try{
  writer = new ObjectOutputStream(socket.getOutputStream());
  writer.writeObject(_info);
 }
 catch (IOException e) {
  System.err.println("サーバサイド送信エラー");
  e.printStackTrace();
 }
}

クライアント側

ObjectInputStreamでオブジェクトを投げる。

public void run() {
 try {
  reader = new ObjectInputStream(socket.getInputStream());
  InfomationBase message = (InfomationBase) reader.readObject();
  output.setInfomation(message);//output:表示機的なクラス
 }
 catch (ClassNotFoundException e) {
  System.err.println("送られてきたオブジェクトがInfomationBaseではありません");
  e.printStackTrace();
 }
 catch (IOException e) {
  System.err.println("クライアント受信エラー");
  e.printStackTrace();
 }
 finally{
  try{
   reader.close();
  }
  catch(IOException e){
   System.err.println("受信ストリームクローズできません");
   e.printStackTrace();
  }
 }
}

おきたこと

java.net.SocketException : Connection resetってクライアント側で言われた。

解決

エラーの意味そのまんま。
http://software.fujitsu.com/jp/manual/manualfiles/M050000/B1WN5031/03/msg43/msg09893.htm
OutputStreamを開いたままサーバー側のプログラムが終了しているのが問題だった。
ちゃんと送った後に閉じるorプログラムが終了しないのどちらかすると問題なく動いた。

将来的にはサーバーとクライアントでずっと通信するしサーバーから通信切ることはないので大丈夫そうかな?

今回のオチ

つくりたてでpostないの嫌だったし、多少はね?

the first post

どっかのだれかの雑日記はじめました

適当に日々あったこと書きます