Unityでトランプゲームのスピードを作ってみよう!

こんにちは!ジェイです。今回は、Unityを使ってカードゲーム「スピード」を実装する方法を詳しく解説します。

初心者でも理解しやすいように、カードの生成からデッキのシャッフル、プレイヤーの手札管理、中央の山札の管理、勝敗判定まで、ステップバイステップで説明します。

また、AIプレイヤーのターン処理や勝敗表示など、ゲームの完成までの全工程を網羅しています。Unityの基本的な操作やスクリプトの書き方を学びながら、実際にゲームを作成する体験ができるので、ぜひ挑戦してみてください。

Unityでトランプゲームのスピードを作ってみよう!

まず、Unityプロジェクトを新規作成します。プロジェクト名は「SpeedCardGame」にしましょう。

アセットの準備

以下のアセットが必要です。

  • カードのスプライト(表と裏)
  • オーディオクリップ(カードを出す音など)

Unityエディタでの手順

プロジェクトのセットアップ

  • Unityを起動し、新しいプロジェクトを作成します。プロジェクト名を「SpeedCardGame」にします。

シーンの準備

  • メインシーンを開き、必要なUI要素を配置します。例えば、TextMeshProを使用して勝敗表示用のテキストを配置します。
  • Hierarchyビューで右クリックし、UI > Canvasを作成します。
  • Canvasを選択し、その中にUI > TextMeshPro - Textオブジェクトを追加します。名前をresultTextに変更し、非表示に設定します(Inspectorビューでチェックを外す)。
  • 同様に、Player1とPlayer2の残りカード枚数を表示するためのTextMeshPro – Textオブジェクトを追加します。名前をそれぞれplayer1CardNumTextplayer2CardNumTextに変更します。

カードのプレハブを作成

  • プロジェクトビューで右クリックし、Create > Folderを選択してPrefabsフォルダを作成します。
  • Hierarchyビューで右クリックし、2D Object > Spriteを選択してカードオブジェクトを作成します。
  • このオブジェクトにSpriteRendererコンポーネントを追加し、カードのスプライトを設定します。さらに、AudioSourceコンポーネントを追加します。
  • カードオブジェクトをプロジェクトビューのPrefabsフォルダにドラッグし、プレハブとして保存します。

スクリプトの配置

  • プロジェクトビューで右クリックし、Create > Folderを選択してScriptsフォルダを作成します。
  • 以下のスクリプト(Card.cs、Deck.cs、GameManager.cs)を作成し、それぞれScriptsフォルダに保存します。
  • Deck.csをデッキオブジェクトに、Card.csをカードプレハブに、GameManager.csを空のGameObject(名前をGameManagerにする)にアタッチします。

Card.cs

using UnityEngine;

public class Card : MonoBehaviour
{
    public SpriteRenderer spriteRenderer;
    public Sprite cardFace;
    public Sprite cardBack;
    public AudioSource audioSource;

    public string suit;
    public int rank;

    public int DeckNumber = -1;
    public int PlayerIndex = -1;
    void Start()
    {
        // SpriteRendererが設定されていることを確認
        if (spriteRenderer == null)
        {
            spriteRenderer = GetComponent<SpriteRenderer>();
            if (spriteRenderer == null)
            {
                Debug.LogError("SpriteRenderer component is missing on the Card prefab.");
            }
        }
    }

    public void Initialize(string cardSuit, int cardRank)
    {
        suit = cardSuit;
        rank = cardRank;
        cardFace = Resources.Load<Sprite>($"Cards/{suit}_{rank}");
        if (cardFace == null)
        {
            Debug.LogError($"Failed to load sprite for {suit}_{rank} from path Cards/{suit}_{rank}");
        }

        audioSource = GetComponent<AudioSource>();
    }

    public void ShowCardFace()
    {
        if (cardFace != null)
        {
            spriteRenderer.sprite = cardFace;
        }
        else
        {
            Debug.LogError("Card face sprite is not set.");
        }
    }

    public void ShowCardBack()
    {
        if (cardBack != null)
        {
            spriteRenderer.sprite = cardBack;
        }
        else
        {
            Debug.LogError("Card back sprite is not set.");
        }
    }

    public void PlaySound()
    {
        if (audioSource != null)
        {
            audioSource.Play();
        }
    }

    void OnMouseDown()
    {
        if (GameManager.Instance != null)
        {
            GameManager.Instance.OnCardClicked(this);
        }
        else
        {
            Debug.LogError("GameManager instance is null.");
        }
    }
}

Deck.cs

using System.Collections.Generic;
using UnityEngine;

public class Deck : MonoBehaviour
{
    public GameObject cardPrefab;
    public List<Card> player1Cards = new List<Card>();
    public List<Card> player2Cards = new List<Card>();
    public Transform player1Deck;
    public Transform player2Deck;

    public void CreateDeck()
    {
        string[] suits = { "Hearts", "Diamonds", "Clubs", "Spades" };
        int[] ranks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };

        foreach (var suit in suits)
        {
            foreach (var rank in ranks)
            {
                if (suit == "Clubs" || suit == "Spades")
                {
                    GameObject cardObject = Instantiate(cardPrefab, player1Deck.position, Quaternion.identity);
                    cardObject.name = suit + "_" + rank;

                    Card newCard = cardObject.GetComponent<Card>();
                    newCard.Initialize(suit, rank);

                    newCard.ShowCardBack();
                    cardObject.transform.SetParent(player1Deck);
                    player1Cards.Add(newCard);
                }
                else if (suit == "Hearts" || suit == "Diamonds")
                {
                    GameObject cardObject = Instantiate(cardPrefab, player2Deck.position, Quaternion.identity);
                    cardObject.name = suit + "_" + rank;

                    Card newCard = cardObject.GetComponent<Card>();
                    newCard.Initialize(suit, rank);

                    newCard.ShowCardBack();
                    cardObject.transform.SetParent(player2Deck);
                    player2Cards.Add(newCard);
                }
                else
                {
                    Debug.Log("no cards");
                }
            }
        }
    }

    public void ShuffleDeck()
    {
        for (int i = 0; i < player1Cards.Count; i++)
        {
            Card temp = player1Cards[i];
            int randomIndex = Random.Range(i, player1Cards.Count);
            player1Cards[i] = player1Cards[randomIndex];
            player1Cards[randomIndex] = temp;
        }

        for (int i = 0; i < player2Cards.Count; i++)
        {
            Card temp = player2Cards[i];
            int randomIndex = Random.Range(i, player2Cards.Count);
            player2Cards[i] = player2Cards[randomIndex];
            player2Cards[randomIndex] = temp;
        }
    }
}

GameManager.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine.UI; // TextMeshProUGUI用の名前空間を追加

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    public Deck deck;
    public List<Card> player1Hand = new List<Card>();
    public List<Card> player2Hand = new List<Card>();
    public Transform player1HandTrans;
    public Transform player2HandTrans;
    public Transform centerPile1;
    public Transform centerPile2;
    public TextMeshProUGUI resultText; // TextMeshProUGUIを使用するように変更
    public TextMeshProUGUI player1CardNumText; // Player1の残りカード枚数を表示
    public TextMeshProUGUI player2CardNumText; // Player2の残りカード枚数を表示
    private Card centerCard1;
    private Card centerCard2;
    private int sortingOrder = 0;
    private Coroutine player2TurnCoroutine; // コルーチンを保持するためのフィールド
    public float cardDistance = 1.5f;
    public Button restartButton;

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }

    void Start()
    {
        InitializeGame();   
    }

    public void InitializeGame()
    {
        restartButton.gameObject.SetActive(false);
        deck.player1Cards.Clear();
        deck.player2Cards.Clear();
        player1Hand.Clear();
        player2Hand.Clear();
        deck.CreateDeck();
        deck.ShuffleDeck();
        DealCards();
        resultText.gameObject.SetActive(false); // 勝敗テキストを非表示にする
        player1CardNumText.text = "Player:" + (deck.player1Cards.Count + player1Hand.Count).ToString();
        player2CardNumText.text = "CPU:" + (deck.player2Cards.Count + player2Hand.Count).ToString();
        player2TurnCoroutine = StartCoroutine(Player2Turn());
    }

    void DealCards()
    {
        int initialHandSize = 4; // プレイヤーの初期手札の枚数

        // プレイヤー1の手札を配置
        for (int i = 0; i < initialHandSize; i++)
        {
            if (deck.player1Cards.Count > 0)
            {
                Card card1 = deck.player1Cards[0];
                card1.gameObject.transform.SetParent(player1HandTrans);
                card1.DeckNumber = player1Hand.Count;
                card1.PlayerIndex = 1;
                player1Hand.Add(card1);
                card1.transform.position = player1HandTrans.position + new Vector3(i * cardDistance, 0, 0);
                card1.ShowCardFace();
                deck.player1Cards.RemoveAt(0);
            }

            if (deck.player2Cards.Count > 0)
            {
                Card card2 = deck.player2Cards[0];
                card2.gameObject.transform.SetParent(player2HandTrans);
                card2.DeckNumber = player2Hand.Count;
                card2.PlayerIndex = 2;
                player2Hand.Add(card2);
                card2.transform.position = player2HandTrans.position + new Vector3(i * cardDistance, 0, 0);
                Destroy(card2.GetComponent<Collider2D>());
                card2.ShowCardFace();
                deck.player2Cards.RemoveAt(0);
            }
        }

        // センターピルの最初のカードを配置
        if (deck.player1Cards.Count > 0)
        {
            centerCard1 = deck.player1Cards[0];
            centerCard1.gameObject.transform.SetParent(centerPile1);
            centerCard1.transform.position = centerPile1.position;
            Destroy(centerCard1.GetComponent<Collider2D>());
            centerCard1.ShowCardFace();
            centerCard1.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            deck.player1Cards.RemoveAt(0);
        }

        if (deck.player2Cards.Count > 0)
        {
            centerCard2 = deck.player2Cards[0];
            centerCard2.gameObject.transform.SetParent(centerPile2);
            centerCard2.transform.position = centerPile2.position;
            Destroy(centerCard2.GetComponent<Collider2D>());
            centerCard2.ShowCardFace();
            centerCard2.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            deck.player2Cards.RemoveAt(0);
        }
    }

    public void OnCardClicked(Card clickedCard)
    {
        if (clickedCard.PlayerIndex != 1) return; // 表示以外ならリターン

        if (IsValidMove(clickedCard, centerCard1))
        {
            MoveCardToCenterPile(clickedCard, centerPile1, ref centerCard1, player1Hand);   
        }
        else if (IsValidMove(clickedCard, centerCard2))
        {
            MoveCardToCenterPile(clickedCard, centerPile2, ref centerCard2, player1Hand);   
        }
        else
        {
            CheckIfBothPlayersCannotMove();
        }
    }

    private bool IsValidMove(Card clickedCard, Card centerCard)
    {
        return clickedCard.rank + 1 == centerCard.rank ||
               clickedCard.rank - 1 == centerCard.rank ||
               (clickedCard.rank == 1 && centerCard.rank == 13) ||
               (clickedCard.rank == 13 && centerCard.rank == 1);
    }

    private void MoveCardToCenterPile(Card clickedCard, Transform centerPile, ref Card centerCard, List<Card> playerHand)
    {
        // 中央の山札のカードのソートレイヤーを変更
        clickedCard.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;

        // クリックされたカードを中央の山札の位置に移動
        clickedCard.transform.SetParent(centerPile);
        clickedCard.transform.position = centerPile.position;

        // 中央の山札のカードをクリックされたカードに置き換え
        centerCard = clickedCard;
        Destroy(centerCard.GetComponent<Collider2D>());

        // 必要に応じてカードの表示を更新
        centerCard.ShowCardFace();
        centerCard.PlaySound();

        // クリックされたカードの位置を取得
        int clickedCardIndex = playerHand.IndexOf(clickedCard);

        // 新しいカードをデッキから手札に移動
        if (playerHand == player1Hand)
        {
            if (deck.player1Cards.Count > 0)
            {
                Card newCard = deck.player1Cards[0];
                newCard.Initialize(newCard.suit, newCard.rank); // スプライトを正しく設定
                newCard.gameObject.transform.SetParent(player1HandTrans);
                newCard.transform.position = player1HandTrans.position + new Vector3(clickedCardIndex * cardDistance, 0, 0);
                newCard.ShowCardFace();
                playerHand[clickedCardIndex] = newCard;
                newCard.DeckNumber = clickedCardIndex;
                newCard.PlayerIndex = 1;
                deck.player1Cards.RemoveAt(0);
            }
            else
            {
                // デッキが空の場合、手札からカードを削除
                playerHand.RemoveAt(clickedCardIndex);
            }
        }
        else if (playerHand == player2Hand)
        {
            if (deck.player2Cards.Count > 0)
            {
                Card newCard = deck.player2Cards[0];
                newCard.Initialize(newCard.suit, newCard.rank); // スプライトを正しく設定
                newCard.gameObject.transform.SetParent(player2HandTrans);
                newCard.transform.position = player2HandTrans.position + new Vector3(clickedCardIndex * cardDistance, 0, 0);
                newCard.ShowCardFace();
                playerHand[clickedCardIndex] = newCard;
                newCard.DeckNumber = clickedCardIndex;
                newCard.PlayerIndex = 2;
                deck.player2Cards.RemoveAt(0);
            }
            else
            {
                // デッキが空の場合、手札からカードを削除
                playerHand.RemoveAt(clickedCardIndex);
            }
        }

        player1CardNumText.text = "Player:" + (deck.player1Cards.Count + player1Hand.Count).ToString();
        player2CardNumText.text = "CPU:" + (deck.player2Cards.Count + player2Hand.Count).ToString();

        CheckForWinner();
    }

    private void CheckIfBothPlayersCannotMove()
    {
        bool player1CannotMove = !CanPlayerMove(player1Hand);
        bool player2CannotMove = !CanPlayerMove(player2Hand);

        if (player1CannotMove && player2CannotMove)
        {
            bool player1win = false;
            bool player2win = false;

            if (deck.player1Cards.Count > 0)
            {
                DrawCardsToCenterPilesPlayer1();
            }
            else
            {
                if (player1Hand.Count > 0)
                {
                    DrawCardsFromHandsToCenterPilesPlayer1();
                }
                else
                {
                    // Player1勝利
                    player1win = true;
                }
            }

            if (deck.player2Cards.Count > 0)
            {
                DrawCardsToCenterPilesPlayer2();
            }
            else
            {
                if (player2Hand.Count > 0)
                {
                    DrawCardsFromHandsToCenterPilesPlayer2();
                }
                else
                {
                    // Player2勝利
                    player2win = true;
                }
            }
          
            if(player1win)
            {
                if(!player2win)
                {
                    Debug.Log("PlayerWin");
                    foreach (var hand in player1Hand)
                    {
                        Destroy(hand.GetComponent<BoxCollider2D>());
                    }
                    resultText.text = "Player Win!";
                    resultText.gameObject.SetActive(true);
                    restartButton.gameObject.SetActive(true);
                    if (player2TurnCoroutine != null) StopCoroutine(player2TurnCoroutine); // コルーチンを停止
                }
                else
                {
                    Debug.Log("Draw");
                    foreach (var hand in player1Hand)
                    {
                        Destroy(hand.GetComponent<BoxCollider2D>());
                    }
                    resultText.text = "Draw!";
                    resultText.gameObject.SetActive(true);
                    restartButton.gameObject.SetActive(true);
                    if (player2TurnCoroutine != null) StopCoroutine(player2TurnCoroutine); // コルーチンを停止
                }
            }
            else if(player2win)
            {
                if (!player1win)
                {
                    Debug.Log("CPUWin");
                    foreach (var hand in player1Hand)
                    {
                        Destroy(hand.GetComponent<BoxCollider2D>());
                    }
                    resultText.text = "CPU Win!";
                    resultText.gameObject.SetActive(true);
                    restartButton.gameObject.SetActive(true);
                    if (player2TurnCoroutine != null) StopCoroutine(player2TurnCoroutine); // コルーチンを停止
                }
                else
                {
                    Debug.Log("Draw");
                    foreach (var hand in player1Hand)
                    {
                        Destroy(hand.GetComponent<BoxCollider2D>());
                    }
                    resultText.text = "Draw!";
                    resultText.gameObject.SetActive(true);
                    restartButton.gameObject.SetActive(true);
                    if (player2TurnCoroutine != null) StopCoroutine(player2TurnCoroutine); // コルーチンを停止
                }
            }
            else
            {
                StartCoroutine(ShowSpeedText("Seed")); // "Speed" テキストを表示
            }
        }
    }
    private bool CanPlayerMove(List<Card> playerHand)
    {
        foreach (Card card in playerHand)
        {
            if (IsValidMove(card, centerCard1) || IsValidMove(card, centerCard2))
            {
                // プレイヤーはまだカードを出すことができる
                return true;
            }
        }
        return false;
    }

    private void DrawCardsToCenterPilesPlayer1()
    {
        // プレイヤー1のデッキからカードを引いてセンターピル1に置く
        if (deck.player1Cards.Count > 0)
        {
            // 既存の中央の山札のカードのソートレイヤーを変更
            foreach (Transform child in centerPile1)
            {
                child.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            }

            Card newCenterCard1 = deck.player1Cards[0];
            newCenterCard1.Initialize(newCenterCard1.suit, newCenterCard1.rank);
            newCenterCard1.gameObject.transform.SetParent(centerPile1);
            newCenterCard1.transform.position = centerPile1.position;
            newCenterCard1.ShowCardFace();
            newCenterCard1.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            centerCard1 = newCenterCard1;
            deck.player1Cards.RemoveAt(0);
        }
    }

    private void DrawCardsToCenterPilesPlayer2()
    {
        // プレイヤー2のデッキからカードを引いてセンターピル2に置く
        if (deck.player2Cards.Count > 0)
        {
            // 既存の中央の山札のカードのソートレイヤーを変更
            foreach (Transform child in centerPile2)
            {
                child.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            }

            Card newCenterCard2 = deck.player2Cards[0];
            newCenterCard2.Initialize(newCenterCard2.suit, newCenterCard2.rank);
            newCenterCard2.gameObject.transform.SetParent(centerPile2);
            newCenterCard2.transform.position = centerPile2.position;
            newCenterCard2.ShowCardFace();
            newCenterCard2.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            centerCard2 = newCenterCard2;
            deck.player2Cards.RemoveAt(0);
        }
    }

    private void DrawCardsFromHandsToCenterPilesPlayer1()
    {
        // プレイヤー1の手札からカードを引いてセンターピル1に置く
        if (player1Hand.Count > 0)
        {
            // 既存の中央の山札のカードのソートレイヤーを変更
            foreach (Transform child in centerPile1)
            {
                child.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            }

            Card newCenterCard1 = player1Hand[0];
            newCenterCard1.Initialize(newCenterCard1.suit, newCenterCard1.rank);
            newCenterCard1.gameObject.transform.SetParent(centerPile1);
            newCenterCard1.transform.position = centerPile1.position;
            newCenterCard1.ShowCardFace();
            newCenterCard1.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            centerCard1 = newCenterCard1;
            player1Hand.RemoveAt(0);
        }
    }

    private void DrawCardsFromHandsToCenterPilesPlayer2()
    {
        // プレイヤー2の手札からカードを引いてセンターピル2に置く
        if (player2Hand.Count > 0)
        {
            // 既存の中央の山札のカードのソートレイヤーを変更
            foreach (Transform child in centerPile2)
            {
                child.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            }

            Card newCenterCard2 = player2Hand[0];
            newCenterCard2.Initialize(newCenterCard2.suit, newCenterCard2.rank);
            newCenterCard2.gameObject.transform.SetParent(centerPile2);
            newCenterCard2.transform.position = centerPile2.position;
            newCenterCard2.ShowCardFace();
            newCenterCard2.GetComponent<SpriteRenderer>().sortingOrder = sortingOrder++;
            centerCard2 = newCenterCard2;
            player2Hand.RemoveAt(0);
        }
    }

    private void CheckForWinner()
    {
        if (player1Hand.Count == 0)
        {
            if(player2Hand.Count > 0)
            {
                Debug.Log("Player Win!");
                foreach(var hand in player1Hand)
                {
                    Destroy(hand.GetComponent<BoxCollider2D>());
                }
                resultText.text = "Player Win!";
                resultText.gameObject.SetActive(true);
                restartButton.gameObject.SetActive(true);
                if (player2TurnCoroutine != null) StopCoroutine(player2TurnCoroutine); // コルーチンを停止
            }
            else
            {
                Debug.Log("Draw!");
                foreach (var hand in player1Hand)
                {
                    Destroy(hand.GetComponent<BoxCollider2D>());
                }
                resultText.text = "Draw!";
                resultText.gameObject.SetActive(true);
                restartButton.gameObject.SetActive(true);
                if (player2TurnCoroutine != null) StopCoroutine(player2TurnCoroutine); // コルーチンを停止
            }
        }
        else if (player2Hand.Count == 0)
        {
            if (player1Hand.Count > 0)
            {
                Debug.Log("CPU Win!");
                foreach (var hand in player1Hand)
                {
                    Destroy(hand.GetComponent<BoxCollider2D>());
                }
                resultText.text = "CPU Win!";
                resultText.gameObject.SetActive(true);
                restartButton.gameObject.SetActive(true);
                if (player2TurnCoroutine != null) StopCoroutine(player2TurnCoroutine); // コルーチンを停止
            }
            else
            {
                Debug.Log("Draw!");
                foreach (var hand in player1Hand)
                {
                    Destroy(hand.GetComponent<BoxCollider2D>());
                }
                resultText.text = "Draw!";
                resultText.gameObject.SetActive(true);
                restartButton.gameObject.SetActive(true);
                if (player2TurnCoroutine != null) StopCoroutine(player2TurnCoroutine); // コルーチンを停止
            }
        }
    }

    private IEnumerator Player2Turn()
    {
        while (true)
        {
            yield return new WaitForSeconds(Random.Range(1, 4));

            Card cardToPlay1 = null, cardToPlay2 = null;

            foreach (Card card in player2Hand)
            {
                if (card.PlayerIndex == -1) continue;
                
                if (IsValidMove(card, centerCard1))
                {
                    cardToPlay1 = card;
                    break;
                }
            }
            foreach (Card card in player2Hand)
            {
                if (card.PlayerIndex == -1) continue;

                if (IsValidMove(card, centerCard2))
                {
                    cardToPlay2 = card;
                    break;
                }
            }

            if (cardToPlay1 != null)
            {
                MoveCardToCenterPile(cardToPlay1, centerPile1, ref centerCard1, player2Hand);
            }
            else if (cardToPlay2 != null)
            {
                MoveCardToCenterPile(cardToPlay2, centerPile2, ref centerCard2, player2Hand);
            }
            else
            {
                CheckIfBothPlayersCannotMove();
            }
        }
    }
    private IEnumerator ShowSpeedText(string _text)
    {
        resultText.text = _text;
        resultText.gameObject.SetActive(true);
        yield return new WaitForSeconds(2);
        resultText.gameObject.SetActive(false);
    }
}

オブジェクトのリンク

  • GameManagerオブジェクトのInspectorで、以下をアタッチして設定します。
    • Deck: デッキオブジェクトをドラッグアンドドロップ
    • player1HandTrans: Player1の手札のTransformをドラッグアンドドロップ
    • player2HandTrans: Player2の手札のTransformをドラッグアンドドロップ
    • centerPile1: 中央の山札1のTransformをドラッグアンドドロップ
    • centerPile2: 中央の山札2のTransformをドラッグアンドドロップ
    • resultText: ResultTextオブジェクトをドラッグアンドドロップ
    • player1CardNumText: Player1CardNumTextオブジェクトをドラッグアンドドロップ
    • player2CardNumText: Player2CardNumTextオブジェクトをドラッグアンドドロップ

ボタンの設定

  • UI > ButtonをCanvas内に追加し、名前をrestartButtonに変更します。
  • Buttonオブジェクトを選択し、InspectorでOnClickイベントを追加し、GameManagerオブジェクトをドラッグアンドドロップします。
  • No Functionをクリックし、ドロップダウンメニューからGameManager > InitializeGameを選択します。

ゲームの実行

  • Unityエディタでゲームを実行し、カードゲーム「スピード」をプレイします。プレイヤーがカードをクリックすると、そのカードが中央の山札に移動し、AIプレイヤーが自動的にターンを進行します。

スクリプトの説明

Card.cs

Card.csはカードの情報を保持し、カードの表示や音声の再生を行うスクリプトです。このスクリプトでは、カードのスーツやランクを設定し、カードの表と裏の画像を表示する方法を提供します。また、カードがクリックされたときにGameManagerに通知する機能も備えています。

Deck.cs

Deck.csはデッキの生成とシャッフルを行うスクリプトです。このスクリプトでは、カードデッキを生成し、各プレイヤーにカードを割り当て、デッキをシャッフルします。

GameManager.cs

GameManager.csはゲーム全体を管理するスクリプトです。このスクリプトでは、ゲームの初期化、カードの配布、プレイヤーの手札管理、中央の山札管理、ターンの進行、勝敗判定、AIプレイヤーの動作などを制御します。また、プレイヤーの手札の数を更新し、勝敗を表示する機能も含まれています。

おわりに

このプロジェクトでは、Unityを使ってカードゲーム「スピード」を実装する方法を学びました。カードの生成、デッキのシャッフル、プレイヤーの手札管理、中央の山札の管理、勝敗判定、AIプレイヤーのターン処理など、ゲームの基本的な要素を網羅しています。この記事を参考にして、ぜひ自分のゲームを作ってみてください。