ステージギミックの作成
どうもこんにちは,たつぷりです.皆さんご存知の通り,UnityではProbuilderを用いて簡単にステージのプロトタイプを作成することができます.今回の記事ではProbuilderを用いて作成したステージにギミックを作ってみたいと思います.ここでギミックと言っているのはスイッチをONにすると扉が開いたりエレベーターが動く,落とし穴が開く,といったことを想定しています.
参考映像
今回作成したギミックの動作テストをYouTubeにアップしています.
動くギミックの要素
上で具体的にあげた例の自動扉やエレベーター,落とし穴はいずれも以下の要素からなります.
扉やエレベーターの実体のオブジェクト
ギミックを作動させるための操作盤
オブジェクトを移動させるスクリプト
ここで,1はProbuilderで作ったもの,2は以前作成した鍵のついた扉の仕組みを流用することで作成できます.よって今回は3のオブジェクトを移動させるためのスクリプトの作成を行います.
必要な情報
まずはギミックを実装する上で必要な情報は何か整理します.基本的には,
どの方向 に どのくらいの距離 を動かすか
どれくらいの早さで操作を完了させるか
の情報で記述できそうです.後者を定義しておかないとオブジェクトを瞬間移動させることになってしまいます.
まず前者は,移動の変位分のベクトルに他なりません.これを与えることで方向と,距離の情報を得ることができます.後者は「何フレームで操作を完了させるか」を指定する整数を与えれば良いです.これを以下ではステップ数と呼ぶことにします.
これによって,与えた変位ベクトルの距離をステップ数で割った1フレームあたりの変位ベクトルを定義することができます.つまりUpdate関数のなかでステップ数の回数だけ変位ベクトルを動かすことで,少しずつ動かすことができます.
以上の情報に加えて,扉が開いているかどうかの情報も記述することにします.これによって扉を開けっぱなしにするのではなく,開け閉めをすることができます.
より具体的には,扉が閉まっている時は与えられた変位ベクトルだけ動かし,開いている時は与えた変位ベクトルの絶対値が同じで向きが反対のベクトルだけ動かすことによって開け閉めを実装することができます.ここまでをまとめると以下の情報を与えることでギミックを実装することができます.
変位ベクトル(Vector3)
操作が持続するフレーム数(int)
扉が開いてるか否か(bool)
実装
では実際に上で整理した情報を用いてギミックを実装していきます.
1フレームあたりの変位ベクトル
1フレームあたりの変位diff(Vector3型)を以下のように定義します.
[SerializeField] Vector3 dir; //与えた変位ベクトル Vector3 diff; diff = 1.0f/(float)step * dir;
与えたベクトルの大きさを単純にステップ数で割っただけです.ただし注意したいのは,Vector3の絶対値はfloat型なのでint型で定義したステップ数はfloatにキャストして使う必要があります.
オブジェクトの移動
オブジェクトの位置を移動させるのはTranslateメソッドで実現できます.先ほど定義したdiffを使って
this.transform.Translate(diff);
をUpdate中に実行することで各フレームでdiffずつ変位を与えることができます.これをステップ数の回数だけくり返すことで期待通りの動きが実現されます.
扉が開いているか否か
上で示した扉を開ける操作が完了したら,扉の開閉を格納するbool値変数を反転させるようにしておけばそれで完了です.私の認識ではbool値の反転は,
bool hoge = true; //bool値変数の宣言・初期化 hoge = !hoge;//変数hogeの反転
というようにして実装するのが簡単です.
補足
今回オブジェクトはTranslateで移動させていますが,これは基本的には物理を無視した瞬間移動のようです.ですから今回実装した具体例のエレベーターでは下に降りる際にプレイヤーが慣性で置いていかれるようなことが起きてしまいます.これはいろいろ解決法があると思いますが,今回は対処療法的ですがPlayerSetting>Physics で重力加速度を変更しました.defaultでは地球上の重力加速度と同じ9.8m/s2になっていますが,これを10倍ほど大きくしてとりあえず床に置いていかれない道ように改良しました.
まとめ
今回はPribuilderで作ったステージにギミックの作成を試みました.今のところスイッチで動作する自動扉とエレベーターを作成してみました.他に応用できる例として自分が考えているのは(最初にも述べましたが)落とし穴の実装です.「スイッチを押したら落とし穴が開いて敵を落とした後にもう一度スイッチを押して蓋をしてプレイヤーが通れるようにする」といったことができるようになれば攻略の幅も広がって面白そうだなあーっと思っています.
だんだんProbuilderを使って自作の建造物が作れるようになってきました.今後,もう少しProbuilderを用いたレベルデザインに関して知識が溜まってきたら改めて解説記事を書きたいと思っています.
ではまた,次の記事でお会いしましょう.たつぷりでした.
パズル的要素を実装してみた(第1回:近づくと操作できるようにする)
こんにちは,たつぷりです.前記事の次回予告で「イベントシーンの実装をするよ」と言ったのですが,先にやりかけていたことがあったのでそちらをまず解決することにしました.
それは,アイテム管理の実装です.具体的にはステージ中で鍵を拾って,その鍵を用いて扉を開けたりできるようにしたいということです.これを実装することでゲームに若干のパズル的要素を加えることができるので,ただ敵を倒したり逃げたりするだけのゲームよりもメリハリをつけることができると考えました.なのでしばらくは,
- アイテム(鍵を想定)を取得し,
- アイテム管理画面からアイテムを使用し,
- 使用したアイテムに応じてイベントを起こす
といった流れをゲームに取り入れることを目指していきたいと思います.
現状の紹介
まず初めに今回の開発の前提となる,プロジェクトの現状についてまとめておきます.現状は以下のようになっています.
- 扉などに近づくと,コントローラーのボタンに対応したアイコンが出現
- そのボタンを押すとシーン遷移を行う
- シーン遷移の直前にはプレイヤーの情報を書き込むためのシングルトンオブジェクトに情報を格納
これを以下のように改善していきます.
実装したいこと
第1段階:鍵のかかった扉の実装
- 扉に鍵の情報を格納する.例えば「None」や「Key1」などを列挙型変数として設定できるようにしておく
- 鍵の情報に応じて発生するイベントを分岐させる.例えば「None」なら特定の鍵がなくてもシーンが遷移.「Key1」ならKey1があればシーン遷移,なければ「鍵がかかっている」というテキストを表示
第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");
で実現できます.
以上より,鍵がかかっていない扉を制御するスクリプトとして以下のようなものを提案します.
ストーリーの演出の仕方について考えてみた
どうもたつぷりです.ゲーム開発をちまちま進めてきて,ゲームシステムやUIも少しずつできてきたので,徐々に「それっぽさ」は出てきたと個人的には思えるようになってきました.
しかしまだ自分が思うゲームの要素として足りないものがあります.それはストーリー性とそれを表現するイベントシーンです.これは私の趣味ですが,ある程度ストーリーのあるゲームの方がやりがいがあります(バトロワ系とかはそれはそれでめっちゃ好きですが...).
ストーリーをどう演出すればいいのか?
というわけで,今回は自分の思うストーリーの表現方法についてまとめてみます.この記事ではストーリーそのものの構成法ではなく,ゲームを実装する際の演出の方法に的を絞って考えてみます.続く記事で具体的にイベントムービーの作成に取り組んでいく予定ですので興味のある方はぜひそちらもご参照ください.尚,ここではホラーゲームやアクションゲームのストーリーを念頭に置いていますのでご注意ください.
まずストーリーを演出するために可能な方法を(素人考えですが)私なりに列挙してみました.
- ステージ上の小物として新聞やレポートなどを配置し,過去に起こった出来事を書いた客観的な情報を開示することでプレイヤーに理解させる
- イベントシーンとしてムービーを再生し直接的にストーリーを演出する
- ステージの雰囲気・構造などからプレイヤーに悟らせる,ストーリーを理解するために重要と思われるものをただゲームの中に登場させプレイヤーに考察してもらう
などがパッと思いつくことです.それぞれについてもう少し考えてみたいと思います.
ステージに情報を開示のためのオブジェクトを配置(静的な情報開示)
- この方法はまず実装が非常に簡単です.ステージ中に適当に開示したい情報を格納したオブジェクトおくだけで実行でき,台詞や説明文を出すためのプログラムを既に書いていれば流用できます.
- この方法を使うと舞台となる場所などに関しての背景知識を提供することができます.
- またステージをすすめるに連れてより確信に迫る情報を開示していけばプレイヤーは真相に近づいていく高揚感や、情報によっては不穏さや恐怖を演出することができます.
- しかしこの方法ではプレイヤーに直接関係する出来事をストーリーとして演出できません.
例:研究施設の謎
例えば「この街にあった研究機関で実験中に事故が発生,研究者ら数名に精神異常などがみられその後死亡が確認された.」と書いた新聞記事などを配置しておけば,これだけでこのゲームでは何かこの実験に関わる敵が出てくるなということを印象づけられます.
ゲームが進行するに連れてさらに,「その実験のもみ消された事実」や「裏で糸を引いている人物からの指示」などが書かれたレポートなどのオブジェクトを配置しておくとゲームを進めるに連れて真実に近づいていく感覚を演出できます.
イベントシーンを用いる(動的な情報開示)
- 上の方法では文字や静止画と言ったものの情報しか与えられないのに対しこちらは映像として強制的にその世界を体験・追体験させることができます.
- ストーリーを直接伝えるための手段としてだけではなく恐怖を煽るような演出などにも使えます.
- この方法は没入感を与えることができる一方で作りが雑だとむしろ興醒めする危険があります.
例:敵に至る恐怖
過去に起きた事件を追体験するムービーを作ったとしましょう.それが,ある場所で強力な敵が現れ殺されるという旨のムービーだったすると,その後その場所に到達した際になにも説明しなくても「あいつが来る」と思わせることができるし,そこに至るまでの道中の所々をムービーに入れておけば,自分も敵に近づいている恐怖とそれと同時に核心に迫っていく高揚感といったを演出することができるでしょう.
プレイヤーに考察させる(消極的な情報開示)
- これを狙って演出するにはオブジェクトの配置など綿密な計画が必要
- プレイヤーが自ら考察ことで一層の没入感が得られる
- 難解なストーリーを理解したいと思わせることで,プレイヤーのゲームへの動機を提供する.
- やり込み要素の一つにもなる.
- 紙一重でわけの分からないだけの「クソゲー」になってしまう.
例:呪われた人形
ステージの最中で何度も同じオブジェクトを出すことをと考えます.簡単な例として,ホラーゲームで人形を何度もステージに配置することを考えてみましょう.こうするだけで「この人形の持ち主の呪いなのか...?」といったことをプレイヤーに悟らせることができます.さらにある場所では,人形が無惨な姿になっていれば「ここで何か事件が起きたのか?持ち主は何かに殺された?」と思わせたり,一方で人形が吊るされていれば,「持ち主は自殺したのか?」というように悟らせることができます.このようにオブジェクトの配置の仕方を変えるだけでプレイヤーに悟らせる内容は大きく変えることができそうです.
結局どう演出するのがいいのか?
上で見てきたように演出の方法にはいくつかの系統があります.そしてそれらには長所短所があるので自分の望む演出,開示したい情報の種類に応じて使い分ける必要があるのは確かだと思います.
それと同時にどれか一つの表現方法に固執してしまうのもプレイヤーを飽きさせてしまうのかもしれません.複合的に用いることでメリハリをつけたりストーリーを伝えやすくなるかもしれません.
- 例えば,始めのうちは消極的な情報開示で不安を煽りつつ話に引き込み,徐々に静的・動的なな情報開示で答え合わせをしていくような方法をとると,プレイヤーは謎が解けていく感覚を楽しむことができます.
有名なゲームでの例
バイオハザード7の内容を思い出すと(一応ネタバレしないように陽には書きません),
- 最初の方で何度もお婆さんが出てきます.これは消極的な情報開示と考えられます.
- 最終的には研究に関してのレポート見つけたり,戦闘シーン前のイベントなどで真相に迫っていきます.
- また最終的にあえて謎を残した状態で終わるのも考察のしがいがあってプレイしたあとでも楽しませることができる演出と言えるかもしれません.
- このゲームでは途中でプレイヤーが切り替わり過去の事件をゲームとして追体験させたりする方法もとられています.
まとめ
結局,様々な表現方法を目的に応じて適宜,複合的に組み合わせるとことに落ち着きそうです.適当にストーリーをデザインするのではなく,これらを念頭において自分がどのような雰囲気のゲームにしたいか,どうストーリーを展開したいかを練る必要があると考えられます.
しかし結局は趣味でつくるゲームなので,自分の思想出すことが一番大事だとは思います.
次回はこのような形式的な話ではなく,実際にイベントシーンの実装方法についてまとめていきたいと思います.
それではまた.