Unity一週間ゲームジャム「つながる」に参加しました。
前回の「10」はいろいろ忙しくてスキップ、前々回とその前は参加したものの、技術検証的なことに時間を使ってしまい、ゲームとしては微妙なものでした。
今回は自分にとって新しい技術はあまり使わず、ゲーム性を高めることを目標に作りました。
とは言っても、プロジェクトを新規作成したのが木曜日の夜で、金曜日に原型を作成、土曜日にほぼ完成させ、日曜日は調整、という感じで、相変わらずの短期決戦でした。
作成したゲームは下記になります。
また、今回はGitHubに既にコードをアップしています。
ゲームの基本的なアイデアは、コナミの名作パズルシューティング「クオース」を元にしています。
クオースの場合、四角を作るのですが、今回はテーマに合わせてブロックをつなげて一列にすると消える、としました。
技術的に新しく追加したのは下記のみです。
以前はGoogle Spreadsheetを使う方式だったのですが、ニフクラを使う方式になったそうです。
ニフティクラウドの時のアカウントは使えなくなっていたので新規登録しました。
日本語フォントを入れるのにコンバートが必要なようで、今回は行っていません。デフォルトの英語のフォントでいいデザインのものが合ったのでそちらを使用しました。uGUIのTextよりクリアで文字列の配置もやりやすいので今後も使っていきたいです。
以下、ゲームを作る上で悩んだ点と解決方法です。
自機の移動を1ユニット単位でしかさせなくするものです。スナップ移動自体はpositionに±1すればできますが、そのままだとワープ的な移動になってしまうので、アニメーションをつけて移動させます。こういう場合は定番アセットDOTween(無料版)がとても便利です。
ただ、Tweenで移動中にさらに移動のキー入力を受け付けてしまうと挙動がおかしくなるので、変数canMoveを用意して、移動中はfalseにし、Tweenのコールバックイベントでtrueに戻す、としました。
canMove = false; transform.DOMoveY(posY, 0.1f).OnComplete(() => { canMove = true; });
弾もY座標はスナップする必要があるのですが、自機がTweenで移動中に弾を発射すると、半端な位置に生成されてしまいます。
弾のY座標をスナップするために下記の関数を使用しました。
float Snap(float value) { return Mathf.Floor(value / 1.0f) * 1.0f; }
スナップの基準値で割ったものの整数部分にスナップの基準値を掛ける、というものです。
弾ブロックを、既に存在するブロックに当てると跳ね返って弾ブロックが消えます。これもDOTweenを使いました。
gameObject.transform.DOMove(new Vector3(pos.x - 1f, pos.y - 2f), 0.2f).SetEase(Ease.OutQuad).OnComplete(() => { Destroy(gameObject); });
跳ね返りの動きが終わった後にコールバックでDestroyしています。
ブロックの隙間に弾ブロックを当てると、そこに弾ブロックが留まります。
これは、弾ブロックがそのまま残るのではなく、隙間を示すオブジェクトのスプライトを書き換えています。
public void ChangeFace() { gameObject.GetComponent<SpriteRenderer>().sprite = PlacedSprite; gameObject.tag = "Block"; var parent = gameObject.transform.parent.gameObject; parent.GetComponent<BlockParent>().LuckCount--; }
タグを変更しているのは、弾ブロックに対しての当たり判定をつけるためです。
また、縦一列を管理している親オブジェクトが保持している、一列揃うために足りないブロックの数を減少させています。
外壁と背景はスクロールさせていますが、その都度InstantiateとDestroyをすると負荷がかかるので、画面左から出てしまったオブエクトを右端に移動する、という方法を使っています。
void FixedUpdate() { speed = GameManager.Instance.EnemyBlockSpeed; pos = new Vector3(pos.x - speed * Time.deltaTime, pos.y, pos.z); transform.position = pos; if (pos.x < limitX) { Vector3 newPos = new Vector3(GameManager.Instance.RightLimitPos, transform.position.y, transform.position.z); transform.position = newPos; pos = newPos; } }
ただ、動くことは動くのですが、時々ブロックの間が空いてしまったりして見栄えが悪くなっています。UpdateをFixedUpdateにしたのですが同じ状況で、まだ解決策は見つかっていません。
その他、ブロックの隙間の数を多くしないように抑えたり、細かい難易度調整は行いましたが、ブロックを消した数に応じてリニアにスピードが速くなっていく、という単純なものなので、難易度上昇のカーブを付けられるようにするなどは今後の課題です。