← 記事一覧に戻る

ブロック崩し3

ブロック崩し3

ブロック崩し2のプロジェクトを変更する形にする
→フォルダコピーしてリネーム、UnityHubから追加してみる
以降は課題にする

課題の解説後、メリットを説明
Start/Awakeをいたるところで書くと、どこで何が起きているか見つけにくくなる
→仕様変更やバグ修正が大変

GameManagerに集約することで、GameManagerを見ればゲームの全体像がわかるようになる
→これはプロの現場ではよくやる手法

スクリプト

StageGenerator.cs

csharp
1using UnityEngine; 2 3public class StageGenerator : MonoBehaviour 4{ 5 [SerializeField] private GameObject block; 6 [SerializeField] private GameObject coin; 7 [SerializeField] private int marginX; 8 [SerializeField] private int marginY; 9 [SerializeField] private int row; 10 [SerializeField] private int column; 11 12 // Start is called once before the first execution of Update after the MonoBehaviour is created 13 public void Initialize(out int blockCount) 14 { 15 blockCount = 0; 16 var basePosition = transform.position; 17 for (int i = 0; i < row; i++) 18 { 19 int coinNumber = Random.Range(0, row); 20 for (int j = 0; j < column; j++) 21 { 22 Vector3 pos = basePosition + new Vector3(j * marginX, -i * marginY, 0); 23 if (j == coinNumber) 24 { 25 Instantiate(coin, pos, Quaternion.identity); 26 } 27 else 28 { 29 Instantiate(block, pos, Quaternion.identity); 30 blockCount++; 31 } 32 } 33 } 34 } 35 36 // Update is called once per frame 37 void Update() 38 { 39 40 } 41}

BallState.cs
csharp
1public enum BallState 2{ 3 Idle, 4 Flying 5}

Ball.cs
csharp
1using System; 2using UnityEngine; 3using UnityEngine.InputSystem; 4 5public class Ball : MonoBehaviour 6{ 7 public Action<GameObject> OnCollision; 8 public BallState State => state; 9 10 [SerializeField] private float launchSpeed = 8f; 11 [SerializeField] private Rigidbody2D rigidbody2d; 12 13 private BallState state = BallState.Idle; 14 15 void Update() 16 { 17 if (state != BallState.Idle) return; 18 19 Pointer pointer = Pointer.current; 20 if (pointer == null || !pointer.press.wasPressedThisFrame) return; 21 22 Vector2 screenPos = pointer.position.ReadValue(); 23 Vector3 worldPos = Camera.main.ScreenToWorldPoint( 24 new Vector3(screenPos.x, screenPos.y, -Camera.main.transform.position.z)); 25 26 Vector2 dir = ((Vector2)worldPos - (Vector2)transform.position).normalized; 27 rigidbody2d.linearVelocity = dir * launchSpeed; 28 state = BallState.Flying; 29 } 30 31 void OnCollisionEnter2D(Collision2D collision) 32 { 33 OnCollision?.Invoke(collision.gameObject); 34 } 35 36 void OnTriggerEnter2D(Collider2D other) 37 { 38 OnCollision?.Invoke(other.gameObject); 39 } 40 41 public void Stop() 42 { 43 if (state != BallState.Flying) return; 44 rigidbody2d.linearVelocity = Vector2.zero; 45 state = BallState.Idle; 46 } 47}

GameManager
csharp
1using UnityEngine; 2using TMPro; 3 4public class GameManager : MonoBehaviour 5{ 6 [SerializeField] private Ball ball; 7 [SerializeField] private GameObject clearUIPanel; 8 [SerializeField] private StageGenerator stageGenerator; 9 [SerializeField] private TextMeshProUGUI scoreText; 10 11 private int remainingBlocks; 12 private int score; 13 14 void Start() 15 { 16 clearUIPanel.SetActive(false); 17 stageGenerator.Initialize(out remainingBlocks); 18 19 ball.OnCollision += CollisionBall; 20 scoreText.text = "Score: " + score; 21 } 22 23 private void CollisionBall(GameObject other) 24 { 25 switch (other.tag) 26 { 27 case "Block": 28 BlockCollision(other); 29 return; 30 case "Floor": 31 FloorCollision(); 32 return; 33 case "Coin": 34 CoinCollision(other); 35 return; 36 } 37 } 38 39 private void BlockCollision(GameObject block) 40 { 41 Destroy(block); 42 remainingBlocks--; 43 if (remainingBlocks <= 0) 44 { 45 clearUIPanel.SetActive(true); 46 } 47 } 48 49 private void FloorCollision() 50 { 51 ball.Stop(); 52 } 53 54 private void CoinCollision(GameObject coin) 55 { 56 Destroy(coin); 57 score++; 58 scoreText.text = "Score: " + score; 59 } 60}