スポンサーリンク
スポンサーリンク
Unityゲームの作り方メモ

【Unity】ツムツム風パズルゲームの作り方

Unity

ユニティーを使用したツムツム風ゲームの作り方のメモです。ゲーム制作の参考にしていただければ嬉しいです。トグルボタンをクリックすると記事が表示されます。小さくて見ずらい画像はクリックで拡大できます。

使用する素材

ボールの作成

用意した画像をヒエラルキーウィンドウにドラッグ&ドロップします。

ボールに必要なコンポーネントを付けていきます。

ボールにつけるコンポーネント
Rigidbody 2D
CircleColider 2D

作成したボールをprefabにしておきます。

壁の作成

空のオブジェクトを作成します。名前はWallにしました。

壁につけるコンポーネント
Edgecolider2D

Edgecoliderを編集してかべを作成します。

ボールを跳ねるようにする

Bounclnessを設定します。

ボールのrigidbodyのmaterialの項目に設定します。

ボールを増やして再生するとこんな感じになります。

ボールの生成

新しくC#スクリプトを作成します。名前はBallGeneratorにしました。

一個ずつボールを生成したいのでコルーチンを使います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BallGenerator : MonoBehaviour
{
    //ボールを生成する

    [SerializeField] GameObject ballPrefab = default;

    private void Start()
    {
        StartCoroutine(Spawns(10));
        
    }
    public IEnumerator Spawns(int count) 
    {
        //ボールを数個生成する
        for (int i = 0; i < count; i++)
        {
            //ランダムな位置
            Vector2 pos = new Vector2(Random.Range(-0.2f, 0.2f), 8f);
            //生成する
            Instantiate(ballPrefab,pos,Quaternion.identity);
            //時間をあける
            yield return new WaitForSeconds(0.05f);
        }
       
    
    }
}

ランダムな位置から少し時間を空けてボールが生成されるようになりました。

5種類のボールを生成する

BallGeneratorにコードを追加します。

生成時にボールの画像を設定して5種類のボールを作ります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BallGenerator : MonoBehaviour
{
    //ボールを生成する

    [SerializeField] GameObject ballPrefab = default;

    //設定する画像
    [SerializeField] Sprite[] ballSprite = default;

    private void Start()
    {
        StartCoroutine(Spawns(10));
        
    }
    public IEnumerator Spawns(int count) 
    {
        //ボールを数個生成する
        for (int i = 0; i < count; i++)
        {
            //ランダムな位置
            Vector2 pos = new Vector2(Random.Range(-0.2f, 0.2f), 8f);
            //生成する
            GameObject ball =  Instantiate(ballPrefab,pos,Quaternion.identity);
            //ランダムに画像を設定する
            int ballID = Random.Range(0, ballSprite.Length);
            ball.GetComponent<SpriteRenderer>().sprite= ballSprite[ballID];
            //時間をあける
            yield return new WaitForSeconds(0.05f);
        }
       
    
    }
}

inspector画面からballspriteを設定します。

5種類の画像を設定しました。

色の違うボールが生成されるようになりました。

ボールの差別化

スクリプトを使用してボールにIDを持たせて差別化します。

新しくC#スクリプトを作成します。名前はBallにしました。

using UnityEngine;

public class Ball : MonoBehaviour
{
    public int id;
}

作成したスクリプトをボールのprefabに設定します。

Ballgeneratorにコードを追加します。

生成した時にIdを設定するようにします。

//Spawnsのfor文の中に書く
ball.GetComponent<Ball>().id= ballID;

再生して確認すると色ごとに別のIDが設定されるようになりました。

ボールをクリックできるようにする

新しくC#スクリプトを作成します。名前はGameSystemにしました。

空のオブジェクトを作成してGameSystemをアタッチしておきます。

using UnityEngine;

public class GameSystem : MonoBehaviour
{
    [SerializeField] BallGenerator ballGenerator = default;

    bool isDragging;
    
    void Start()
    {
        //BallGeneratorのStart関数を消してこちらで処理する
        StartCoroutine(ballGenerator.Spawns(30));
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //右クリックを押し込んだ時
            OnDragBegin();
        }
        else if (Input.GetMouseButtonUp(0))
        {
            //右クリックを離したとき
            OnDragEnd();
        }
        else if (isDragging) 
        {
            OnDragging();
        }


    }

    void OnDragBegin() 
    {
        //マウスによるオブジェクトの判定
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);
        if (hit && hit.collider.GetComponent<Ball>())
        {
            Debug.Log("ボールにヒット");
        }
    
    }
    void OnDragging() 
    {
    
    }

    void OnDragEnd() 
    {
        Debug.Log("ドラッグ終了");
    
    }
}

inspector画面からBallGeneratorをセットします。

ボールをクリックするとログが表示されるようになりました。

ボールを削除する

クリックしたボールを削除するためにリストを作成して、

そのリストに追加されたボールを削除するようにしていきます。

[SerializeField] List<Ball> removeBalls= new List<Ball>();

 void OnDragBegin() 
    {
        //マウスによるオブジェクトの判定
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);
        if (hit && hit.collider.GetComponent<Ball>())
        {
            Debug.Log("ボールにヒット");
            Ball ball = hit.collider.GetComponent<Ball>();
            AddRemoveBall(ball);    
            isDragging= true;
        }
    
    }
    void OnDragging() 
    {
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);
        if (hit && hit.collider.GetComponent<Ball>())
        {
            Debug.Log("ボールにヒット");
            Ball ball = hit.collider.GetComponent<Ball>();
            
            AddRemoveBall(ball);
           
        }

    }

    void OnDragEnd() 
    {
        //removeBallsのボールを消去
        int removeCount = removeBalls.Count;
        for (int i = 0; i < removeCount; i++)
        {
            Destroy(removeBalls[i].gameObject);
        }
        removeBalls.Clear();
        Debug.Log("ドラッグ終了");
        isDragging= false;
    
    }

    void AddRemoveBall(Ball ball) 
    {
        //まだ持ってないボールのみ追加する
        if (removeBalls.Contains(ball) == false)
        {
            removeBalls.Add(ball);
        }
    
    }

選択したボールが消えるようになりました。

同じ種類のボールだけリストに追加する

同じ種類のボールで距離の近いものをリストに追加して、3個以上なら消えるようにします。

using System.Collections.Generic;
using UnityEngine;

public class GameSystem : MonoBehaviour
{
    [SerializeField] BallGenerator ballGenerator = default;

    bool isDragging;

    [SerializeField] List<Ball> removeBalls= new List<Ball>();

    //現在ドラッグしているボール
    Ball currentDraggingBall;
    
    void Start()
    {
        //BallGeneratorのStart関数を消してこちらで処理する
        StartCoroutine(ballGenerator.Spawns(30));
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //右クリックを押し込んだ時
            OnDragBegin();
        }
        else if (Input.GetMouseButtonUp(0))
        {
            //右クリックを離したとき
            OnDragEnd();
        }
        else if (isDragging) 
        {
            OnDragging();
        }
    }

    void OnDragBegin() 
    {
        //マウスによるオブジェクトの判定
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);
        if (hit && hit.collider.GetComponent<Ball>())
        {
            Ball ball = hit.collider.GetComponent<Ball>();
            AddRemoveBall(ball);    
            isDragging= true;
        }  
    }
    void OnDragging() 
    {
        Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(mousePosition, Vector2.zero);
        if (hit && hit.collider.GetComponent<Ball>())
        {
            //現在ドラッグしているボールと同じ種類で距離の近いボールをリストに追加する
            Ball ball = hit.collider.GetComponent<Ball>();
            //ボールのIDが一致したら
            if (ball.id == currentDraggingBall.id)
            {
                //距離が近い
                float distance = Vector2.Distance(ball.transform.position, currentDraggingBall.transform.position);
                if (distance < 1.5)
                {
                    AddRemoveBall(ball);

                }
            }
        }

    }

    void OnDragEnd() 
    {
        //removeBallsのボールを消去
        int removeCount = removeBalls.Count;
        //3個以上なら消す
        if (removeCount >= 3)
        {
            for (int i = 0; i < removeCount; i++)
            {
                Destroy(removeBalls[i].gameObject);
            }
        }
        removeBalls.Clear();
        isDragging= false;
    }

    void AddRemoveBall(Ball ball) 
    {
        currentDraggingBall = ball;
        //まだ持ってないボールのみ追加する
        if (removeBalls.Contains(ball) == false)
        {
            removeBalls.Add(ball);
        }
    
    }
}

スコアの実装

ボールを消した数によってスコアを加算するようにしていきます。

スコアを表示するテキストを作成します。私はゲーム画面の左上に配置しました。

GameSystemにスコアを表示するコードを追加していきます。

  int score;
    [SerializeField] Text scoreText = default;

 void Start()
    {
        //スコアの初期設定
        score= 0;
        addScore(0);
        //BallGeneratorのStart関数を消してこちらで処理する
        StartCoroutine(ballGenerator.Spawns(30));
    }

void addScore(int point) 
    {
        //スコアの更新
        score += point;
        scoreText.text = score.ToString();
    }


    void OnDragEnd() 
    {
        //removeBallsのボールを消去
        int removeCount = removeBalls.Count;
        //3個以上なら消す
        if (removeCount >= 3)
        {
            for (int i = 0; i < removeCount; i++)
            {
                Destroy(removeBalls[i].gameObject);
            }
            //消えた分だけ生成する
            StartCoroutine(ballGenerator.Spawns(removeCount));
            //スコアを加算する
            addScore(removeCount * 100);
        }
        removeBalls.Clear();
        isDragging= false;
    }

inspector画面からスコアテキストを設定します。

ボールを消すとスコアが加算されるようになりました。

パズルゲームのアセット

スポンサーリンク
C-BA memo
タイトルとURLをコピーしました