【GW企画】7日間でUnity製のカジュアルゲームを作る【3日目】

※2019年5月に書いたものをnoteに移植したものです。

「GW10連休を活かしUnityでカジュアルゲームを作ってリリースする企画」の3日目

3日目の計画

・企画の練り直し
・練り直した企画のシステム実装

3日目にやったこと

企画の練り直し

▼ゲームルールの変更
より高く積み上げることを目標としたスコア性のゲーム

▼操作性の変更
鍋が下がって離したときにバネのように飛ぶ挙動。
左右操作をいれないことでユーザーの選択肢を減らし、シンプルな操作性にする。

▼デザインの変更
コンロ → テーブル上の配置
ステーキ → パンケーキ

カメラワークの変更

画像1

左右操作がなくなったため左右均等のカメラワークでなくてよくなった。
パンケーキの高さと距離感の両方を見やすくするために斜めからのカメラワークに変更。

パンケーキを飛ばす挙動の実装

上記の記事内のコードを元に実装。
またTrail Rendererを使ってパンケーキが飛んでいく軌跡を表示する実装を組み込んだ。

パンケーキをクルクル回りながら飛ばす実装

飛ばすだけの実装だと味気ないので、飛ばしたタイミングでパンケーキがクルクルと回転しながら飛んでいくためのコードを実装した。

ただ上記実装だと問題が発生した。
パンケーキが飛ぶ瞬間から回転挙動が始まるため、飛ばした瞬間にフライパンに引っかかってしまうのだ。
これを避けるためにフライパンへの衝突判定が入っている場合は回転させないように条件分岐をつけた。

タップ時間と飛距離が連動するように変更

このままだとただタップするだけでゲーム性がないため、ユーザーがタップした時間の長さによってパンケーキの飛距離が変わるように実装。
実装の流れとしては、マウスを押している間だけ時間をカウントし、そのカウント数分だけ飛ばすときのエネルギーを増やす感じだ。

Unityでマウス入力を扱う - TASOGARE GAMES BLOGUnity逆引き:マウス入力を扱う カーソル座標の取得 クリック判定tasogare-games.hatenablog.jp

パンケーキが飛んだら次のパンケーキが生成される実装

皿の外にパンケーキが着地する以外のケースでは、パンケーキがとんだ後に新しいパンケーキが準備される必要がある。

現在のパンケーキの衝突判定を元に、新しいパンケーキを生成するフラグを付けていく。
ただし新しいパンケーキが生成されたタイミングで古いパンケーキのスクリプトは停止させる必要があるためスクリプトの無効化もコードに混ぜ込む。
(パンケーキ自体に飛ばすスクリプトを持たせるよりも、プレイヤーのスクリプトを分けて書いた方が賢い書き方だったかもしれません…)

ここまでの実装をまとめるとこんな感じ。

using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class Fly : MonoBehaviour
{
// 物理剛体
private Rigidbody physics = null;
// 飛ばす間だけ回転させるためのフラグ
private bool stay;
// クリックしている時間のカウント
private float GetMouseTime;
//ゲームオブジェクト探す系
GameObject Flypan = GameObject.Find("Flypan");
GameObject Plate = GameObject.Find("Plate");
GameObject Desk = GameObject.Find("Desk");
GameObject Floor = GameObject.Find("Floor");
// 初期化処理
public void Awake()
{
this.physics = this.GetComponent();
}
// 毎フレームごとの処理
public void Update()
{
//クリックを押した時の処理
if (Input.GetMouseButtonDown(0))
{
//時間の初期化
GetMouseTime = 0;
}
//クリックを押してる間の処理
if (Input.GetMouseButton(0))
{
// タイムを加算する
GetMouseTime += Time.deltaTime;
}
//クリックを離した時の処理
if (Input.GetMouseButtonUp(0))
{
Debug.Log("ボタン押してる時間" + GetMouseTime.ToString("F2"));
//ジャンプの処理(高さと距離は2:1ぐらいが調子良い?)
this.Flip(new Vector3(0f, GetMouseTime*6f, GetMouseTime*3f));
}
if (stay == false)
{
transform.Rotate(new Vector3(5, 0, 0));
}
}
// あたり判定の確認処理(空中にいるかいないかの判断)
private void OnCollisionEnter(Collision collision)
{
stay = true;
if (collision.gameObject.name == "Flypan")
{
Debug.Log("フライパンにあたってます");
}
if (collision.gameObject.name == "Plate")
{
Debug.Log("プレートにあたってます");
GameObject nextPancake = Instantiate(Resources.Load("Pancake")) as GameObject;
this.GetComponent().enabled = false;
}
if (collision.gameObject.name == "Desk")
{
Debug.Log("机にあたってます");
GameObject nextPancake = Instantiate(Resources.Load("Pancake")) as GameObject;
this.GetComponent().enabled = false;
}
if (collision.gameObject.name == "Floor")
{
Debug.Log("床にあたってます");
GameObject nextPancake = Instantiate(Resources.Load("Pancake")) as GameObject;
Destroy(this.gameObject);
}
}
private void OnCollisionExit(Collision collision)
{
stay = false;
}
// ボールをはじく
public void Flip(Vector3 force)
{
// 瞬間的に力を加えてはじく
this.physics.AddForce(force, ForceMode.Impulse);
}
}

ただしこの時点で致命的な問題も発生。
冒頭のTwitterの動画を見てもらうとわかりやすいかもしれないけど、当たり判定の管理がガバガバだったために、ある一定の挙動を行うと指数関数的にパンケーキが生成されてしまうバグがあった…。

3日目の振り返り

当初企画を3日目の時点で変更することに対して早すぎるかなとも思ったものの、後から振り返ってみるとこのタイミングで変更してよかった。
(2日目のテンションで当たり判定の調査を続けていたらとてもGW中のリリースは間に合わなかったので)
3日目はコードの調整が多かったのでパズル感覚もあり楽しくできたような。

この記事が気に入ったらサポートをしてみませんか?