Aizu-Progressive xr Lab blog

会津大学のVR部であるA-PxLの部員が持ち回りで投稿していくブログです。部員がそれぞれVRに関する出来事やVRにちなんだことについて学んだことを書いていきます。

連絡はサークルTwitterのDMへお願いします。
「面白法人カヤックVR分室」としても活動しています。詳細はこちら

VRアカデミー 4/1, 4/8

VRプロフェッショナルアカデミー

今回は 4/1 に行われた第1回の講座と、 4/8に行われた第2回の講座について書いていこうかと思います。

4/1(第1回)

やっとはじまりました、VRプロフェッショナルアカデミー。これから私は毎週土曜日東京に通うことになりますw せっかく頑張って通うのに聞いてきたこと忘れては嫌なのでできるだけ早くここに備忘録つける癖をはやくつけたいです。(もう第1回から2週間経ってしまいましたが。)

第1回の講義では4人のゲストのお話を聞くことができました。

1人目 高橋建滋様

Ocufes知ってる人なら絶対しっているVR界では超有名な高橋様からお話を聞くことができました。現在PS4でホラゲを作っているそうです。
 高橋様はHMDを知らない人に説明する際、HMDのことを「新しいメディア」(ラジオやテレビなどと同じ、人類が120年ぶりに発明したメディア)と説明していました。またメディアというのは人間を賢く、優しくするためのもの、例えば活字というメディアは人類が感情を手に入れるためのものだとも説明してくれました。
 VRの演出方法は今はまだいろんな企業とかが研究中だそうで、それはVRだと昔ながらの演出方法が使えないからだそうです。そんな現在新しい演出方法を探している最中のことを大航海時代とも言っていましたw それに加え、「死体で谷を埋めていく」(たくさん失敗して、たくさん失敗してからその上を皆んなが歩いていく)という表現もしていました。つまり失敗を前提に作っていこうということでした。我が部も色々失敗を繰り返して成長できればいいなと思います。

2人目 待場勝利様

大学卒業後、アメリカへ映像制作を勉強。サムスン電子ジャパンでは Gear VRを担当したり株式会社ejeでVRのコンテンツに関わったりと、様々なVR制作に関わっている方です。
 現在は360度動画をメインに制作しているみたいで、今まで平面だった映像が立体にできるので、地味ではあるが深堀りして新たな表現をしていくと言っていました。
 待場様のお話しで一番印象に残ったのは、「オペレーションが重要」という話です。VRに慣れている方ならともかく、一般の方にはHMDを渡されてもそれをどのように使うかがわからないですよね。どの方が言っていたかは忘れてしまいましたが、お客さんにHMDを壊されてしまったことがあると話していた方もいましたので、特にハイエンドなHMDを使用する際にはオペレーションをしっかりしないとなあ、と感じました。

3人目 赤崎信也様

株式会社 積木製作の取締役 マネージャーをされています。機会エンジニアからCGの世界にきたそうで、現在は建築特化だそうです。
 赤崎様は「今VRを始めるメリット」について話していました。そのメリットとは、

  • 先駆者と呼ばれる

  • 今までのゲームや映画の概念を覆えせる

  • 市場を新たに創ることができる。価格も自分である程度は決めることができる(相場がまだ決まっていない)

とのことです。我らVR部部員がみな"先駆者"と呼ばれる者になれると考えると感慨深いですなあ。

4人目 古賀琢麻

株式会社アイロック 代表取締役 プロレーシングドライバーをされている方です。プロドライバーとして世界を転職してきて、そのドライビングレース経験を投入して開発をしたドライビングシュミレーターT3Rシュミレーターを開発、製造販売しています。
 古賀様は世界を見てきているので、他国と日本を比べた話をしてくれました。すごくストレートに「日本人は遅い、だって寝るもん」などとスケールのでかい意見が飛んできました。
 あと、早くやるって大事という話で、できるやつって最初にパーンッとやってあとダラダラ、最後修正って特徴があると思うとも言っていました。


このほかにも、パネルディスカッションで様々なことを聞けました。

  • 脳をどのように効率良く騙すか、脳がそれを本物だと思うエッセンスを考える

  • ものすごく妄想する(他人に自分の考えてることを事細かく説明できるようになるまで)

  • VRの最終目標は「どれだけ人の心をゆるがせるか」

  • 一般人には物語を見せないとダメ、すごい技術で盛り上がれるのは技術オタクだけ

  • 初心を忘れない!

  • 2020年にVRのキラーコンテンツが出るんじゃないか?

  • 脳科学、生理学、人文学、心理学などあらゆる分野に触れて「人間」を知ることが大事。つまりはVRってのは人間への追求

初めてHMDをかぶったときの感動を私はまだ忘れていません。初心にかえる上でも、その記憶は大事なものだと思うのでこれからも忘れずに開発をしていけたらいいなと思います。

4/8 (第2回)

2日目はあえて名前を伏せますが、Unityすごい方のお話を聞くことができました!

VR開発をしたい人には二つの道があるそうで、
「(VR開発ができる)会社に入りたい」という道と、「コンテンツを作りたい」という道です。

会社に入ってVR開発

「メリット」

  • OJT(職場で実際に実務をさせることで従業員の職業教育をすること)

  • 予算が出る

  • チーム開発としてそれなりに大きな規模の開発ができる


    「デメリット」

  • 自分のやりたいことができないかもしれない

もし、VR開発ができる会社に入りたいんだったら…?
「とにかくモノをつくる!」
今の会社でモノがなくて入れる会社はない。

VRの開発ができる会社に入社するパターン例として、

例1:
VRコンテンツ作った

ツイッターに経過を報告

VR開発者と仲良くなる

オフラインイベントで会う(VR展示会など)

就職


例2:
コンテンツ作る

VRについての技術記事を書いていく

VRイベントで登壇

SNS経由で会社からお誘い

就職


例3:
ゲーム会社でVRやりたいと申し出

却下されたので、もくもくと作った

世間がVR熱高まってきたので、手のひらクルー

アレオレ事変(あれは俺が作ったと、周りの人が言い出す)

腹が立って就職

きっかけは全部「つくる、だす!」からですね!

コンテンツを作りたい


空いている時間を使って作るしかないですね。
「メリット」
* もし利益が出るならばそれらは自分らのもの

「デメリット」
* 仲間を集めるのが大変

※講師の方も、いばらの道です、と言っていました。でも、部活であれば仲間集めというところはデメリットではないですね!!

作品について、
優れた作品には「属人性」が高い
優れた作品は一部の天才が作る

では平凡な人には?
「希少性で勝負!」
希少性は掛け算。珍しい×珍しい=めちゃくちゃ珍しい
VR×自分の分野=希少性が一つ生まれる

例: VRで福祉ってできないかな?
ある人はお年寄りを見ていて、VRで何かできないかと考えた。なかなか外に出ることができないご老人のための体験動画をある人が撮ってきて、ハコスコとかで見る!
VR×福祉×世界旅行
はどうだろうとある人は考え、彼はクラウドファンディングでお金を集めた。結果うまくいき、今では福祉領域で利用され始めている。ご老人が「ここに行きたい!」と思えばリハビリも頑張る気力につながりますよね!


自分はどんな掛け算ができるか考えてみよう。 VR×自分の分野×アイデア

まとめると、会社に入りたいんだったらとりあえず作る!!!作品作りたいんだったらVR×自分の分野×アイデア


「その他雑学」
* なぜHMDには一眼方式があるか?ーーー斜視が怖いため
* 90fps(=11ms/1フレーム)あればVR酔いしにくいと言われている
* 人間はFPS77までなら認識できるらしい(個人差はある)
* Unityアセットストアにて、欲しいものリストに多く登録されているアセットはキャンペーンで値引きされやすいらしい

written by Akiyama

この前のVRアカデミーで気になったところ 〜その1〜

この前のVRアカデミーで使ったプロジェクトデータで、初めから書いてあったコードで気になったところがあったので自分なりに色々してみた。

レイヤーとビット演算

当たったら呼ばれる OnCollisionEnter() 関数の中に

public class Arrow : MonoBehaviour {

    public LayerMask _hitableLayer;
    ・・・

    void OnCollisionEnter ( Collision collision ) {

        if (((1 << collision.gameObject.layer) & _hitableLayer) != 0) {
            /*
             * 衝突したオブジェクトが _hitableLayerに含まれるとき。
             * LayerMaskは複数のレイヤーを指定できてInspector上では扱いやすいが、
             * データ上はビット演算になっていて、直感的でない。
             * 指定のレイヤーにだけ反応するようにするには、上記の書き方をすると効率的。
            */

            「指定したレイヤーとぶち当たったレイヤーが同じだったときの処理」

        } else {
	   「それ以外のレイヤーにぶち当たったときの処理」
        }

    }

と書いてった。

if (((1 << collision.gameObject.layer) & _hitableLayer) != 0) { }

これなんだろう、、、見たことない書き方だなあ。<< を使ってるからビット関連かな、、、

ログに出して見た

Sample

    void OnCollisionEnter ( Collision collision ) {

	Debug.Log ("shift operation : " + ((1 << collision.gameObject.layer)));
	Debug.Log ("_hitableLayer : " + _hitableLayer.value);
	Debug.Log ("bit operation : " + ((1 << collision.gameObject.layer) & _hitableLayer));

        if (((1 << collision.gameObject.layer) & _hitableLayer) != 0) {
           ・・・
        } else {
           ・・・
        }
      ・・・
    }


「if文の条件が成り立ったときのログ」
f:id:aizu-vr:20170306202511p:plain:w200

「if文の条件が成り立たず else文のときのログ
f:id:aizu-vr:20170306202510p:plain:w200


_hitableLayer は public な変数で、Unityエディタから "Target" というレイヤーが選択されている。Tags & Layer からUnityに設定されているLayer一覧をみてみると、
f:id:aizu-vr:20170306204049p:plain:w300
となっていて、Target は8個目(0を入れると9個目)に設定されていた。

Debug.Log ("_hitableLayer : " + _hitableLayer.value);

のログでは 256 とでている。なんで "Target" から 256 が?きっと2進数からきてるのではないだろうか。

256 は 2の8乗。Target は8個目にあった。ここが関係してるのかと。


8 7 6 5 4 3 2 1 0 (桁)
1 0 0 0 0 0 0 0 0 (2進数) = 256(10進数)

1 << collision.gameObject.layer

というところはシフト演算なので、collision.gameObject.layer の値だけ 1 をシフトさせる。
Target レイヤー以外は Default レイヤー(0番目)で設定されているので 1 のままでシフトしない。よってログでも 1 が出力されている。

Target レイヤー(8番目)にあたったときは、8回シフトするので、
1 (0回目)
10 (1回目)
100 (2回目)
1000 (3回目)
10000 (4回目)
100000 (5回目)
1000000 (6回目)
10000000 (7回目)
100000000 (8回目) = 256(10進数)

よってログで 256 と出力されている。


この 1 か 256 の値と、_hitableLayer (256) を & でビット演算すると、

「1のとき」
000000001
100000000 &
ーーーーーー
000000000 = 0(10進数)

よって、if (((1 << collision.gameObject.layer) & _hitableLayer) != 0) { } が成り立たなくなる。

「256のとき」
100000000
100000000 &
ーーーーーー
100000000 = 256(10進数)

よって、if (((1 << collision.gameObject.layer) & _hitableLayer) != 0) { } が成り立つ。

こんなやり方があったなんて...。ビット演算シフト演算なので効率は良さそうですね。これはいいこと知ったっ!


ちょっと文章で書くのきつかったです。。。わかりにくくてごめんなさい。

あぁ〜、大学で2進数とかビット演算とか習うけどこーゆーところで使うんだなあ。と大学の勉強のモチベにもつながりました。またなんか気になるところ解決できたら投稿します。



written by Akiyama

VR Academy 〜3/4 プレ講座〜

3/4にVRプロフェッショナルアカデミーのプレ講座(3回目)が行われました。第2回目には私は参加できていないので、4月入って講座がはじまったときに第2回目に参加された方にどのようなことをやったのか聞いてみたいですね。第3回はVRの知識がついたというよりかは、Unityの知識がつきました。見たことはあるけど使ったことのない機能が色々でてきたので、ここに備忘録として記録しておこうと思います。


UnityEvent

public or SerializeField 属性の UnityEventを使うことによってコールバック関数をUnity側から設定することができます。
e-words.jp

例えば、

using UnityEngine;
using UnityEngine.Events;

public class TestEvent : MonoBehaviour {

	public UnityEvent publicEventTest;
	[SerializeField] private UnityEvent serializeFieldEventTest;

}

このようなコードをかいて空オブジェクトに付け加えてみると、
f:id:aizu-vr:20170305222436p:plain
のようにUnity側に先ほど作った UnityEvent がエディタにでてきます。こっからコールバック関数を指定できます。


〜 Sample 〜

先ほどのファイルを以下に書き換えました↓

using UnityEngine;
using UnityEngine.Events;

public class TestEvent : MonoBehaviour {

	public UnityEvent publicEventTest;
	[SerializeField] private UnityEvent serializeFieldEventTest;

	void Update() {

		if (Input.GetKeyDown (KeyCode.Space)) {
			publicEventTest.Invoke ();
		}

		if (Input.GetMouseButtonDown (0)) {
			serializeFieldEventTest.Invoke ();
		}

	}

}

UnityEvent名.Invoke() でUnityエディタから指定した関数を実行させることができます。今回は新しく DebugTest.cs というファイルを先ほどと同じように空オブジェクトに付け加えて以下のコードを書きました。

using UnityEngine;

public class DebugTest : MonoBehaviour {

	public void PrintDebug() {
		Debug.Log ("Debug test");
	}

	public void PrintInt(int num) {
		Debug.Log (num);
	}

}

PrintDebug()関数は引数を取らない関数で、PrintInt()関数はint型の引数を1つとる関数です。
この2つの関数をUnityエディタから UnityEvent に指定します。ドラッグ&ドロップで先ほどの空オブジェクトだったものをいれてあげます。
f:id:aizu-vr:20170305230431p:plain
そしたら、No Function とかいてあるボタンを押して関数が書いてあるファイル名から関数名を探して選択します。
f:id:aizu-vr:20170305230705p:plain
関数のアクセス修飾子が public でないと候補欄に関数がでてきませんので注意してください。
f:id:aizu-vr:20170305225935p:plain
2個目の関数の引数もUnityエディタから指定できますね(ここでは1996と入力しているところです)。

実行して、Spaceキーと左クリックを押すと、
f:id:aizu-vr:20170305231456p:plain
とログにでてきました!




シングルトン

シングルトン自体についてはWikiなどで調べてください。
シングルトンは私は今まで名前しか聞いたことありませんでした。こんなふうに実装するんだなあ、としみじみ思いました。

新しく SingletonTest.cs というファイルを作り、以下をかきました。

using UnityEngine;

public class SingletonTest : MonoBehaviour {

	private int num = 0;

	private static SingletonTest instance;

	private void Awake () {
		if (instance == null) {
			instance = this;
		} else if (instance != null) {
			Destroy(this.gameObject);
		}
	}

	public static SingletonTest GetInstance() {
		return instance;
	}

	public void Print() {
		Debug.Log ("Test" + num);
		num++;
	}

}

これを他のファイルから使います。

using UnityEngine;

public class UsingSingleton : MonoBehaviour {

	// Update is called once per frame
	void Update () {
		if (Input.GetMouseButtonDown (1)) {
			SingletonTest.GetInstance().Print();
		}
	}
}

これで右クリックをするとログに、
f:id:aizu-vr:20170305235643p:plain
こんな感じでながれてきました。


シングルトンについてはまだ私自身使い勝手がイマイチ理解できてないので、これから実践で使ってみて慣れていこうと思います。
あとクエストのオブジェクトループがよくまだわかってないのでわかったら追記しようかと。

written by Akiyama

VR Academy 〜プレ講座〜

1/28、VRプロフェッショナルアカデミーのプレ講座が行われました。
来年度の4月から本格的に始まる講座のために、VRがどのようなものか、ビジネスではどのように使われているか、VRコンテンツのジャンルはどのようなものがあるか、制作にはどのような知識・技術が必要かなどを約5時間で教えていただきました。

「VRの価値の3要素」

1、体験

映像をあたかも目の前の現実として経験している

2、時間、場所の超越

時間や場所の制約がない

3、超現実

そもそも現実では不可能な視点で見れる

これこそがVRの価値だと。これから作る作品にはこれらがふくまれているかに気をつけて開発していこうと思いました。

あと、このVRアカデミー4月からはじまって3ヶ月間毎週あるのですが、最後にいままで習ったものを使って作品を作り、その作ったものを企業の方々に来てもらって発表するらしいんです。いやあ、知らなかたです。すごく緊張しますが、普通の学生じゃ経験できないようなことだと思うので頑張ってみようと思います。

 その日学んだことを忘れないように、このブログを備忘録として記録していこうかと思います。っということで1/28の分書いていきます。


「カメラを2分割する」

f:id:aizu-vr:20170305132337p:plain

スマホのVRでは画面を2分割しますよね、まずその2分割の方法を書いていきます。

まず、Hierarchy に Camera を2つ用意します。(Hierarchy で右クリック -> Camera)
両方とも同じ座標に設置します。(Transform コンポーネントを同じにする)
その2つのカメラを空オブジェクトにいれておきましょう。(Hierarchy で右クリック -> Create Empty。その空オブジェクトを違うわかりやすい名前に変えておきましょう)
f:id:aizu-vr:20170305132654p:plain

Right/LeftCamera には最初から、

  • Transform
  • Camera
  • Flare Layer
  • Audio Listener

の Component がついています。同じシーンに ”Audio Listener” が2つ以上あるとUnity側から怒られるので片方消しておきましょう。

LeftCamera の Camera コンポーネントViewport Rect プロパティーの値をいじって2分割します。

Viewport Rect は X, Y, W, H の要素を持っており、X, Y はカメラビューを2次元の平面上のどこに表示するかを設定でき、W, H はカメラビューの表示の幅と高さを設定できます。すべて0~1の値です。

カメラビューの左上を軸として考え、左側のカメラのXを0、Wを0.5にします。2分割なので半分の0.5です。同じように右側のカメラのXを0.5、Wを0.5にすることによって2分割にできます。左右同じビューになっていればOKです。


「プラットフォームによってコードを分岐させる」

Unity上だとこのコード実行してほしいけど、スマホ上だとこっちのコードを実行してほしい...というときには、プラットフォームごとに処理を分けます。#if#elif をつかって分岐させます。

↓プラットフォームごとの書き方はこちらの公式のマニュアルを見てください
docs.unity3d.com

sample code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour {

	public float speed;
	Quaternion _attitude;

	// Use this for initialization
	void Start () {
		#if UNITY_EDITOR
		#elif UNITY_IOS || UNITY_ANDROID

		Input.gyro.enabled = true;

		#endif
	}

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

		#if UNITY_EDITOR

		if (Input.GetKey (KeyCode.LeftArrow)) {
			this.transform.Rotate (Vector3.up * -Time.deltaTime * speed, Space.World);
		}
		if (Input.GetKey (KeyCode.RightArrow)) {
			this.transform.Rotate (Vector3.up * Time.deltaTime * speed, Space.World);
		}
		if (Input.GetKey (KeyCode.UpArrow)) {
			this.transform.Rotate (Vector3.left * Time.deltaTime * speed);
		}
		if (Input.GetKey (KeyCode.DownArrow)) {
			this.transform.Rotate (Vector3.left * Time.deltaTime * -speed);
		}

		#elif UNITY_IOS || UNITY_ANDROID

		_attitude = Input.gyro.attitude;
		_attitude.x *= -1; _attitude.y *= -1;
		this.transform.rotation = Quaternion.AngleAxis(90f, Vector3.right) * _attitude;

		#endif
	}
}

これを書いたファイルを Cameras に付け加えると、iPhoneまたはAndroidだったら内臓されているジャイロセンサーをONにして、デバイスの向きをとりそれをカメラの向きに代入してくれます。


第1回はこんな感じでした。来年度から本格的に始まる前にやっとくことをおすすめされたところをやっておき万全の状態で挑みたいですね

written by Akiyama

VR部 ブログ開設

これから学んでいくことを忘れないための備忘録や、これから入部してくれる部員たちのために学んだ知識を書き残していきましょう!
VR部のブログではありますが、もちろんVRに関係ないことも投稿してくれても大丈夫です。(例えば大学の講義で習ったこととか...)

何か記事を書き込むときには、

  • カテゴリーを選択
  • 名前

をお願いします!

それでは、これからみんなで頑張っていきましょーっ!

written by Akiyama

会津大学VR部の部員が持ち回りで投稿していくブログです。特にテーマに縛りを設けずに書いていきます!