たつぷりの調査報告書

博士後期課程(理学)の学生が趣味でUnityやBlenderで遊ぶブログです。素人が独学で勉強した際の忘備録です。

パズル的要素を実装してみた(第1回:近づくと操作できるようにする)

こんにちは,たつぷりです.前記事の次回予告で「イベントシーンの実装をするよ」と言ったのですが,先にやりかけていたことがあったのでそちらをまず解決することにしました.

それは,アイテム管理の実装です.具体的にはステージ中で鍵を拾って,その鍵を用いて扉を開けたりできるようにしたいということです.これを実装することでゲームに若干のパズル的要素を加えることができるので,ただ敵を倒したり逃げたりするだけのゲームよりもメリハリをつけることができると考えました.なのでしばらくは,

  • アイテム(鍵を想定)を取得し,
  • アイテム管理画面からアイテムを使用し,
  • 使用したアイテムに応じてイベントを起こす

といった流れをゲームに取り入れることを目指していきたいと思います.

現状の紹介

まず初めに今回の開発の前提となる,プロジェクトの現状についてまとめておきます.現状は以下のようになっています.

  • 扉などに近づくと,コントローラーのボタンに対応したアイコンが出現
  • そのボタンを押すとシーン遷移を行う
  • シーン遷移の直前にはプレイヤーの情報を書き込むためのシングルトンオブジェクトに情報を格納

これを以下のように改善していきます.

実装したいこと

第1段階:鍵のかかった扉の実装

  • 扉に鍵の情報を格納する.例えば「None」や「Key1」などを列挙型変数として設定できるようにしておく
  • 鍵の情報に応じて発生するイベントを分岐させる.例えば「None」なら特定の鍵がなくてもシーンが遷移.「Key1」ならKey1があればシーン遷移,なければ「鍵がかかっている」というテキストを表示

第2段階:アイテムの情報管理の実装

  • アイテム情報を格納するためのスクリプトを作成し,オブジェクトに貼り付ける
  • アイテムを取得するための関数の作成.具体的には,アイテム情報をプレイヤーオブジェクトに書き込む
  • シーン遷移の前に特定のアイテム(鍵)を持っているか判定する
  • アイテム管理パネルからアイテムの管理・アイテムの使用を行えるようにする

以上のように意外とやることが多そうなので,何回かに分けて記事にしようと思います.

今回の目標

今回目標にするのは,オブジェクトに近づくことで何か操作したりイベントを起こしたりできるシステムを作ることです.これを用いると次のようなことができるようになります.

  • 扉を開けてシーンを遷移
  • アイテムの取得
  • 説明文を表示

上の二つは説明するまでもないので最後の「説明文を表示」という部分を補足しておくと,これはステージ内で演出・攻略目的でテキスト表示させることです.例えばゲーム序盤で窓の外を見て「見覚えないの景色だ,ここはどこだろう」などと表示すれば,主人公はどこかに連れてこられたのか?などと思わせることができます.このようなゲームの雰囲気作りだけでなく本質的なヒントなどを示すのにも使えると思います.

今回は具体的に「鍵のかかっていない扉」を作ってみます.「鍵のかかっていない扉」はここでは以下のような性質を持ったオブジェクトであると定義します

  1. プレイヤーが近づき,かつ正面を向いている時に入力受け付け中を表すアイコンをオブジェクトの上に表示する
  2. 1の時,実際に入力が行われるとシーンを遷移する

今回作るのはこのようにシンプルなものですが,ここに色々を追加していくことでより複雑な処理を可能にする最も基本的なシステムだと思います.

鍵のかかっていない扉

では実際に鍵のかかっていない扉を実装していきます.下にスクリプトを添付してあるので参考程度にみてください.

条件を表現する

まず,1の条件条件「プレイヤーが近づき,かつ正面を向いている」を表現する方法を考えます.この条件の前半部分を記述するために扉とプレイヤーとの距離を測ります.これは扉の位置ベクトル(this.transform.position)とプレイヤーオブジェクトの位置ベクトル (player.transform.position)の差から計算できます.ベクトルの基本を思い出すと,

player.transform.position - this.transform.position

扉を基準にしたプレイヤーまでのベクトルです.これの距離,すなわち絶対値を閾値と比較して扉の近くにいるかどうかを判定します.次に後半の条件,プレイヤーが正面(扉)を向いているかどうかは,高校数学を思い出すとプレイヤーの前方方向

playerTrans.forward

とプレイヤーから見た扉へのベクトルの内積によって表現できます.例えばこれらが直交している時,すなわちプレイヤーの真横に扉がある時はこの内積が0を返し,それよりも前方にいる時はこの内積が正の値を返します.

以上より,条件「プレイヤーが近づき,かつ正面を向いている」を表現できるようになりました.

アイコンの表示

なのでこれを満たしていると時にはアイコンを表示するようにします.基本的にはアイコンを入れたCanvasのSetActiveのtrue/falseを入れ替えれば良いのですが,これだけではプレイヤーの位置に応じて時時刻刻と変化する扉の位置に動的にアイコンを表示させることができません.これを実現するにはゲーム空間上の扉の位置をCanvas上に射影してそこにアイコンを表示させる必要があります.これは

RectTransformUtility.WorldToScreenPoint

を用いて実現することができます.下のIcon.csです.これをアイコン(Imageオブジェクト)に貼り付けておけばプレイヤーの位置が変わったらそれに応じてアイコンの表示位置を変えることができます.

シーン遷移

今回は条件を満たし,その時に入力があれば問答無用でシーンを遷移します.シーン遷移は

SceneManager.LoadScene("Scene Name");

で実現できます.

以上より,鍵がかかっていない扉を制御するスクリプトとして以下のようなものを提案します.

gist62913427ca837805421701723b02c121