内容
UNITYで3Dブロック崩しゲームを作ってみた
ユーチューブの動画を見ながらUnityでシンプルな3Dブロックくずし(簡易版)を作ってみました。
丁寧に解説された動画なのでわかりやすいです。少しだけ、Unityのバージョンが違うせいか、設定が違っていたりしますが、コード自体は問題なさそうです。
/Documents/新書類/UnityProgram/block_break_out/
製作中は、シーンにブロックを入れて整列させてから、Prefabにしています。
なので、製作中と完成形ではHierarchyヒエラルキーの並びが異なります。
実際のゲームは、スペースで開始、矢印キーの左右でバーが左右に動きます。
WEBGLを使用しています。おそらくFirefoxとサファリで動くと思います。
プラグインが必要になります。
WEBGLの場合はプラグインは不要みたいですが、ブラウザがWEBGLに対応していない場合は、実行できません。
https://unity3d.com/jp/webplayer
https://docs.unity3d.com/jp/530/Manual/class-PlayerSettingsWeb.html
https://docs.unity3d.com/jp/530/Manual/UsingWebPlayertemplates.html
ブロック崩しこちらで遊べます
1面しかありません。音もないのでちょっと寂しい感じです。
こちらのリンクをクリックして下さい。スペースキーと左右の矢印キーで操作します。
http://pikucha.sakura.ne.jp/unity/block_break_out.html
・参考にしたユーチューブ動画
Live Training Jan. 5th 2015: Creating a Breakout Game for Beginners
ソースコード
C#
一部変更して、ブログの此方側を更新していないことがあります。
paddle.cs(バー)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Paddle : MonoBehaviour { public float paddleSpeed = 1f; public Vector3 playerPos = new Vector3(0,-9.5f,0); private Ray ray ; private RaycastHit rayCastHit ; // Update is called once per frame void Update () { /* 矢印キーで左右に float xPos = transform.position.x + (Input.GetAxis("Horizontal")*paddleSpeed); playerPos = new Vector3(Mathf.Clamp(xPos,-9f,9f),-9.5f,0f); transform.position = playerPos; */ //マウスに追随する場合はこちら //if(Input.GetMouseButton(0)){ ray=Camera.main.ScreenPointToRay(Input.mousePosition); if(Physics.Raycast(ray,out rayCastHit)){ //transform.position=rayCastHit.point; playerPos = new Vector3(Mathf.Clamp(rayCastHit.point.x,-9f,9f),-9.5f,0f); transform.position = playerPos; } //} /* こっちははだめ 全然動かない //マウスのx,y座標を取得 Vector3 vecMouse = Input.mousePosition; //ワールド座標に変換 Vector3 screenPos = Camera.main.ScreenToWorldPoint(vecMouse); //オブジェクトに代入 x only //playerPos = new Vector3(Mathf.Clamp(screenPos.x,-9f,9f),-9.5f,0f); //transform.position = playerPos; transform.position = screenPos; */ } } |
ball.cs ボール
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Ball : MonoBehaviour { public float ballInitialVelocity = 600f; public Rigidbody rb; private bool ballInPlay; void Awake(){ rb = GetComponent<Rigidbody> (); } // Update is called once per frame void Update () { /* if (Input.GetKeyDown("space")) ,Input.GetButtonDown ("Fire1") is mouse */ if (Input.GetKeyDown ("space") && ballInPlay == false) { transform.parent = null; ballInPlay = true; rb.isKinematic = false; //ボールのベクトル rb.AddForce (new Vector3 (ballInitialVelocity, ballInitialVelocity, 0)); } } } |
GM.cs全体管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; //この段階で、GMオブジェクトにかぶせてもエラーになる。Bricks.csを作ってから設定が必要みたい。 public class GM : MonoBehaviour { public int lives = 3; public int bricks = 20; public float resetDelay = 1f; public Text livesText; public GameObject gameOver; public GameObject youWon; public GameObject bricksPrefab; public GameObject paddle; public GameObject deathParticles; public static GM instance = null; private GameObject clonePaddle; // Use this for initialization void Awake () {//Start () if (instance == null) instance = this; else if (instance != this) Destroy (gameObject); Setup (); } public void Setup(){ clonePaddle = Instantiate (paddle, transform.position, Quaternion.identity) as GameObject; Instantiate (bricksPrefab, transform.position, Quaternion.identity); } void CheckGameOver(){ if (bricks < 1) { youWon.SetActive (true);//hide to appear Time.timeScale = .25f; Invoke ("Reset", resetDelay); } if (lives < 1) { gameOver.SetActive (true); Time.timeScale = .25f; Invoke ("Reset", resetDelay); } } void Reset(){ Time.timeScale = 1f; SceneManager.LoadScene ("level1");//※変わったらしい。Application.LoadScene ("level1"); } public void LoseLife(){ lives--; livesText.text = "Lives: " + lives; Instantiate (deathParticles, clonePaddle.transform.position, Quaternion.identity); Destroy (clonePaddle); Invoke ("SetupPaddle", resetDelay); CheckGameOver (); } void SetupPaddle(){ clonePaddle = Instantiate (paddle, transform.position, Quaternion.identity) as GameObject; } public void DestroyBricks(){ bricks--; CheckGameOver (); } // Update is called once per frame void Update () { } } |
bricks.csブロック
1 2 3 4 5 6 7 8 9 10 11 12 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bricks : MonoBehaviour { public GameObject brickParticle; void OnCollisionEnter(Collision other){ Instantiate (brickParticle, transform.position, Quaternion.identity); GM.instance.DestroyBricks (); Destroy (gameObject); } } |
DeadZone.cs ミス用の設定
1 2 3 4 5 6 7 8 9 10 11 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DeadZone : MonoBehaviour { void OnTriggerEnter(){ GM.instance.LoseLife (); } } |
TimedDestroy.csパーティクルの削除、あってもなくても良さそうなスクリプト
1 2 3 4 5 6 7 8 9 10 11 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TimedDestroy : MonoBehaviour { public float destroyTime = 1f; // Use this for initialization void Start () { Destroy (gameObject, destroyTime); } } |
画面
waterという名称だけど、ボールが接触したかどうかを判定するためのオブジェクト