前回までで普通にゲームとして成り立つようになりましたが、そのままではちょっと寂しいので得点アイテムであるコインを追加してみましょう。
コインの作成
さて、これまでプレイヤーキャラや床・壁は2Dのスプライトを使って作ってきましたが、今回はちょっと趣向を変えて3Dオブジェクトでコインを作ってみます。まず、シーンのヒエラルキーを右クリックして「Create」→「3D Object」→「Capsule」を選択してください。すると白いカプセル状のオブジェクトが作られます。これがコインの元になるオブジェクトです。
ただし、そのままでは3Dゲーム用の当たり判定がついているので、それを削除して2Dゲーム用の当たり判定をつけます。インスペクタに表示されている「Mesh Collider」を右クリックして「Remove Component」を選んで削除してください。そうしたら、いつも通り「Box Collider 2D」と「Rigidbody2D」をアタッチし、さらにタグとレイヤーを「Item」にしてください。これで当たり判定の設定はOKです。
次にコインの色を変更します。3Dオブジェクトの色や質感を変更するときはマテリアルというものを使います。「Materials」フォルダを右クリックして、「Create」→「Material」を選択しましょう。新しくつくられたマテリアルファイルの名前を「CoinMaterial」に変更したら、次のように設定を変更します。
- 「Albedo」で黄色を選択
- 「Metalic」と「Smoothness」を0にし、「Source」を「Albedo Alpha」に変更
- 「Emission」にチェックを入れ、同じ黄色を選択
- 「Specular Higjlights」と「Reflections」のチェックを外す
これで立体感が飛んだ2次元的なマテリアルができました。あとはこれを「Mesh Renderer」コンポーネントのMaterialsにアタッチしてください。
コインのプログラム
次にコインのプログラムを作ります。新しいC#スクリプトを作り、名前を「Coin」に変更し、Coinオブジェクトにアタッチしてください。そしてスクリプトを開いて次のソースコードを記入してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Coin : MonoBehaviour {
[SerializeField]
float speed = -10.0f;
Rigidbody2D rigidBody2D;
bool inCamera = false;
//初期化
void Start()
{
rigidBody2D = GetComponent<Rigidbody2D>();
}
//物理演算
void FixedUpdate()
{
rigidBody2D.velocity = new Vector2(speed, rigidBody2D.velocity.y); ;
}
//カメラ内外の判定処理
void OnBecameVisible()
{
inCamera = true;
}
void OnBecameInvisible()
{
if (inCamera)
{
Destroy(gameObject, 1.0f);
}
}
}
最後に、コインをプレハブ化してください。これでコインができました。
コイン生成オブジェクトの作成
さて、そうしたら次にコイン生成オブジェクトを作ります。…と言いたいところですが、ここでちょっと考えてみましょう。コインの生成は一定間隔で行いたいのですが、これは壁の生成とよく似ています。そこで壁の生成と一緒にコインも生成してしまうのはどうでしょうか?この方法なら新たにコイン生成オブジェクトを作ったり、そのプログラムを新しく作る必要がなくなります。
コイン生成オブジェクトのプログラム
そこで壁の生成プログラムを改造します。プログラムを下記のように書き換えてください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Emitter : MonoBehaviour {
[SerializeField]
float emitWaitTimeMin = 0.6f;
[SerializeField]
float emitWaitTimeMax = 1.0f;
[SerializeField]
float intervalCofficient = 0.98f; //レベルアップしたとき、生成間隔を何倍するかの係数
[SerializeField]
float wallSpawnX = 13.0f;
[SerializeField]
float wallSpawnY = -2.5f;
[SerializeField]
float coinSpawnX = 11.0f;
[SerializeField]
float coinSpawnY = 5.0f;
[SerializeField]
GameObject wall;
[SerializeField]
GameObject coin;
[SerializeField]
GameManager gameManager;
bool emitterEnabled = true;
int cullentLevel;
float emitWaitTimeMinNow;
float emitWaitTimeMaxNow;
//毎フレームの処理
void Update ()
{
//タイトルまたはゲームオーバー画面
if (!gameManager.playing)
{
//初期化
cullentLevel = gameManager.level;
emitWaitTimeMinNow = emitWaitTimeMin;
emitWaitTimeMaxNow = emitWaitTimeMax;
}
//プレイ中の処理
if (emitterEnabled && gameManager.playing)
{
//生成処理
Instantiate(wall, new Vector3(wallSpawnX, wallSpawnY, transform.position.z), Quaternion.identity);
Instantiate(coin, new Vector3(coinSpawnX, coinSpawnY, transform.position.z), Quaternion.identity);
StartCoroutine(EmitWait());
//レベルアップ時に生成速度Up
if (gameManager.level != cullentLevel)
{
emitWaitTimeMinNow *= intervalCofficient;
emitWaitTimeMaxNow *= intervalCofficient;
cullentLevel = gameManager.level;
}
}
}
//生成を待つ処理
IEnumerator EmitWait()
{
emitterEnabled = false;
float emitWaitTime = Random.Range(emitWaitTimeMinNow, emitWaitTimeMaxNow);
yield return new WaitForSeconds(emitWaitTime);
emitterEnabled = true;
}
}
できたらEmitterコンポーネントにCoinのプレハブを登録するなど必要な設定を行ってください。
問題点
ここでテストプレイしてもらうと、コインがプレイヤーに当たっても消えないという問題があることがわかります。まだコインを消す処理を追加していないからです。そこで、次のページではその辺も含めてプレイヤーの処理を追加し、ゲームオーバーなどの処理も行うように改造します。
次のページ→プレイヤースクリプトの改造

