2023年9月8日金曜日

エンドレスランナー「ギルガメランナー」の開発日記#2

 



おはこんばんちわ!ギルガメです!
引き続き「ギルガメランナー」の開発を進めていきます!


今回はもうちょっとエンドレスランナーの要素を追加していきたいので下記を対応してみました。
  • エンドレスランナー中にアイテムを拾ってポイントを稼ぐ(UIを表示)
  • エンドレスのゲームプレイのタイムを測る(UIを表示)
  • タイムによってスピードを加速して難易度を上げていく

対応したコードは下記になります。(ほとんどが追加になります)

using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
public class GameManager : MonoBehaviour
{
public bool isGameOver = false;
public TextMeshProUGUI scoreText;
public TextMeshProUGUI timerText;
public Stage[] stages;
private bool isRunning = false;
private int score = 0;
private float startTime = 0f;
private PlayerController playerController;
private ObstacleSpawner obstacleSpawner;
private int currentStage = 0;
void Start()
{
startTime = Time.time;
isRunning = true;
playerController = GameObject.Find("Player").GetComponent<PlayerController>();
obstacleSpawner = GameObject.Find("ObstacleManager").GetComponent<ObstacleSpawner>();
}
void Update()
{
if (isGameOver)
{
RestartGame();
}
if (isRunning)
{
float elapsedTime = Time.time - startTime;
int seconds = (int)elapsedTime;
timerText.text = seconds.ToString();
if (stages.Length > currentStage && seconds > stages[currentStage].nextStage)
{
playerController.speed = stages[currentStage].PlayerSpeed;
obstacleSpawner.spawnRate = stages[currentStage].ObstacleSpeed;
currentStage++;
}
}
}
public void GameOver()
{
isGameOver = true;
}
void RestartGame()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
// ポイントを取得したらスコアを加算
public void UpdateScore(int point = 1)
{
score = score + point;
scoreText.text = score.ToString();
}
}
view raw GameManager.cs hosted with ❤ by GitHub
using UnityEngine;
public class ObstacleSpawner : MonoBehaviour
{
public GameObject obstaclePrefab;
public GameObject pointPrefab;
public float spawnRate = 2.0f;
private float spawnInterval;
void Start()
{
Invoke("SpawnObstacle", 2.0f);
}
void SpawnObstacle()
{
spawnInterval = Random.Range(0.5f, spawnRate);
if (Random.Range(0, 2) == 0) {
Instantiate(obstaclePrefab, new Vector3(Random.Range(-1, 2) * 2, Random.Range(0, 2) + 0.6f, transform.position.z), Quaternion.identity);
} else {
Instantiate(pointPrefab, new Vector3(Random.Range(-1, 2) * 2, Random.Range(0, 2) + 0.6f, transform.position.z), Quaternion.identity);
}
Invoke("SpawnObstacle", spawnInterval);
}
}
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float speed = 10.0f;
public float jumpForce = 5.0f;
private Rigidbody rb;
private int lane = 1; // 0: 左, 1: 中央, 2: 右
private Vector3[] lanePositions = { new Vector3(-2, 1, 0), new Vector3(0, 1, 0), new Vector3(2, 1, 0) };
private Vector3 targetPosition; // プレイヤーが移動する目的地
private bool isGrounded = true; // プレイヤーが地面にいるかどうか
void Start()
{
rb = GetComponent<Rigidbody>();
targetPosition = transform.position; // 初期位置を設定
}
void Update()
{
// レーン切り替え
if ((Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A)) && lane > 0)
{
lane--;
SwitchLane();
}
else if ((Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D)) && lane < 2)
{
lane++;
SwitchLane();
}
// ジャンプ(地面にいる場合のみ)
if (Input.GetButtonDown("Jump") && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isGrounded = false; // ジャンプ後は地面から離れる
}
// スムーズなレーン切り替え(X座標のみ)
Vector3 newPosition = transform.position;
newPosition.x = Mathf.Lerp(newPosition.x, targetPosition.x, speed * Time.deltaTime);
transform.position = newPosition;
// 前進(Z座標)
transform.Translate(Vector3.forward * speed * Time.deltaTime, Space.World);
}
void SwitchLane()
{
targetPosition = lanePositions[lane];
targetPosition.z = transform.position.z; // Z座標は変更しない
}
private void OnTriggerEnter(Collider other)
{
// ゲームオーバー
if (other.gameObject.tag == "Obstacle")
{
FindObjectOfType<GameManager>().GameOver();
}
// スコア加算
else if (other.gameObject.tag == "Point")
{
FindObjectOfType<GameManager>().UpdateScore();
Destroy(other.gameObject);
}
}
void OnCollisionEnter(Collision collision)
{
// 地面に触れたらisGroundedをtrueにする
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
}
using System;
[Serializable]
public class Stage
{
public int nextStage = 0;
public int PlayerSpeed = 0;
public float ObstacleSpeed = 0;
}
view raw Stage.cs hosted with ❤ by GitHub

対応したことを細かく説明していきます。

  • ポイントを稼ぐ機能は障害物を生成するスクリプトと同じ機能で生成していきます。ポイント用のプレハブを作成してタグをPointに設定します。プレイヤーが接触した時にタグを確認してポイントのオブジェクトを破壊してスコアを更新します。

  • エンドレスのゲームプレイのタイムを測る、こちらはシンプルにTime.timeを使って秒数をIntに変換して更新していきます。

  • UIの表示はTextMesh Proを使っていきます。こちらの方がはっきり表示されるので万能です。デフォルトでは日本語の表示がないのでGoogle Fontsから好きなフォントをダウンロードしてTextMesh Proで対応できるようにFontを生成します。ドットのフォントが好きなのでそちらで進めていきます。

  • タイムによってスピードを加速して難易度を上げていく、こちらはStageというクラスを作成してSerializableを追加して画面上で時間の経過で難易度を設定しやすくします。

NextStage:タイムがその値を超えると反映される
PlayerSpeed:プレイヤーのスピードを加速
ObstacleSpeed:障害物の生成のDelayの短縮

上記を追加してみました。下記でV0.2でデプロイしているのでぜひ触ってみてください




次はデザインでも変えていこうかな。

最後まで読んでいただきありがとうございます!
これからもギルガメを応援していただけるよ嬉しいです!

0 件のコメント:

コメントを投稿