ブロックゲームの制作

開発のTips

1.シーンの構成
 ブロックゲームは4つのシーンから成ります。

2.各シーンのゲームオブジェクトとスクリプト
2.1 StartScene

(1)start1g
・「START」ボタンが押されたら、GameSceneのシーンに切り替えます。

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

public class StartIconHandler : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private void OnMouseDown()
    {
        Debug.Log("Game Start");
        // ゲーム画面に切り換え
        GameManager.score = 0;
        SceneManager.LoadScene("GameScene"); // ゲームシーンに移動
    }
}

(2)closemark
・「×」ボタンが押されたら、アプリケーションを終了します。

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

public class GameQuitHandler : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private void OnMouseDown()
    {
        Debug.Log("Game Quit");
        AndroidJavaClass version = new AndroidJavaClass("android.os.Build$VERSION");
        int apiLevel = version.GetStatic<int>("SDK_INT");
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

        if (apiLevel >= 21)
        {
            activity.Call("finishAndRemoveTask");
        }
        else
        {
            activity.Call("finish");
        }
    }
}

2.2 GameScene

(1)GameManager
・スコア、ボールの数を管理します。
・ボールを生成するメソッドを持ちます。ボールが最大数に達したらゲームオーバーとし、GameOverScneneに切り替えます。
・スコアを加算するメソッドを持ちます。スコアの数で全てのブロックを崩したと判断し、
ゲームゴールとし、GameGoalSceneのシーンに切り替えます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.SocialPlatforms.Impl;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{
    public GameObject ballPrefab; // ボールのプレハブ
    public Transform ballSpawnPoint; // ボールの生成位置
    public int playerScore = 0; // プレイヤーのスコア
    public int maxBalls = 3; // 最大ボール数
    private int currentBallCount = 0; // 現在のボール数をカウントするフィールド

    public Text scoreText; // スコア表示用Textコンポーネント
    public Text ballCountText; // ボール数表示用Textコンポーネント

    public static int score = 0; // 現在のスコア
    public int ballCount = 0; // 現在のボールの数

    // Start is called before the first frame update
    void Start()
    {
        //SpawnBall();
        ballCount = maxBalls;//残りのボール数
        UpdateUI();
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    // ボールを生成する
    public void SpawnBall()
    {
        //if (ballPrefab != null && ballSpawnPoint != null)
        if (ballPrefab != null)
        {
            if (currentBallCount < maxBalls)
            {
                // ボールを生成
                GameObject newBall = Instantiate(ballPrefab, ballSpawnPoint.position, Quaternion.identity);
                currentBallCount++; // ボールを生成したらカウントを増やす
                ballCount = maxBalls-currentBallCount;//残りのボール数
                Debug.Log("ballcount:"+ballCount);
                UpdateUI();

                 // 必要ならばボールの発射処理を呼び出す
                 Ball ballScript = newBall.GetComponent<Ball>();
                if (ballScript != null)
                {
                    ballScript.InitializeBall(); // ボールの初期化
                }
            }
            else
            {
                Debug.Log("ボールの最大数に達しました。");
                //GameOver
                SceneManager.LoadScene("GameOverScene"); // ゲームシーンに移動

            }
        }
        else
        {
            Debug.LogError("ballPrefabまたはballSpawnPointが設定されていません!");

            if (ballPrefab == null)
            {
                Debug.LogError("ballPrefabが設定されていません!");
            }
            if (ballSpawnPoint == null)
            {
                Debug.LogError("ballSpawnPointが設定されていません!");
            }
        }
    }
    
    // スコアを加算する
    public void AddScore(int points)
    {
        playerScore += points;
        score = playerScore;
        Debug.Log("Score: " + playerScore);
        UpdateUI();
        if (score == BlockManager.columns * BlockManager.rows *10)
        {
            Debug.Log("Game Goal");
            // ゲームゴール画面に切り換え
            SceneManager.LoadScene("GameGoalScene"); // ゲームゴールシーンに移動
        }
    }

    // ゲームリセット用
    public void ResetGame()
    {
        playerScore = 0;
        SpawnBall();
        Debug.Log("Game Reset");
    }

    // UIを更新するメソッド
    void UpdateUI()
    {
        scoreText.text = "SCORE: " + score;
        ballCountText.text = "BALLCOUNT" + ballCount;
    }

}

(2)Ball(Prefab)
・ボールに初速度を与えるメソッドを持ちます。
・ボールが壁に衝突したとき、同じ軌跡を繰り返さないようにするため、ランダムな角度と速度を設定します。
・ボールがWall_Bの壁に衝突してボールを消滅させるとき、ボールを削除しないで非表示とします。(ボールを削除した場合、新たなボールのオブジェクトを取得できなかったため)
 また、非表示にしたボールが物理的に影響しないように衝突を無効化します。

 // ボールを完全停止させる処理
    private void StopBall()
    {
        rb.velocity = Vector2.zero;       // 移動速度をゼロにする
        rb.angularVelocity = 0f;          // 回転速度をゼロにする
        rb.isKinematic = true;            // 物理演算を無効化
        GetComponent<Renderer>().enabled = false; // ボールを非表示にする
        Collider2D collider = this.gameObject.GetComponent<Collider2D>();
        if (collider != null)
        {
            collider.enabled = false; // Colliderを無効化
        }
    }
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Ball : MonoBehaviour
{
    public float speed = 5f; // ボールの速度
    private Rigidbody2D rb;
    private GameObject currentBall; // 現在のボールを一時的に保存するフィールド
    private Renderer ballRenderer;
    //衝突時の角度調整追加
    public float angleVariation = 1f; // ランダムな角度調整範囲

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();

        Launch();
       
        BallManager manager = FindObjectOfType<BallManager>();
        if (manager != null)
        {
            manager.SetBall(this.gameObject);
        }

    }

    // Update is called once per frame
    void Update()
    {

    }
    // ボールを発射する
    private void Launch()
    {
        Vector2 direction = new Vector2(Random.Range(-1f, 1f), 1).normalized;
        rb.velocity = direction * speed;
        ballRenderer = this.gameObject.GetComponent<Renderer>();
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        Vector3 direction = rb.velocity.normalized;

        // ランダムな角度調整を加える
        direction.x += Random.Range(-angleVariation, angleVariation);
        direction.y += Random.Range(-angleVariation, angleVariation);

        // 正規化して速度を設定
        rb.velocity = direction.normalized * speed;
        Debug.Log("衝突時の角度調整しました");

        if (collision.gameObject.CompareTag("Block"))
        {
            //Destroy(collision.gameObject);
            //FindObjectOfType<GameManager>().AddScore(10); // スコアを加算
            Debug.Log("ブロックに衝突");
        }
        else if (collision.gameObject.CompareTag("Wall_Bottom"))
        {
            /*修正*/

            // ボールを完全停止
            StopBall();

            // 新しいボールを再生成
            GameManager gm = FindObjectOfType<GameManager>();
            if (gm != null)
            {
                gm.SpawnBall();
            }
            else
            {
                Debug.LogError("GameManagerが見つかりません!");
            }
        }
        else if (collision.gameObject.CompareTag("Player"))
        {
            Debug.Log("Playerに衝突");
        }
        else if (collision.gameObject.CompareTag("Wall_LR"))
        {
            Debug.Log("左右の壁に衝突");
         }
    }

    // ボールを完全停止させる処理
    private void StopBall()
    {
        rb.velocity = Vector2.zero;       // 移動速度をゼロにする
        rb.angularVelocity = 0f;          // 回転速度をゼロにする
        rb.isKinematic = true;            // 物理演算を無効化
        GetComponent<Renderer>().enabled = false; // ボールを非表示にする
        Collider2D collider = this.gameObject.GetComponent<Collider2D>();
        if (collider != null)
        {
            collider.enabled = false; // Colliderを無効化
        }
    }

    public void InitializeBall()
    {
        rb = GetComponent<Rigidbody2D>(); // Rigidbody2Dを取得
        rb.isKinematic = false;           // 物理演算を有効化
        rb.velocity = Vector2.zero;       // 移動速度をリセット
        rb.angularVelocity = 0f;          // 回転速度をリセット
        Launch();                         // ボールを発射
    }
}

(3)BallManager
・ボールを登録するメソッドを持ちます。
・ボールの色を変えるメソッドを持ちます。

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

public class BallManager : MonoBehaviour
{
    private GameObject currentBall; // 操作対象のBall
    private Renderer ballRenderer;  // BallのRenderer

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    // Ballを登録する
    public void SetBall(GameObject ball)
    {
        Debug.Log("SetBall()が呼ばれました");
        currentBall = ball;
        ballRenderer = currentBall.GetComponent<Renderer>();

        if (ballRenderer != null)
        {
            ballRenderer.material.shader = Shader.Find("Unlit/Color"); // 必要に応じてシェーダーを設定
            Debug.Log("Shader : "+ballRenderer.material.shader);
            if (ballRenderer.material.shader == null)
                        {
                Debug.Log("Shader 'Standard' が見つかりません。");
            }

            ballRenderer.material.SetFloat("_Mode", 0); // Opaqueに設定
            //ballRenderer.material.color = UnityEngine.Color.white;
            // ライティングの影響を無視して単色に設定
            ballRenderer.material = new Material(Shader.Find("Unlit/Color"));
            UnityEngine.Color color = new UnityEngine.Color(1.0f, 0.0f, 0.0f, 1.0f);
            Debug.Log("色を初期化しました");
        }
        else
        {
            Debug.LogError("操作対象のBallが登録されていません。SetBall()を呼び出してください。");
        }

        if (ballRenderer == null)
        {
            Debug.LogError("Rendererが見つかりません。BallオブジェクトにRendererコンポーネントが付いているか確認してください。");
        }
    }

    // 色を変更する
    public void ChangeColor(UnityEngine.Color color)
    {
        if (ballRenderer != null)
        {
            //ballRenderer.material.shader = Shader.Find("Standard"); // 必要に応じてシェーダーを設定
            //ballRenderer.material.SetFloat("_Mode", 0); // Opaqueに設定

            // ライティングの影響を無視して単色に設定
            ballRenderer.material = new Material(Shader.Find("Unlit/Color"));
            ballRenderer.material.color = color;
            Debug.Log("色を変更しました");
        }
        else
        {
            Debug.LogError("操作対象のBallが登録されていません。SetBall()を呼び出してください。");
        }
    }

}

(4)BlockManager
・ブロック(プレファブ)に赤、黄、青の中からランダムな色を付けて、3行4列で表示します。

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

public class BlockManager : MonoBehaviour
{
    public GameObject blockPrefab; // Blockプレハブ
    public static int rows = 3;           // 行数
    public static int columns = 4;        // 列数
    public float spacingX = 1.0f;  // ブロックの横方向の間隔
    public float spacingY = 1.0f;  // ブロックの縦方向の間隔
    public Vector2 startPosition = new Vector2(-1.5f, 3.5f); // 最初の配置位置

    private Color[] blockColors = { Color.red, Color.yellow, Color.blue }; // 色の選択肢


    // Start is called before the first frame update
    void Start()
    {
        GenerateBlocks();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void GenerateBlocks()
    {
        for (int row = 0; row < rows; row++)
        {
            for (int col = 0; col < columns; col++)
            {
                // 配置位置を計算
                Vector2 position = new Vector2(
                    startPosition.x + col * spacingX,
                    startPosition.y - row * spacingY
                );

                // Blockを生成
                GameObject block = Instantiate(blockPrefab, position, Quaternion.identity);

                // ランダムな色を選択
                Color randomColor = blockColors[Random.Range(0, blockColors.Length)];

                // BlockのRendererを取得して色を設定
                Renderer blockRenderer = block.GetComponent<Renderer>();
                if (blockRenderer != null)
                {
                    blockRenderer.material.color = randomColor;
                }
            }
        }
    }

}

(5)Canvas
 ScoreText スコアのテキスト表示
 BallCounterTexT ボール残り数のテキスト表示

(6)closemark
・「×」ボタンが押されたら、アプリケーションを終了します。

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

public class GameQuitHandler : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private void OnMouseDown()
    {
        Debug.Log("Game Quit");
        AndroidJavaClass version = new AndroidJavaClass("android.os.Build$VERSION");
        int apiLevel = version.GetStatic<int>("SDK_INT");

        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

        if (apiLevel >= 21)
        {
            activity.Call("finishAndRemoveTask");
        }
        else
        {
            activity.Call("finish");
        }
    }
}

(7)Red1,Yellow1,Blue1,Right1,Left1
・各々の色ボタンが押されたら、BallManagerのChangeColor()メソッドを呼び出して、ボールの色を変えます。

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

public class OnMouse_Red : MonoBehaviour
{
    //public GameObject targetObject; // 色を変える対象オブジェクト

    private Color buttonColor; // ボタンの色

    // Start is called before the first frame update
    void Start()
    {
        // ボタンの色を直接 blue に設定
        buttonColor = Color.red;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void OnMouseDown()
    {
        Debug.Log("Redボタンが押されました");

        // BallManagerを取得して色を変更
        BallManager manager = FindObjectOfType<BallManager>();
        if (manager != null)
        {
            Debug.Log("Ball Manager 取得");
            
            manager.ChangeColor(buttonColor);
        }

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

public class OnMouse_Yellow : MonoBehaviour
{
    //public GameObject targetObject; // 色を変える対象オブジェクト
    private Color buttonColor; // ボタンの色(Inspectorで設定可能)


    // Start is called before the first frame update
    void Start()
    {
        // ボタンの色を直接 blue に設定
        buttonColor = Color.yellow;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void OnMouseDown()
    {
        Debug.Log("Yellowボタンが押されました");

        // BallManagerを取得して色を変更
        BallManager manager = FindObjectOfType<BallManager>();
        if (manager != null)
        {
            Debug.Log("Ball Manager 取得");
            manager.ChangeColor(buttonColor);
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OnMouse_Blue : MonoBehaviour
{
    //public GameObject targetObject; // 色を変える対象オブジェクト
    // Start is called before the first frame update
    private Color buttonColor; // ボタンの色

    void Start()
    {
        // ボタンの色を直接 blue に設定
        buttonColor = Color.blue;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void OnMouseDown()
    {
        Debug.Log("Blueボタンが押されました");

        // BallManagerを取得して色を変更
        BallManager manager = FindObjectOfType<BallManager>();
        if (manager != null)
        {
            Debug.Log("Ball Manager 取得");
            manager.ChangeColor(buttonColor);
        }

    }
}

・右矢印ボタンが押されたら、プレイヤーを右に移動するメソッドを呼び出します。

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

public class OnMouse_Right : MonoBehaviour
{
    public GameObject targetObject; // 動かす対象オブジェクト

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void OnMouseDown()
    {
        Debug.Log("右ボタンが押されました");
        // 動かすオブジェクトのスクリプトを取得してメソッドを呼び出す
        Player moveScript = targetObject.GetComponent<Player>();
        if (moveScript != null)
        {
            moveScript.MoveRight(); // 移動開始
        }
    }

}

・左矢印ボタンが押されたら、プレイヤーを左に移動するメソッドを呼び出します。

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

public class OnMouseDown_Left : MonoBehaviour
{
    public GameObject targetObject; // 動かす対象オブジェクト

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void OnMouseDown()
    {
        Debug.Log("左ボタンが押されました");
        // 動かすオブジェクトのスクリプトを取得してメソッドを呼び出す
        Player moveScript = targetObject.GetComponent<Player>();
        if (moveScript != null)
        {
            moveScript.MoveLeft(); // 移動開始
        }
    }
}

(8)Wall_B,Wall_L,Wall_R,Wall_T
 スクリプトは無し、BoxCollider2Dコンポーネントを追加

(9)Play
・プレイヤーを右、又は左に移動するメソッドを持ちます。

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

public class Player : MonoBehaviour
{
    private Rigidbody2D myRigidBody;
    public float playerSpeed = 10;
    private bool canMoveLeft = true;
    private bool canMoveRight = true;

    // Start is called before the first frame update
    void Start()
    {
        myRigidBody = this.gameObject.GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {

    }

    void FixedUpdate()
    {
        // 横方向の速度を強制的に0に設定
        Vector2 velocity = myRigidBody.velocity;
        velocity.x = 0;
        myRigidBody.velocity = velocity;
    }

    // 左方向に移動
    public void MoveLeft()
    {
        if(canMoveLeft) Move(Vector2.left);
    }
    // 右方向に移動
    public void MoveRight()
    {
        if(canMoveRight) Move(Vector2.right);
    }
    // 移動処理
    private void Move(Vector2 direction)
    {
        Vector2 newPosition = myRigidBody.position + direction * playerSpeed * Time.deltaTime;
        myRigidBody.MovePosition(newPosition);
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Wall_Left"))
        {
            canMoveLeft = false;
        }
        else if (collision.gameObject.CompareTag("Wall_Right"))
        {
            canMoveRight = false;
        }
    }

    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Wall_Left"))
        {
            canMoveLeft = true;
        }
        else if (collision.gameObject.CompareTag("Wall_Right"))
        {
            canMoveRight = true;
        }
    }
}

2.3 GameGoalScene

(1)close
・「CLOSE」ボタンが押されたら、アプリケーションを終了します。

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

public class GameQuitHandler : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private void OnMouseDown()
    {
        Debug.Log("Game Quit");
        AndroidJavaClass version = new AndroidJavaClass("android.os.Build$VERSION");
        int apiLevel = version.GetStatic<int>("SDK_INT");

        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

        if (apiLevel >= 21)
        {
            activity.Call("finishAndRemoveTask");
        }
        else
        {
            activity.Call("finish");
        }
    }
}

(2)restart
・「START」ボタンが押されたら、GameSceneのシーンに切り替えます。

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

public class StartIconHandler : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    private void OnMouseDown()
    {
        Debug.Log("Game Start");
        // ゲーム画面に切り換え
        GameManager.score = 0;
        SceneManager.LoadScene("GameScene"); // ゲームシーンに移動
    }
}

2.4 GameOverScene

(1)GameOverManager
・GameManagerオブジェクトの静的変数scoreを取得して表示します。

(2)Canvas
・Textエリアにスコアを表示します。

(3)restart
・「START」ボタンが押されたら、GameSceneのシーンに切り替えます。

・スクリプトファイルは、前記2.3項(2)に同じです。

(4)close
・「CLOSE」ボタンが押されたら、アプリケーションを終了します。

・スクリプトファイルは、前記2.3項(1)に同じです。

3.ビルド
 WebGLオプションのビルド方法については本サイト内の下記の記事を参照してください。

https://region-sys.com/webブラウザで実行するための方法/

End

タイトルとURLをコピーしました