はじめに
みなさん,こんにちはbearlです.
今回は昨年話題になったスイカゲームをUnityを使って爆速,1時間以内で作ってみました.かなり簡単なものを作ったので,これを応用して自分だけのすばらしいスイカゲームを作ってみてください!コメントくれたら,相談に乗りますし,作ってみたスイカゲームを是非ぼくに遊ばせてください^^
初心者の方から作成できるようにしているので,下の目次を見て大丈夫なところは飛ばしていってくださいね〜
GitHubのリンクを置いておきます.
目次
- プロジェクトの作成
- フィールドの作成
- フルーツの作成
- フルーツを落とすPlayerの作成
- フルーツたちの当たった時の処理(合体処理)
- フルーツを積み立てすぎないようにする
- スコア表示
- ゲームオーバーの設定
Ex1. フルーツに写真をつけてみよう!
Ex2. BGM,サウンドをつける!!
実行環境
Unity 2022.3.24f1
1. プロジェクトの作成
2. フィールドの作成
では,まずゲーム画面を映すカメラを設定します.
MainCameraを以下のように設定してください.
Projectionを変更し忘れていませんか?
Sizeは10になっていますか?
フルーツたちが入るカゴの作成
Hierarchyタブを右クリックして「2D Object」→ 「Sprites」 → 「squeare」で四角形を作ります.
当たり判定の作成
Inspectorタブの一番下にある「Add Component」を押し,「BoxCollider2D」を追加します.
検索で「Box」と打つと出てくると思います.
大きさと場所の設定
InspectorタブのTrasformの値をいじると変更できます.
下を参考にして,床,右の壁,左の壁を作っていきましょう.
床 | |
---|---|
右壁 | |
左壁 |
3. フルーツの作成
さくらんぼを例として作ります.
オブジェクトの作成
Hierarchyタブを右クリックし,「2D Object」→ 「Sprites」 → 「Circle」でまるを作っていきましょう.
Add ComponentでCircle Collider 2Dを追加します.名前はCherryにします.
tagの作成
InspectorタブのTagを押し,AddTab→Tagsの+でcherryというTagを作ります.
そして,作ったTagをつけてあげましょう.
物理法則の追加
Add ComponetでRigidbody2Dを追加します.これで物理法則は追加されますが,このままだとかなり跳ねてしまいます.
そこで.反発係数を設定しましょう.
Projectタブを右クリックして「Create」→「Physical Material」を追加します.
バージョンが違う場合は下の時もあります.
「Create」→「2D」→「Physical Material 2D」
Physical MaterialにはFrictionとBouncinessがあります.
Friction | 摩擦力 |
---|---|
Bouncines | 反発係数 |
これをフルーツのCircleCollider2DのMaterialで選択するとOKです!
Hierarchyタブにある作ったフルーツをProjectタブにドラッグ&ドロップしてPrefab化しましょう.
そしたら,Sceneから全て消してもらって大丈夫です!
「Prefab」:ゲームオブジェクトやコンポーネントの再利用可能なテンプレート
他のフルーツでも同じようにして作りましょう.
わたしは
- Cherry:大きさ1
- Kaki:大きさ2
- Orange:大きさ3
- Peach:大きさ4
- Suika:大きさ5
の5つを作りました.
4. フルーツを落とすPlayerの作成
Playerオブジェクトの作成
Hierarchyタブを右クリックし,「2D Object」→ 「Sprites」→「Isometric Diamond」とします.
Transformな適当な場所にします(下図参考).
Player.csの作成
Projectを右クリックして「Create」→「C#Script」でPlayer.csを作成します.処理としては,Input.GetKey()
で特定キーを打ち込まれた時にTrue
を返す.spaceDelay
でスペースキーを連打できないように次に押すまでの時間を設定しました.これは定数なのでconst
をつけます.Instantiate()
で
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float maxX;
public float speed;
public GameObject[] FruitsList;
private float spaceDelay = 0.5f;
void Update()
{
spaceDelay -= Time.deltaTime;
//movement
if(transform.position.x < maxX)
{
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
transform.position += new Vector3(1, 0, 0) * Time.deltaTime * speed;
}
}
if(transform.position.x > -maxX)
{
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
transform.position += new Vector3(-1, 0, 0) * Time.deltaTime * speed;
}
}
//space key
if (spaceDelay < 0 && Input.GetKeyDown(KeyCode.Space))
{
spaceDelay = 1.0f;
transform.position += new Vector3(1, 0, 0) * Time.deltaTime * speed;
Instantiate(FruitsList[Random.Range(0, FruitsList.Length)], transform.position, transform.rotation);
}
}
}
以下の写真は,MaxXは横移動の制限するもので,Speedが横移動の速さ,FruitsListでPlayerから生成されるフルーツを決めている.
5. フルーツたちの当たった時の処理(合体処理)
さくらんぼを例にします.
Projectを右クリックして「Create」→「C#Script」でFruitsCollision.csを作る.同じフルーツ同士が当たった時に進化先のフルーツが1つできるようにします.処理としては,Tagで同じフルーツかを管理し,gameobjectにはそれぞれにIDがあり,それが少ない方の場所にかきができてるようにしました.
以下のコードを参考にしてください.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FruitsCollision : MonoBehaviour{
public GameObject NextFruit;
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == gameObject.tag)
{
// 自分のインスタンスIDと衝突相手のインスタンスIDを比較
if (gameObject.GetInstanceID() < collision.gameObject.GetInstanceID())
{
//すいかの場合はNextFruitがnullなので生成しない
if (NextFruit != null)
{
//NextFruitを生成
Instantiate(NextFruit, transform.position, transform.rotation);
}
Destroy(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
}
これをCheeryのPrefabにAddComponentして,GameObject NextFruitsをKakiのPrefabを選択する.scoreAddNumに任意の値を入れてください.
この一連のことを他のフルーツでもしてください.
GameObject NextFruitsはCherryの進化先のフルーツがかきだからです.
フルーツにあった進化先のフルーツを設定しましょう!
6. フルーツを積み立てすぎないようにする
Playerの位置を少しだけずらすことで,連続で積まれることを防いぎました.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float maxX;
public float speed;
public GameObject[] FruitsList;
private float spaceDelay = 0.5f;
//// 追加コード
public float plus = 0.2f;
///
void Update()
{
spaceDelay -= Time.deltaTime;
//movement
if(transform.position.x < maxX)
{
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
transform.position += new Vector3(1, 0, 0) * Time.deltaTime * speed;
}
}
if(transform.position.x > -maxX)
{
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
transform.position += new Vector3(-1, 0, 0) * Time.deltaTime * speed;
}
}
//space key
if (spaceDelay < 0 && Input.GetKeyDown(KeyCode.Space))
{
spaceDelay = 1.0f;
/* 入れ替えコード */
transform.position += new Vector3(plus, 0, 0) * Time.deltaTime * speed;
plus *= -1;
///
Instantiate(FruitsList[Random.Range(0, FruitsList.Length)], transform.position, transform.rotation);
}
}
}
7. スコア表示
Textの作成
Hierarchyを右クリックして「UI」→「Text-TextMeshPro」を作成する.
すると,HierarchyにCanvasその下にText (TMP)が作成される.
Text (TMP)をscoreとしておく.
scoreの作成
Projectを右クリックして「Create」→「C#Script」でScoreDisplay.csを作る.
Hierarchyを右クリックして「Create Empty」してGameManagerという空のObjectを作る.
Add ComponetでScoreDisplay.csを追加する.それのscoreTextに先ほど作成したTextMeshProのscoreを選択する.
GameManagerは空のオブジェクトとして,オブジェクトとしては必要ないけどスクリプトだけが動いて欲しい時に使います.
ScoreDisplay.csのコードをいかに記述する.
using TMPro;
using UnityEngine;
public class ScoreDisplay : MonoBehaviour
{
public TextMeshProUGUI scoreText;
static public int score = 0;
void Update()
{
if (scoreText != null)
{
scoreText.text = "score: " + score;
}
}
}
当たったときに点数を増やす
さくらんぼを例にします.
さくらんぼ同士がぶつかった時に10点増やすようにします.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FruitsCollision : MonoBehaviour{
public GameObject NextFruit;
public int socreAddNum;//スコアの加算値
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == gameObject.tag)
{
// 自分のインスタンスIDと衝突相手のインスタンスIDを比較
if (gameObject.GetInstanceID() < collision.gameObject.GetInstanceID())
{
//すいかの場合はNextFruitがnullなので生成しない
if (NextFruit != null)
{
//NextFruitを生成
Instantiate(NextFruit, transform.position, transform.rotation);
}
Destroy(gameObject);
ScoreDisplay.score += socreAddNum;
}
else
{
Destroy(gameObject);
}
}
}
}
8. ゲームオーバーの設定
GameManagerを作る
Projectを右クリックして「Create」→「C#Script」でGameManager.csを作る.
GameManagerオブジェクトにAdd Componetする.加えて,GameManagerにAdd ComponentでBox Collider 2D をつける.なにをするかというと,GameOverとなるかごのふたを作っているのです.
そして,IsTrigerをチェックしておきましょう.
Transformは以下を参考にしてください.
GameManager.csのコードは以下のようにします.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
static public bool gameOver = false;
private bool gameOverTime = false;
private float time = 0.0f;
public GameObject gameOverGUI;
public GameObject player;
void Update()
{
if (Input.GetKey(KeyCode.Escape))
{
Application.Quit();
}
if(gameOverTime)
{
time += Time.deltaTime;
}
if(time > 2.0f)
{
gameOver = true;
}
if(gameOver)
{
player.SetActive(false);
gameOverGUI.SetActive(true);
}else{
player.SetActive(true);
gameOverGUI.SetActive(false);
}
}
void OnTriggerEnter2D(Collider2D collider)
{
gameOverTime = true;
}
void OnTriggerExit2D(Collider2D collider)
{
gameOverTime = false;
time = 0.0f;
}
}
GameObjectのBoxCollider2DのIs Triggerはチェックしていますか?
GameOverの時の処理
GameObjectを全て消すようにします.
Projectを右クリックして「Create」→「C#Script」でGameOverDestroy.csを作る.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverDestroy : MonoBehaviour
{
void Update()
{
if(GameManager.gameOver)
{
Destroy(gameObject);
}
}
}
これを全てのフルーツのPrefabにAddComponentする.
ゲームオーバー画面をつくる
Herarchyタブ→「2DObject」→「Sprites」→「Square」でゲームオーバー画面のタブを作ります.
Transformは以下の写真参考にしてください.
これの子どもに
Herarchyタブ→「UI」→「Canvas」を作成.
また,その下に
Herarchyタブ→「UI」→「Button」でリトライボタンを作成する.
Herarchyタブ→「UI」→「TextMeshPro」でTotalscoreとscore2を作成する.
そしてそれぞれの配置は以下の通りである.
リトライ | |
---|---|
Totalscore | |
score2 |
リトライの下にあるTMPにはRetryという文字を書く.
score2表示
SocreDisplay.csを以下のように追加する.
public class ScoreDisplay : MonoBehaviour
{
public TextMeshProUGUI scoreText;
static public int score;
/// 追加コード
public TextMeshProUGUI scoreText2;
///
void Update()
{
if (scoreText != null)
{
scoreText.text = "score: " + score;
}
/// 追加コード
if (scoreText2 != null)
{
scoreText2.text = score.ToString();
}
///
}
}
これで,GameManagerのScoreDisplayのscore2にTMPのscore2を選択する.
リトライボタンの設定
GameRetry.csを作成する.
以下のようなコードを書く.
using UnityEngine;
using UnityEngine.UI;
public class GameRetry : MonoBehaviour
{
private Button retryButton;
private void Start()
{
retryButton = GetComponent<Button>();
retryButton.onClick.AddListener(RetryGame);
}
private void RetryGame()
{
ScoreDisplay.score = 0;
GameManager.gameOver = false;
}
}
これをリトライボタンにAdd Componentする.
すべて作り終わったら,写真のようにInspectorタブからGameOverGUIのチェックを外しましょう.
これで見えなくなります.
EventSystemというものを消してはいけません!!これがボタンを押せるようにしています.
Ex
ここまででスイカゲームの基礎は完成しました.これからは,自分らしいスイカゲームを作成するための手助けになればと思い写真と音をつけられるようにする方法を伝授します!ぜひ,最後までみてオリジナルのスイカゲームを作られるようになりましょう!!
Ex.1 フルーツに写真をつけてみよう!
事前準備:大きさに合った写真
わたしは以下のような大きさにしました.
さくらんぼ | かき | おれんじ | もも | すいか |
---|---|---|---|---|
170(px) | 200 | 350 | 450 | 500 |
画像の反映
用意した写真をProjectタブにドラッグ&ドロップします.そして,Sprite RendererのSpriteを適切な画像を選びます.
当たり判定の調整
次に,PrefabをダブルクリックしてPrefabを編集する画面を開きます.
Circle Collider 2DのRadiusで大きさを変更Offsetで中心を変更して,適切な当たり判定になるようにします.Edit Colliderのボタンを押すことで,マウスで感覚的に当たり判定を調整することができます.
Radiusの参考
さくらんぼ | かき | おれんじ | もも | すいか |
---|---|---|---|---|
0.8 | 1 | 1.7 | 2 | 2.5 |
Ex.2 BGM,サウンドをつけてみよう!!
BGM,SE(サウンドエフェクト)にしたいmp3ファイルをUnityのProjectタブにドラッグ&ドロップする.
BGM
HierarchyでAudioSourceを作成する.
InspectorタブのAudioSorceのAudioClipでBGMにしたいファイルを選ぶ.
そして,Play On AwakeとLoopをチェックする.
Play On Awake:ゲームが始まってすぐに音楽が開始する
Loop:音源が終了すると初めから再生される
SE
当たった時に音がでるようにします.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FruitsCollision : MonoBehaviour{
public GameObject NextFruit;
public int socreAddNum;//スコアの加算値
///SEの追加
public AudioClip collisionSound;
///
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == gameObject.tag)
{
// 自分のインスタンスIDと衝突相手のインスタンスIDを比較
if (gameObject.GetInstanceID() < collision.gameObject.GetInstanceID())
{
//すいかの場合はNextFruitがnullなので生成しない
if (NextFruit != null)
{
//NextFruitを生成
Instantiate(NextFruit, transform.position, transform.rotation);
}
Destroy(gameObject);
ScoreDisplay.score += socreAddNum;
}
else
{
/// 追加コード
AudioSource.PlayClipAtPoint(collisionSound, transform.position);
///
Destroy(gameObject);
}
}
}
}
これのComponentのAudioClipのcollisionSoundに鳴らしたい音を選択します.
さいごに
みなさんお疲れ様でした.ここまできたみなさんなら,だいぶUnityについて理解したのではないかと思います!ここで学んだことは,2Dゲーム以外の3Dゲーム開発やVR,MRゲーム開発にも重要なものです!今回の開発を第一歩目として,Unityを使いこなしていってください!そして,ぜひぼくに遊ばせてください^ ^楽しみに待っています!コメントでGitHubのリンクを貼ってくれたら遊びます!UnityRoomだと大変喜びます.
それでは,みなさんよいエンジニア生活を〜👋
さいごにGitHubのリンクを置いておきます.