大阪電気通信大学

他者の装備の鹵獲に重点を置いた拠点防衛型 VR シューティングゲームの制作

作品概要

プレイヤーはVRゴーグルを着用し、VR空間上に存在する銃を使用して自陣に攻め込む敵を迎え撃つ。

銃に必要な弾薬は倒されたNPCから回収する必要があり、残弾数を考慮した戦闘を行う必要がある。

ゲームクリア条件

一定数の敵(赤色のNPC)を倒した後に、30秒間生き延びる

クリアに必須の数の敵を倒すと、30秒間のカウントダウンが始まる。

ゲームオーバー条件

プレイヤーのHPが0となるか、自陣が敵に攻め落とされる

プレイヤーの体力は右手の甲に表示されている。また、味方NPCおよび自陣の旗は青、敵NPCおよび陥落時の自陣の旗は赤で表現されている。

工夫した点

1. ステートベースの NPC

敵と味方のNPCはステート(自身の状態) ベースの思考ルーチンを持っており、 状況に応じて適切な行動を行う。 例えば、プレイヤーの防衛目標である 陣地を保持している 味方NPC は陣地の周囲をパトロールし、接近する敵NPCを発見すると交戦する。

各NPCの状態を表した図

ステート処理の制御および実装方法

ステート処理は各NPCにアタッチされたスクリプトで制御されている。以下はアタッチされたスクリプトの内、拠点へ移動する際のステート処理を抜粋したものである。

現在のNPCのステート(currentState)の変更には、Switch文と各ステート内にあるif文を用いている。

void Update()
{
    switch(currentState) //currentState : 現在のNPCのステート
    {
        case State.GoToCapturePoint: //拠点へ向かうステート
            if(stateEnter) //このステートへ切り替わった際に初めに実行される処理
            {
                stateEnter = false;
                agent.destination = CP_transform_position; //NPCの目的地をセット(拠点)
                agent.speed = moveSpeed; //このステートでのNPCの移動速度をセット
            }

            if(hp<=0) //hpが0以下なら死亡ステートへ移行
            {
                changeState(State.Dead);
            }

            if(Vector3.Distance(eyePosition.position, CP_transform_position) < 10.0f) //拠点の手前10mまで近づいた時
            {
                if(this.gameObject.tag == "Allies") //味方NPCの場合
                {
                    if(cp.GetAlliesList().Count>=CaptureMembers) //拠点内の味方NPCの人数が十分足りている場合
                    {
                        if(!cp.GetAlliesList().Contains(this.gameObject)) //人数は足りているが、自分はまだ拠点内には入っていない場合
                        {
                            changeState(State.Defence); //拠点に侵入せず周囲を警戒
                        }
                    }
                }
                else if(this.gameObject.tag == "Enemy") //敵NPCの場合
                {
                    if(cp.GetEnemyList().Count>=CaptureMembers) //拠点内の敵NPCの人数が十分足りている場合
                    {
                        if(!cp.GetEnemyList().Contains(this.gameObject)) //人数は足りているが、自分はまだ拠点内には入っていない場合
                        {
                            changeState(State.Defence); //拠点に侵入せず周囲を警戒
                        }
                    }
                }

                if(Vector3.Distance(eyePosition.position, CP_transform_position) < 3.0f) //拠点の手前3mまで近づいた時(拠点内の人数が不十分な場合)
                {
                    changeState(State.Capture); //占領ステートへ移行
                }
            }

            if(searchEnemy()) //索敵を行うbool型の関数"searchEnemy"を実行し、true(敵対陣営のキャラクターが視界内にいる)なら交戦ステートへ移行
            {
                lastState = currentState; //交戦終了時に生存していれば、このステートへ戻る
                changeState(State.Engage);
            }

            break;

2. 射撃が苦手な人向けの NPC の弱体化機能

プレイヤーの射撃が NPC に命中しなくても、NPC の周囲に弾が飛んできた際に、 NPC が数秒間攻撃不可(畏怖状態)となるようにした。これによって、射撃が苦手なプレイヤーでもこのゲームをプレイし易くするようにした。

3. 装備を鹵獲しないとクリアが困難なゲームバランス

本ゲームはプレイヤーが VR 空間上のオブジェクトに触れる機会を増やすため、 プレイヤーが持てる 銃の予備弾倉を少なくし、NPCが倒されると、持っていた銃を落とすシステムとした。 このシステムによって、プレイヤーには残弾を管理しつつ、弾薬を無駄にしない射撃スキルが求められるようになった。

倒した敵の銃を拾う様子。プレイヤーは銃の予備弾倉を最大で2個まで保持できる。

動作環境

【OS】Windows10, Windows11

【VRヘッドセット】Oculus Riftシリーズ, Oculus Questシリーズ

【CPU】Core i5 10400

【GPU】Radeon RX 6650XT

【RAM】32GB

※CPU, GPU, RAMは開発に使用したPCに搭載されていたものです。

操作方法

①移動

➁視点切り替え(左右のみ)

③物を掴む

④発砲

作者プロフィール

藤井 玲守

総合情報学部 デジタルゲーム学科

ソフトウエア科学研究室所属

模型製作、味の濃いものが好き

コメント