VRアカデミーにて行われた「VRハッカソン」チーム制作コンテンツ
ハッカソンテーマ:360度でVRならではの体験ができるもの
テーマが360度ということなので「音」と「視線」に重点を置き作成しました。
概要
目の前に現れた3つのドア。
ドアの中では不思議で奇妙な悪夢が待っていた。
コンテンツ解説
プレイヤーは3つのドアから好きなものを選択し中に入ります。
基本的には3つのシーンがあり、ドアを選択することでそのうち2つを体験できます。
シーン内容
スタートシーン
3つのドアから選択する
チキンシーン
鳥のおもちゃが迫ってくる部屋
パンツマンシーン
パンツ男があらゆる方向から襲い来るシーン
お母さんシーン
巨大なお母さんが迫りくるシーン
エンドシーン
ベッドの上で目が覚める
本当に夢だったのか!?
担当範囲
私はパンツマンシーンと各シーンの遷移方法を担当しました。


パンツマンシーン解説
シーンが始まるとパンツマンが目の前に登場します。
しばらくすると視線の方向に設定されたオブジェクト「eyesight」(meshオフで透明)が有効になり
自分の向いた方向のパンツマンが倒れていきます。
eyesightには以下のスクリプトがついており、パンツマンに設定されたEnemy tagを検知すると数をカウントし、数によって次のパンツマン集団を出現させるようにしています。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class manactive : MonoBehaviour
{
// Start is called before the first frame update
public GameObject Enemypoint2;
public GameObject Enemypoint3;
public GameObject Enemypoint4;
public GameObject Enemypoint5;
public GameObject Enemypoint6;
public GameObject Enemypoint7;
public GameObject Door;
public GameObject field;
public GameObject text;
public int count = 0;
void Start()
{
text.SetActive(false);
}
// Update is called once per frame
void Update()
{
if (count >= 15)
{
Invoke(“appear2”, 3f);
}
if(count >= 25)
{
Invoke(“appear3”, 3f);
}
if (count >= 50)
{
Invoke(“appear4”, 3f);
}
if (count >= 80)
{
Invoke(“appear5”, 3f);
}
if (count >= 90)
{
Invoke(“appear5”, 3f);
}
if (count >= 100)
{
count = 0;
Invoke(“Doorappear”, 5f);
Invoke(“fielddelete”, 5f);
Invoke(“appear7”, 5f);
Invoke(“delete”, 7f);
field.SetActive(false);
}
}
public void appear2()
{
Enemypoint2.SetActive(true);
}
public void appear3()
{
Enemypoint3.SetActive(true);
}
public void appear4()
{
Enemypoint4.SetActive(true);
}
public void appear5()
{
Enemypoint5.SetActive(true);
}
public void appear6()
{
Enemypoint6.SetActive(true);
}
public void appear7()
{
Enemypoint7.SetActive(true);
}
public void delete()
{
Enemypoint2.SetActive(false);
Enemypoint3.SetActive(false);
Enemypoint4.SetActive(false);
Enemypoint5.SetActive(false);
Enemypoint6.SetActive(false);
}
public void Doorappear()
{
Door.SetActive(true);
}
public void fielddelete()
{
field.SetActive(false);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == “Enemy”)
{
count++;
}
}
}
パンツマンにはRagdollとAudioSource、Animator(走るアニメーション)、プレイヤーに向かって移動するスクリプトがついています。視線を向けられるとパンツマンに付けられた以下のスクリプトによりAnimatorと移動スクリプトが無効化され落下します。プレイヤー側で数を何度もカウントされないようにtagを変更します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Businessman : MonoBehaviour
{
// Start is called before the first frame update
public GameObject man;
private Animator animator;
public AudioClip sound1;
AudioSource audioSource;
void Start()
{
//Componentを取得
audioSource = man.GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
}
public void Audiooff()
{
man.GetComponent<AudioSource>().enabled = false;
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == “Tarai”)
{
man.GetComponent<Animator>().enabled = false;
}
else if (other.gameObject.tag == “eyesight”)
{
//音(sound1)を鳴らす
audioSource.PlayOneShot(sound1);
man.GetComponent<Animator>().enabled = false;
man.GetComponent<move_lookat>().enabled = false;
this.tag = “Down”;
Invoke(“Audiooff”, 2f);
}
}
}
基本的にはパンツマン登場→視線を向けて倒す
を繰り返し、一定数倒すと次のシーンへの扉が現れる仕組みとなっています。
パンツマンの登場時に効果音(3D音源)をつけることで背後や上下の方向から音がするので、自然とパンツマンの方向を向き、最終的に360度の体験ができるよう工夫しました。
シーン遷移
Scene Controllerを用意し、static変数を設定。
シーン始めにcountをプラス1していき、カウントが2になった状態で遷移するとエンドシーンに遷移するようにしました。
スタートシーン
countを0にリセット
↓
シーン1開始
countに+1
↓
シーン2開始
countにさらに+1で2になる
↓
エンドシーンに遷移
↓
スタートシーンに戻る
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Scenecontroller : MonoBehaviour
{
// Start is called before the first frame update
public static int count = 0;
void Start()
{
count++;
}
// Update is called once per frame
void Update()
{
Debug.Log(count);
}
}
各シーンのドアには以下のスクリプトを設定し、上記で設定したcount変数を読み取り、値によって各シーンにランダム遷移(ランダム変数使用)します。
シーン遷移は手にHand タグをつけてドアに入った段階で遷移します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine;
public class SceneChange : MonoBehaviour
{
// Start is called before the first frame update
public GameObject gameobject;
// Scenecontroller script;
private int count2;
private int ramValue;
OVRScreenFade fade;
GameObject CenterEyeAnchor;
void Start()
{
CenterEyeAnchor = GameObject.Find(“CenterEyeAnchor”);
fade = CenterEyeAnchor.GetComponent<OVRScreenFade>();
//script = gameobject.GetComponent<Scenecontroller>();
}
// Update is called once per frame
void Update()
{
count2 = Scenecontroller.count;
//count2 = script.count;
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == “hand”)
{
ramValue = Random.Range(1, 4);
Debug.Log(ramValue);
if (count2 == 2)
{
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove3”, 5f);
}
else if(count2 == 1)
{
fade.FadeOut(0.0f, 1.0f);
switch (ramValue){
case 1:
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove”, 5f);
break;
case 2:
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove”, 5f);
break;
case 3:
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove2”, 5f);
break;
case 4:
fade.FadeOut(0.0f, 1.0f);
Invoke(“Scenemove2”, 5f);
break;
}
}
}
}