13
15

はじめに

みなさん,こんにちはbearlです.
今回は昨年話題になったスイカゲームをUnityを使って爆速,1時間以内で作ってみました.かなり簡単なものを作ったので,これを応用して自分だけのすばらしいスイカゲームを作ってみてください!コメントくれたら,相談に乗りますし,作ってみたスイカゲームを是非ぼくに遊ばせてください^^

初心者の方から作成できるようにしているので,下の目次を見て大丈夫なところは飛ばしていってくださいね〜

GitHubのリンクを置いておきます.

目次

  1. プロジェクトの作成
  2. フィールドの作成
  3. フルーツの作成
  4. フルーツを落とすPlayerの作成
  5. フルーツたちの当たった時の処理(合体処理)
  6. フルーツを積み立てすぎないようにする
  7. スコア表示
  8. ゲームオーバーの設定

Ex1. フルーツに写真をつけてみよう!
Ex2. BGM,サウンドをつける!!

実行環境

Unity 2022.3.24f1

1. プロジェクトの作成

写真のように新しいプロジェクトを作成しましょう.
スクリーンショット 2024-06-01 13.18.04.png

2. フィールドの作成

では,まずゲーム画面を映すカメラを設定します.
MainCameraを以下のように設定してください.

image.png

Projectionを変更し忘れていませんか?
Sizeは10になっていますか?


フルーツたちが入るカゴの作成

Hierarchyタブを右クリックして「2D Object」→ 「Sprites」 → 「squeare」で四角形を作ります.
image.png


当たり判定の作成

Inspectorタブの一番下にある「Add Component」を押し,「BoxCollider2D」を追加します.
検索で「Box」と打つと出てくると思います.
image.png


大きさと場所の設定

InspectorタブのTrasformの値をいじると変更できます.

  • Positionが場所
  • Rotaionが角度
  • Scaleが大きさ
    image.png

下を参考にして,床,右の壁,左の壁を作っていきましょう.

image.png 
右壁 image.png
左壁 image.png

このようになったら完成です.
image.png

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 反発係数

わたしは以下のようにしました.
image.png

これをフルーツのCircleCollider2DのMaterialで選択するとOKです!

image.png

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な適当な場所にします(下図参考).

image.png

Player.csの作成

Projectを右クリックして「Create」→「C#Script」でPlayer.csを作成します.処理としては,Input.GetKey()で特定キーを打ち込まれた時にTrueを返す.spaceDelayでスペースキーを連打できないように次に押すまでの時間を設定しました.これは定数なのでconstをつけます.Instantiate()

Player.cs
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から生成されるフルーツを決めている.

image.png

5. フルーツたちの当たった時の処理(合体処理)

さくらんぼを例にします.
Projectを右クリックして「Create」→「C#Script」でFruitsCollision.csを作る.同じフルーツ同士が当たった時に進化先のフルーツが1つできるようにします.処理としては,Tagで同じフルーツかを管理し,gameobjectにはそれぞれにIDがあり,それが少ない方の場所にかきができてるようにしました.
以下のコードを参考にしてください.

FruitsCollision.cs
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の位置を少しだけずらすことで,連続で積まれることを防いぎました.

Player.cs
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としておく.
image.png

Inspectorタブで表示を以下のようにする.
image.png

scoreの作成

Projectを右クリックして「Create」→「C#Script」でScoreDisplay.csを作る.

Hierarchyを右クリックして「Create Empty」してGameManagerという空のObjectを作る.

Add ComponetでScoreDisplay.csを追加する.それのscoreTextに先ほど作成したTextMeshProのscoreを選択する.

GameManagerは空のオブジェクトとして,オブジェクトとしては必要ないけどスクリプトだけが動いて欲しい時に使います.

ScoreDisplay.csのコードをいかに記述する.

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点増やすようにします.

FruitsCollision.cs
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);
                GameManager.score += socreAddNum;

            }
            else
            {
                Destroy(gameObject);
            }
        }
    }
}


8. ゲームオーバーの設定

GameManagerを作る

Projectを右クリックして「Create」→「C#Script」でGameManager.csを作る.
GameManagerオブジェクトにAdd Componetする.加えて,GameManagerにAdd ComponentでBox Collider 2D をつける.なにをするかというと,GameOverとなるかごのふたを作っているのです.
そして,IsTrigerをチェックしておきましょう.

image.png

Transformは以下を参考にしてください.

image.png

GameManager.csのコードは以下のようにします.

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はチェックしていますか?

image.png

GameOverの時の処理

GameObjectを全て消すようにします.
Projectを右クリックして「Create」→「C#Script」でGameOverDestroy.csを作る.

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は以下の写真参考にしてください.
image.png

これの子どもに
Herarchyタブ→「UI」→「Canvas」を作成.
また,その下に
Herarchyタブ→「UI」→「Button」でリトライボタンを作成する.
Herarchyタブ→「UI」→「TextMeshPro」でTotalscoreとscore2を作成する.

依存関係はこのような感じです.
image.png

そしてそれぞれの配置は以下の通りである.

リトライ image.png
Totalscore image.png
score2 image.png

リトライの下にあるTMPにはRetryという文字を書く.

score2表示

SocreDisplay.csを以下のように追加する.

ScoreDisplay.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を作成する.
以下のようなコードを書く.

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のチェックを外しましょう.
これで見えなくなります.

image.png

EventSystemというものを消してはいけません!!これがボタンを押せるようにしています.

Ex

ここまででスイカゲームの基礎は完成しました.これからは,自分らしいスイカゲームを作成するための手助けになればと思い写真と音をつけられるようにする方法を伝授します!ぜひ,最後までみてオリジナルのスイカゲームを作られるようになりましょう!!

Ex.1 フルーツに写真をつけてみよう!

事前準備:大きさに合った写真

わたしは以下のような大きさにしました.

さくらんぼ かき おれんじ もも すいか
170(px) 200 350 450 500

画像の反映

用意した写真をProjectタブにドラッグ&ドロップします.そして,Sprite RendererのSpriteを適切な画像を選びます.

image.png

当たり判定の調整

まず,写真をつけるオブジェクトの大きさを1にしましょう.
image.png

次に,PrefabをダブルクリックしてPrefabを編集する画面を開きます.

image.png

Circle Collider 2DのRadiusで大きさを変更Offsetで中心を変更して,適切な当たり判定になるようにします.Edit Colliderのボタンを押すことで,マウスで感覚的に当たり判定を調整することができます.

image.png

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:音源が終了すると初めから再生される

image.png

SE

当たった時に音がでるようにします.

FruitsCollision.cs
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のリンクを置いておきます.

13
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
15