Unity公式チュートリアルSurvival Shooter WITH PK Chapter.19「照準を表示する」

19.照準を表示する

射撃がどこに飛んでいくかの目安となる照準(レティクル)を表示します。

画像を用意する


今回は32*32pixelで画像を書きました。これをCanvas上に設置し、マウスカーソルの位置を追うようにします。

Reticleクラスの実装

Reticleクラスを作成し中身を実装していきます。

超シンプルですが、ほぼ意図通りの挙動です。

バグ

射撃は、GunBarrelEndオブジェクトの正面に向かって真っすぐ飛んでいく実装になっています。
ただ、射撃の始点であるGunBarrelEndオブジェクトがPlayerの正中線よりやや右に設置されているため、レティクルの位置と実際に射撃が飛んでいく位置がずれてしまっています。
GunBarrelEndオブジェクトの位置を調整してみようと試行錯誤したのですがうまくいかず。このバグは仕様にしようそうしよう。

次回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.20「弾切れ、リロード中、武器チェンジ中をわかりやすくする」

前回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.18「カメラシェイク」

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.18「カメラシェイク」

18.カメラシェイク

カメラシェイクとは、カメラ=画面が小刻みにぶるっと震える演出のことです。ダメージを与えた、受けた、壁に激しくぶつかったなど視点が揺れるときの演出として使います。今回はダメージを与えた時に画面が揺れるようにしてみましょう。かなり臨場感が増しました!

CameraShakeクラスの実装

新しくCameraShakeクラスを作成し、MainCameraにアタッチします。
ShakeTimeの値が正の間カメラが揺れ続け、Update内でShakeTimeの値を減らしています。負の値になると揺れが止まります。
PlayerShootingクラスのShootメソッド内で、ダメージを与えるタイミングでShakeTimeに揺らしたい秒数を入れることでカメラシェイクを実行しています。

public class CameraShake : MonoBehaviour {

public float ShakeTime { get; set; }

private void Start()
{
ShakeTime = 0.0f;
}

private void Update()
{
if (ShakeTime > 0.0f)
{
ShakeTime -= Time.deltaTime;
ShakeCamera();
}
else if(ShakeTime <= 0.0f)
{
ShakeTime = 0.0f;
}
}

public void ShakeCamera()
{
//カメラの揺らし幅
float x = Random.Range(-0.1f, 0.1f);
float y = Random.Range(-0.1f, 0.1f);

//カメラを揺らす
transform.position += new Vector3(x, y, 0);
}
}

次回はコチラ(執筆中)

前回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.17.5「リファクタリング」

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.17.5「リファクタリング」

17.5 リファクタリング

幻の第17回でコードを引っ掻き回した結果、PlayerShootingクラスが鬼のように見づらくなりました。今回は、リロードと武器チェンジの処理を別クラスに引っぺがし、射撃処理自体も関数化することで可読性を高めるリファクタリングを行います。どちらかというと、「こうなりました」という報告。

PlayerReloadクラス

今回Interfaceを練習がてら使ってみました。ただ、武器種ごとにリロードを実装するつもりだったのが結果的にReload関係のクラスは1つで済んだので、Interfaceの用途としては正しくありません。

Interfaceの説明については、こちらの説明が簡潔で非常に理解しやすかったです。
https://qiita.com/Akira_Kido_N/items/7cd18944173cd4cd7229

イメージをつかんだらこちらを読んでより本質的な理解に進むとよいかと。
https://niconare.nicovideo.jp/watch/kn3404

PlayerChangeWeaponクラス

switchの中をもっと共通化できないか30秒くらい悩んでできなさそうだったのであきらめました。

PlayerShootingクラス

全部張ると長くなるので、UpdateとShootメソッドだけ。特にShootメソッドの可読性が上がってます。

リファクタリングはうまくはまるとパズルを解いたような快感がありますね。漫画やゲームの整理が昔から好きだったのでその楽しさにも似てるかも。

次回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.18「カメラシェイク」

前回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.16「調整:攻撃中の移動速度を遅くする」

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.17「調整:ノックバックを実装する」

17.調整:ノックバックを実装する

アクションゲームには欠かせないといってもいいノックバック演出。攻撃を当てた瞬間に、敵やプレイヤーの動きが止まってからリアクションが始まるというもの。

実装に当たって改めてノックバックについて調べてみると、様々なタイプがあるようです。ゲーム内の時間を丸ごと止めるもの、敵だけ、プレイヤーだけ止めるものなどなど。どのようなノックバックがあるかについては、下記の動画が大変参考になりました。

ゲーム開発でのヒットストップ調査

なんでもチャージショットで決めてしまうサムスが強すぎる【スマブラWiiU】

格闘でなく射撃であることを考慮すると「敵だけを止める」タイプのヒットストップが適しているかと思いました。以下、ヒットストップについての考え余談。

ヒットストップとはなんぞ

せっかくのアクションゲームだしヒットストップとか入れてみるか(開発延長)
剣とか格闘のゲームでは欠かせない演出だけど、銃とかシューティングではあんまり見ない気がする?サムスのチャージショットくらいしか例が浮かばない

射撃攻撃とヒットストップについて
仮説1:ヒットストップとは「吹っ飛ばし」の再現である
なので、ライフルとかサブマシンガン、レーザーみたいな貫通の攻撃とはあまり相性が良くない
逆に射撃であっても、ミサイルとか波動拳とかかめはめ波みたいな、衝撃の攻撃とは相性が良い

仮説2:ヒットストップとは「抵抗」の再現である
サンドバックを蹴れば、かならずサンドバックからの跳ね返りが存在し、無抵抗で振り抜くことはできない
その抵抗の感覚を再現するのがヒットストップであるため、自分の体から離れてしまった攻撃からは抵抗を受けないため、射撃とは相性が良くない

ここまで書いてて思ったけど、要するに現実世界に存在する「作用反作用」のフィードバックをいかにしてプレイヤーに与えるか、という問いに対する1つの答えってことかな
逆に言えば、ヒットストップを設けることで、射撃攻撃であっても「吹っ飛ばし」や「抵抗」のような作用反作用のフィードバックをプレイヤーに与えられる、ということだろうか

あとカメラシェイクか
こっちは実装したことあるからすぐいけるはず
ひとくちにヒットストップといってもさまざまなパターンがある模様
それらの挙動を比較してくれているこの動画がかなり参考になる。まずはこれを見て方向性を決めよう

やっぱり格闘と射撃とでは、適切なヒットストップの種類異なってくる気がするなぁ
射撃は自分に反作用のフィードバックがないわけで、自分が止まるタイプのヒットストップはおかしいよなあ
撃つ瞬間に自分だけ硬直⇒当たった時に相手だけ硬直して吹っ飛ぶ なら自然かな?

サムス:撃った瞬間反動でちょっと後ろに下がってる。ヒットストップというよりその反動で重量感を出しているもよう
ベヨネッタ:当たった瞬間その場で硬直してから吹っ飛んでる。硬直中は完全に動きが止まるわけじゃなくて、やられモーションのままぶるぶるしてる?それともエフェクトでそうみえるだけ?

こっちで見ると、食らったほうはその場で上下に細かく揺れたり震えたりしてるのがわかる
撃ったほうはストップしてるというか反動で後ろに下がるor硬直してるだけだな

ていうか格闘でも、攻撃したほうにはヒットストップ入れてないな
不利になっちゃうから当たり前か

ヌルっと止まると気持ちよくない、パキッとその場で止まって欲しいのでWaitForSecondsをつかうか。

WaitForSecondsの間に、別の変数やオブジェクトを格納してしまいNullReferenceエラー
LineRendererの終点
 WaitForSeconds後にLineの終点を更新していたため、更新される前にLineが描画されていた

ノックバックの時に操作するNavmeshAgent
 WaitForSeconds中に壁など敵以外のオブジェクトを打つと、shootHitの対象がエネミーからそのオブジェクトになってしまい、NavMeshAgentを見つけられるNullエラー

実装したけど削除しました!!!

一度実装してみたけど、思ったよりも爽快感に寄与せずゲームプレイがダラけただけだったので削除しました!
攻撃が当たった瞬間=ノックバック処理の実行直前に、NavMeshのVelocityを0にするStopMotionメソッドを事項してます。

がんばって作ったけど削除しました!!!
あと、これを実装するときにPlayerShootingクラスが超でぶになって見づらかったので、リファクタリングを一緒にしてます。これについては次回まとめます。

次回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.17.5「リファクタリング」

前回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.16「調整:攻撃中の移動速度を遅くする」

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.16「調整:攻撃中の移動速度を遅くする」

16.調整:攻撃中の移動速度を遅くする

前回までで、主だった昨日の実装は一段落つきました。ここからは実際に遊んでみてのフィードバックをもとに、細かい部分の実装をしていきます。
気になったのは、逃げながら攻撃していればほぼ追いつめられることが無い点でした。敵の移動速度>プレイヤーの速度となるよう調整するのが一案ですが、例えばシールド象の移動速度を速くすると少々オーバーパワーのようです。そこで、「攻撃中だけプレイヤーの移動速度が遅くなる」ようにします。

PlayerMovementクラスにメソッドを追加

移動速度を遅くするメソッドと、遅くなった移動速度を回復させるメソッドを追記します。

このメソッドの実行は、PlayerShootingクラスから行います。

PlayerShootingクラスから実行

まずは遅くする処理。Shootingメソッドの中で実行します。
また、PlayerMovementの取得は、PublicでInspectorより行います。

次に移動速度を回復させる処理。こちらはUpdateメソッドから。

実装確認

撃ったら移動速度が遅くなる⇒チョットしたら戻る の挙動ができていればOK!

第17回がお蔵入りしたので次回はコチラ

※第17回ではノックバックの実装を行いましたが、イマイチだったので削除してます。それでも読みたい物好きはコチラ

前回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.15「特殊な敵を実装する」

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.15「特殊な敵を実装する」

15.特殊な敵を実装する

前回の記事で書いたように、今回のゲームでは敵と武器とは対になります。

(断続的に登場するオーソドックスな敵)

これはすでに実装しているZonbunnyちゃんで良いでしょう。

(一斉に大量登場するが、HPが低い敵)

Zonbearちゃんのパラメータを調整すれば実現できそうです。

(盾orバリアを持っておりかつ、ダメージを食らわないでいると盾の耐久が回復する敵)

実装が必要ですね。今回はHellephantちゃんをこのシールド持ちにしましょう。

そうしてできた完成図がコチラ。

実装の段取りはこのようになります。

  • Unity上でShieldとなるObjectを用意する
  • Shieldに射撃RayがぶつかったらShieldのHPを減らす
  • ShieldのHPがゼロになったらShieldを破壊する
  • Shieldがダメージを受けずに一定時間経過したら、ShieldのHPを回復させる
  • スナイパーライフルで射撃した時はShieldと本体の両方にダメージを与える
  • Shieldにダメージが入った時、シールドの色を変えたり、大きさを小さくしたり、ヒットのエフェクトを表示する

Unity上でShieldとなるObjectを用意する

Hellephantの子Objectとして、3D Object -> cubeを作成し、ShpereColliderをアタッチします。シールドに衝突判定は設けないため、isTriggerにチェックを入れておきます。また、LayerをShootableにしておくことをお忘れなく。後の工程でこれに気づかず、2時間くらいハマりました。

Shieldの色を半透明にしたいため、専用のMaterialを用意します。Projectビューで右クリック -> Materialを作成し、Albedoから半透明の赤に調整し、ShieldObjectのMeshRendererにあるMaterialに設定します。

設定はこんな感じ。

ShieldHealthManagerの実装

Shieldの管理を行うクラスとしてShieldHealthManagerを用意します。もちろんShieldObjectにアタッチ。
ついでに、ヒット時に大きさを変えたり、エフェクトを表示する処理も一緒に書いてしまいます。色を変える処理はUpdateメソッドもいじる必要があるので事項で説明します。

Shieldにダメージを与える & その際に大きさを変えたりエフェクトを表示する

まずは基本の部分として、TakeShieldDamage()メソッドを実装します。

EnemyHealthクラスのTakeDamage()メソッドをひな型に、変数の名前を書いたりShieldだけの処理を入れたりしてます。
次に、このメソッドの実行元として、PlayerShootingクラスのShoot()メソッドを修正します。

EnemyHealthの判定を行う前にEnemyShieldの判定を差し込んでいます。
isTriggerにチェックを入れたColliderでもRayが衝突判定を返してくれるようにUnity側の設定を変更します。
Edit>ProjectSetting>PhysicsよりQuerriesHitTriggersにチェックを入れればOKです。

Shieldを回復させる & ヒット時にシールドの色を変える

一定時間Shieldへのダメージがなかったら、ShieldのHPを回復させます。これにより、スナイパーライフル以外の武器で倒すには集中砲火が必要となり、ほかの敵と合わせて出現した時のいやらしさが倍増します。

回復の処理は非常にシンプルですね。HPの値と一緒にShieldの大きさも戻してあげます。
シールドの大きさの変化率は数値を直で入れてしまってますが、本当はShieldのHPと、Colliderの大きさとの関係から計算式にすべきです。が、ややこしくなりそうなので今の段階では先送ってます。

また、ヒット時、Shieldの色にアルファ値を足してあげることで透明度を変更しています。
その直後からだんだんと色味を戻すため、Lerp関数を使っています。これはぜひ引き出しとして持っておきたい手法。

これにてShieldの実装は完了~~!!動かしてみて、攻撃を当てるたびに色が変わって小さくなること、HPがゼロになったら消滅すること、スナイパーライフルでは中身ごと攻撃できることを確認したらおしまいです。

次回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.15「特殊な敵を実装する」

前回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.14「武器変更を実装する」

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.14「武器変更を実装する」

14.武器変更を実装する

武器の変更システムに思ったよりも時間を食いましたですよ。強化のシステムはいったん延期して、最後に優先度を再検討しませふ。

クラスの構成について

武器変更はPlayerShootingクラスに実装していきます。本当は別クラスに武器の特性等を実装していくべきと思うのですが、やってみたらどの変数をどこに置いてどこから呼び出して……の切り分けに混乱しまったく実装が進まなかったので諦めました。問題意識としては持っているが能力が追い付かない、ってかんじでふ。かなC。

どんな武器を実装するか

今回は「どんな敵を実装するか」から考え、その敵への対抗手段として武器種を用意する、というアプローチをとります。例えば、「バリアを張っており一撃では倒せない敵」に対して、「バリアを貫通し一撃で倒すことのできる武器」を用意するといった具合に。
また、各武器にはデメリットを必ず用意します。ほかの武器の長所を裏返したデメリットを付与することで使えない武器(死に武器)が存在しにくくなります。
先の貫通武器であれば「ただし連射が効かない」といったように。

今回は以下の三つの武器(敵)を用意することにしました。
* サブマシンガン:連射が効き、攻撃力も並み(断続的に登場するオーソドックスな敵)
* ショットガン:広範囲の敵を一度に攻撃できるが、弾一発の攻撃力が低い(一斉に大量登場するが、HPが低い敵)
* スナイパーライフル:貫通し、攻撃力も高いが連射が効かない(盾orバリアを持っておりかつ、ダメージを食らわないでいると盾の耐久が回復する敵)

概要

武器切り替え機能の追加
武器ごとのステータスを設定:ShootメソッドとReloadメソッド

武器切り替え機能

三種類の武器を、キー1,2,3を押すことで切り替えられるようにします。また、切り替えには既定の時間がかかり即時の切り替えはできなくします。

  • enumで宣言した値を、playerWeapon変数に現在の装備として代入
  • Shootメソッド、Reloadメソッドを調整して、ダメージ値やリロード弾数の部分は引数を受けるように修正:引数の詳細は後ほど解説
  • playerWeapon変数を見て、Shootメソッドに渡す変数を切り替える

ChangeWeaponメソッドの追加

Invokeでは引数を渡すことができないのでcoroutineを使うことにしました。
HUDのアイコンを変えたり、残弾数表示の区切りを変えたり、発射レートの値を変えたりしています。

Shootメソッドの改修

めっちゃ長いですが、ショットガンの場合(isDiffuse == true)とスナイパーライフルの場合(isPierce == true)の場合分けを行い、それぞれ処理を追加してます。

拡散能力を付与する

Rayを配列化して、ランダムな前方に複数射出するようにしています。この時、射線の数だけLineRendererを付与したオブジェクトが必要となるため、gunLine変数も同様に配列として宣言し、GunBarrelEndオブジェクトにぶら下げた射線用のオブジェクトからLineRendererを取得しています。

貫通能力を付与する

Physics.Raycastはぶつかった最初のオブジェクトの情報しか取得しないため、スナイパーライフル装備時はPhysics.RaycastAllを使って、Rayがぶつかったすべてのオブジェクトの情報を取得しています。

この時、Enemy以外にもぶつかっているので、EnemyHealthを取得できずTakeDamageを実行しようとしてもNullエラーが出ることがありました。めんどくさがらずEnemyHealthがNullだった場合の分岐を設けなければいけませんでした。

Reloadメソッドの改修

Changeメソッドと同様の理由でcoroutineを使うことにしました。

クラス設計について

冒頭にも書きましたが勉強不足を実感してます。あまりにもメンテ性が悪すぎる……。この記事を書くためにコードを読み返すのが苦痛すぎました。雰囲気でここまでやってきましたが、体系的な勉強を始める必要がありそうです。

次回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.15「特殊な敵を実装する」

前回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.13「敵に射撃がヒットした時、ノックバックする」

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.13「敵に射撃がヒットした時、ノックバックする」

13.敵に射撃がヒットした時、ノックバックする

今回の実装は大きく2つ。本当は1つでもよいのだが、よりコンセプトをとがらせるため追加の実装を行う。
* 銃から発射しているRayが敵にヒットした時、Rayの方向に敵を移動させる
* ノックバックの距離と角度にすこしランダム性を持たせる
* 予定調和にせず緊張感を保たせたい

Rayが敵にヒットした時、Rayの方向に敵を移動させる

ヒットした時の処理に、Rigidbody.AddForce(shootRay.direction)を追加すれば実装できると思っていたが、試してみたところAddForceが効いている感じがない。

公式リファレンスを確認してみると、NavMeshAgentを付与したキャラクターを動かしたいときには、NavMeshAgent.velocityを使えとのこと。

ではそれを踏まえてもう一度。PlayerShootingクラスをいじっているが、EnemyMovementクラスに新たなメソッドを用意してもいいかもしれない。
武器種によってノックバック距離を変えるならPlayerShootingくらす、エネミーによるならEnemyMovementクラスに書くのがよいのだろうが、両方でやりたい場合はどうしたらいいだろうか。今は分からないので棚上げにして、実装を進めよう(EnemyMovementクラスに記述して、PlayerShootingクラスから調整用の引数を渡して実行、が正解な気がする)。

挙動はこんな感じ。

ノックバックの距離と角度にランダム性を持たせる

上まで出来ていればそう難しくない。
距離はnbPowerの取る値をランダム化させれば良いし、角度もshootRay.directionのxとzの値に少しランダム値を±させてやればよい。

これで実装できたのがコチラ。値の幅は調整の余地があるけども、ランダムでノックバックするようになりました。ただ、触ってみた感触もしかしたらランダムいらないかも。思ったより違和感がある。値の調整でも違和感が拭い去れなければ削除しよう。

次回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.14「武器変更を実装する」

前回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.12「射撃にリロードを設ける」

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.12「射撃にリロードを設ける」

12.射撃にリロードを設ける

必要なことは3つ
* 射撃可能回数に制限を設ける(1マガジンで撃てる数)
* ボタンを押すと射撃可能回数が最大まで回復する
 * マガジンの数は無限。資源の管理はこのゲームの面白さに据えないので。
 * オートリロードは設けない。俺のリロードは革命(レボリューション)なので。
 * リロード中射撃できない時間を設ける。マグチェンジではとうてい味わえない緊張感と高揚を戦闘にもたらすので。

完成形はこんな感じ

弾数制限&リロードの基本を実装

PlayerShooting.csをいじるよ。具体的にはこんな感じ
* 残弾数としてint変数currentAmmo、装填数としてint変数maxAmmoを用意
* Shoot()を実行するたびにcurrentAmmoを減らす
* Shoot()の実行条件にcurrentAmmoが0でないことを追加
* Rを押したらcurrentAmmoにmaxAmmoを代入するReload()メソッドを実行

ミスった点として、Shoot()実行前の残弾数をチェックするタイミングがあります。
最初、

という風に、最初に判定してreturnで抜けてしまったところ、残弾が0になった瞬間Update内のすべてのメソッドが効かなくなりました。
ifの一塊だけ抜けて、Update内の次の関数に行ってほしかったんですが、残弾数の判定⇒0なのでUpdateメソッド自体を抜ける⇒次フレームで再度Updateメソッド実行⇒…の無限ループしちゃいました。幸いすぐ気づいて直せました。

リロードタイムを設ける

リロードボタン(Rキー)を押してn秒後にReload()メソッドを実行するようにします。

これでリロード中は射撃ができないようになりました。リロードタイムがこんなにも息吹を……!!

[追記]嘘です。この実装だとリロード中も射撃できます。あとで直す。

残弾数のUI表示

3枚のスプライトを重ね、FillAmountを使って表現します。

実際に用意した画像ファイルは4枚、一番上の外枠と、内枠の区切りを示す一本の黒い線とで2枚に分けました。バランス調整や、別の武器の実装で装填数の異なるUIを作るとき、応用が利くようにしたかったためです。等間隔になるようなPosition設定がめんどいので、1枚で書いてもそんなに手間が変わらないかも。

HUDCanvas下にImageオブジェクトを4つ追加してそれぞれ画像ファイルを設置。
Projectビュー内の画像ファイルTextureTypeをSprite(2D and UI)にするのを忘れずに。

PlayerShootingスクリプトで制御する必要があるのは真ん中の黄色いスプライトのみです。

ついでに、武器変更機能を見越して、装備中の武器がわかるようなHUDも追加しました。

リロード中の表現

グラフィックでやろうと思ったんですが、AssetStoreに無料でいい感じのオーディオ素材があったのでそちらで実装してみます。

MentalDreams, Weapon Soldier Sounds Pack

リロードタイム3秒で丁度SEの長さとあってますが、今後のバランス調整を経てズレてきた場合は、SEの長さを調整する必要が出てきそうです。

これでリロード周りの実装は終わりです。次回はノックバックを実装しますよ~
それとタイトル名決めました。
SurvivalShooter Who In The Hell Punches or Kicks? -やさしい地獄へようこそ-
略してSurvivalShooter WITH PKです。どうぞよろしく。

次回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.13「敵に射撃がヒットした時、ノックバックする」

前回はコチラ

Unity公式チュートリアルSurvival Shooter応用Chapter.11.5「コンセプトを考える」

Unity公式チュートリアルSurvival Shooter応用Chapter.11.5「コンセプトを考える」

11.5.コンセプトを考える

前回の記事を書いた後、大事な手順を忘れていたことに気づいた。
「このゲームをどんなゲームにしたいか」というコンセプトの確認だ。危うく開発が迷走するところであった。
次の実装に入る前に、コンセプトの整理と先に挙げた5つの要素がそれに沿っているか、過不足はないか確認しよう。

このゲームの醍醐味をどこに置くか

このゲームは、何を面白いと感じてもらうものなのか
何をどうしてどうするためのゲームなのか
なぜこのゲームを作りたいと思ったのか、このゲームで何を伝えたいのか

コンセプトはワンピースにおけるログポースだ。桃鉄における目的地だ。母を訪ねて三千里における母だ。
このコンセプトがなければゲーム開発は迷走する。チームでの開発ならいわずもがな、たぶん個人でも規模が大きくなれば何が正解かわからなくなってくるはずだ。その時に立ち返るためのものである。

今回のSurvivalShooterでは、コンセプトを下記の通り定義する。

襲ってくるたくさんのゾンビを、命からがら全滅させるゲーム

なんてことないコンセプトだと思うかもしれない。だが、下記のようなコンセプトを立てた場合と比べてみてほしい。イメージできるゲームの完成図はだいぶ違うのではないだろうか。

  • 武器を持たない一般人がゾンビに見つからないように、朝が来るまで生き残るゲーム
  • 圧倒的な数のゾンビを、圧倒的な火力で蹂躙するゲーム
  • ゾンビがうろつくマップを、限られた資源だけで何日生き残れるか競うゲーム

コンセプトから実装項目を考える

コンセプトによって実装すべき機能、優先度が変わる。
今回のコンセプトでは、どんなゲームデザインをすべきだろうか。

  • 襲ってくるたくさんのゾンビ
    ゾンビは自分に向かって進んでこなければならない。
    ゾンビの同時出現数も多くなるだろう。

  • 命からがら全滅させるゲーム
    ライフは貴重なものになる。
    また、そもそもダメージを食らわないようなプレイングに対してメリットを設けるべきだろう。
    全滅させるための手段を用意する必要がある。
    ゲームクリアの条件になるのはゾンビの全滅だ。

今回順序が逆になってしまったが、前回の記事で挙げた項目とコンセプトとが一致しているかを確認しよう。

  • 11.敵の出現をWaveで管理する
    ゾンビの出現数を管理することは必須である。プレイ開始直後から100体のゾンビに襲われてはかなわない。
    難易度のデザイン、ゲームクリアに欠かせない機能であるため、(Waveという形にするかはさておき)これは最優先で実装すべきだ。

  • 12.射撃にリロードを設ける
    無制限に攻撃できる場合、(敵が一方的に強くならない限り)プレイヤーは命の危機を感じないし、ゲームプレイにも工夫を凝らさない。
    攻撃のあとに必ず「逃げなければいけない」フェーズが訪れることで、プレイヤーに「(生き残るために)今攻撃すべきかどうか」の駆け引きを強いることができる。これも欠かせない機能といえるだろう。

  • 13.敵に射撃がヒットした時、ノックバックする
    敵に攻撃を当てたことへの何よりの報酬は、敵が死ぬことだ。だが、一発で死んでしまっては面白くない。とはいえ、死ぬまで何の報酬がもたらされないのもストレスだ。中間の報酬として「逃げるのが有利になる」ノックバックを与えるのは悪くない。

  • 15.敵の個性を強くする
    たくさんのゾンビを撃ち殺しているうちに、プレイヤーは飽きてくるだろう。彼らに刺激を与えるために「5発撃っても死なないゾンビ」や「遠いところから攻撃してくるゾンビ」を追加しよう。油断していたプレイヤーたちは目を醒まし、再び対策に頭をひねるだろう。

  • 14.武器変更と武器強化アイテムを出現させる
    夢中になって意地悪なゾンビを追加しているうちに、プレイヤーの持つ武器では対処しきれないモンスターを作ってしまうかもしれない。これではプレイヤーはストレスや理不尽を感じてしまうだろう。フェアなゲームとするために、彼らにも新たな武器を与えよう。嬉々としてゾンビ狩りに精を出してくれることだろう。

さあ実装しよう

前回挙げた実装項目の中には、幸いアテを外しているものはなかった。自分の中でコンセプトは割としっかり固まっていたようだ。が、実装を進める中できっと「これも入れたら面白いだろうな」と思う機能が出てくるだろう。すでにいくつか新しいアイデアは生まれている。だがすべての機能を実装することは時間の面でも根気の面でも不可能だ、取捨選択をしなければならない。その時、ここでコンセプトを明文化していたことが役に立つであろう。

次回はコチラ

Unity公式チュートリアルSurvival Shooter WITH PK Chapter.12「射撃にリロードを設ける」

前回はコチラ

Unity公式チュートリアルSurvival Shooter応用Chapter.11「敵の出現をWaveで管理する」