第2回Unity勉強会
はじめに
こんにちは、seikaです!
今回と第3回の2週で「ブロック崩し」を作成していきます!
第1回で学んだことを使いながら一つずつ進めていきましょう!
👇第1回の記事はこちら👇
目次
- 事前条件
- 今回の環境
- 今回作るもの
- シーンを作る
- Playerを作る
- Ballを作る
- WallRootを作る
- 壁を作る
- BackWallを作る
- BlockRootを作る
- Blockを作る
- Materialを作る
- ブロックを並べる
- PlayerとBallとWallにも色をつける
- カメラを調整する
- Playerを操作できるようにする
- Ballを動かす
- Physics Materialで跳ね返るようにする
- 実行して確認する
- 今回のまとめ
- 次回やること
- あとがき
事前条件
- Unity, エディタ(Rider以外でも可能)のインストールが終了している
- Object指向を多少理解している(継承, interface など)
- 第1回の内容を知っている
今回の環境
この記事では以下の環境で解説していきます。
- Windows 11
- Unity 6.3 LTS (6000.3.17f1)
- Rider 2026.1.3 (エディタ)
第1回とは OS が違いますが、やることは同じです!
今回作るもの
今回はブロック崩しの土台を作ります。
まだブロックは崩れません。タイトル詐欺に見えるかもしれませんが、物事には順序があります。
完成品としては、画面内にPlayer、Ball、Wall、Blockがあり、A, DキーでPlayerを左右に動かせて、Ballが壁やPlayerに当たって跳ね返るところまで作ります。
ブロックを壊す処理、ゲームクリア、ゲームオーバー、リトライなどは第3回で作ります。
というわけで、落ち着いて一個ずつ作っていきましょう。
プロジェクトを作る
第1回で作成したプロジェクトをそのまま使います!
Unity Hub を開くと、前回作った UnityTest (名前は自由にしたはずなので違うかも)みたいなプロジェクトがあると思うので、それを開きます。
シーンを作る
まずは今回使う Scene を作ります。
Project タブの Assets の中に Scenes フォルダがあるので、Scenes フォルダ上で右クリック。
Create -> Scene -> Scene を選択します。
作成できたSceneの名前を
BreakoutScene
に変更してください。
名前を変更できたら、BreakoutScene をダブルクリックして開きます。
これで今回作業する舞台が用意できました。
いきなりですが、ここで一旦保存しておきましょう。
Ctrl + S
大事です。
保存しよう。
Playerを作る
まずはPlayerを作ります。ブロック崩しで下にある棒ですね。
Hierarchy で右クリック。3D Object -> Cube を選択します。
Cubeが作成されたら、名前を
Player
に変更します。
次に Transform を変更します。
今回は以下の値にしておきます。
Position
X: 0
Y: -5
Z: 0
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 3
Y: 0.3
Z: 0.5
これで横長の棒になります。
もし Scene ビューで見づらい場合は、Playerを選択した状態で F キーを押すと、選択中の GO が画面の中央に来ます。
GameObject のことを省略して GO と呼ぶことが多いです!
また、勉強会で言及はしませんが、ScriptableObject は SO と呼ぶことが多いです。気になった人は調べてみてね。
第1回でも出てきましたね。
Player ができたら、Inspector の上側を見てみると Tag という項目があると思います。ここを Player と選択しておきましょう。
次に、Inspector から Add Component を押して Rigidbody を追加します。
Rigidbody を追加したら、以下のように設定します。
Use Gravity: OFF
Constraints:
Freeze Position Y: ON
Freeze Position Z: ON
Freeze Rotation X: ON
Freeze Rotation Y: ON
Freeze Rotation Z: ON
Use Gravity がONだと、Playerは重力で下に落ちます。棒が落下したらテトリスになってしまうので OFF にします。
また、Playerは左右にだけ動いてほしいので、Y方向とZ方向の移動を止めます。回転もいりません。
まあ別に回転しても面白いが……。
Ballを作る
次にBallを作ります。
Hierarchy で右クリックしてください。
3D Object -> Sphere を選択します。
Sphereが作成されたら、名前を
Ball
に変更します。
次に Transform を変更します。
Scaleの横にあるリンクボタンを押すと、X, Y, Zをまとめて変更できます。
今回は以下の値にします。
Position
X: 0
Y: -4.3
Z: 0
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 0.4
Y: 0.4
Z: 0.4
これで Player の少し上に Ball が配置されます。
次に、Ballにも Rigidbody を追加して、以下のように設定します。
Use Gravity: OFF
Collision Detection: Continuous Dynamic
Constraints:
Freeze Position Z: ON
Ball も重力で落ちてほしくないので、Use Gravity は OFF です。
Ball はXY方向に動いて、Z方向には動いてほしくないので Freeze Position Z をONにします。
Collision Detection は Continuous Dynamic にしておきます。
Ball はそこそこ速く動くので、通常の設定だと薄い壁をすり抜けることがあります。
今回のような速度なら大丈夫だと思いますが、事故が起きない設定にしておきましょう。
WallRootを作る
次に、壁をまとめるための GO を作ります。
Hierarchy で右クリックして、Create Empty を選択します。
作成された GO の名前を
WallRoot
に変更します。
WallRoot は空の GO なので Scene ビューには何も表示されませんが、存在はしています。
今回の WallRoot は、壁をまとめるための箱みたいなものです。
この中に RightWall, LeftWall, TopWall, BottomWall, BackWall を入れていきます。
こうしておくと、Hierarchy が見やすくなります。
Hierarchy が散らかると、3日後の自分が「誰だこんな構成にしたやつ」と言い出します。犯人は自分です。
壁を作る
まず WallRoot の子として作りたいので、Hierarchy の WallRoot で右クリックして、3D Object -> Cube を選択します。
作成された Cube の名前を
RightWall
に変更します。
Transform は以下の値にします。
Position
X: 8
Y: 0
Z: 0
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 0.3
Y: 11
Z: 0.5
これで右側の壁ができます。
次に左側の壁を作ります。
RightWall を選択して、Ctrl + D で複製します。
複製された GO の名前を
LeftWall
に変更します。
Transform は以下のようにします。
Position
X: -8
Y: 0
Z: 0
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 0.3
Y: 11
Z: 0.5
違うのはX座標だけです。
次に上の壁を作ります。
RightWall か LeftWall を選択して、Ctrl + D で複製します。
名前を
TopWall
に変更します。
Transform は以下の値にします。
Position
X: 0
Y: 5.5
Z: 0
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 16
Y: 0.3
Z: 0.5
これで上の壁ができます。
最後に下の壁を作ります。
TopWall を選択して、Ctrl + D で複製します。
名前を
BottomWall
に変更します。
Transform は以下の値にします。
Position
X: 0
Y: -5.5
Z: 0
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 16
Y: 0.3
Z: 0.5
これで上下左右の壁ができました。
ブロック崩しでは普通、下に落ちたらゲームオーバーです。
ですが、今回はまだゲームオーバー処理を作らないので、下にも仮の壁を置いておきます。
第3回でこの下の壁は別の役割に変更します。
今は「Ballがどこかへ消えないための仮置き」と思ってください。
ここまでできたら一旦保存しましょう。
Ctrl + S
これは命綱です。
BackWallを作る
次に BackWall を作ります。
これはゲームの背景になる壁です。なくても構いませんが、ないと寂しい。
BottomWall を選択して、Ctrl + D で複製してください。
名前を
BackWall
に変更します。
Transform は以下の値にします。
Position
X: 0
Y: 0
Z: 0.5
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 16
Y: 10
Z: 0.5
これで奥に壁ができます。
もしBallやPlayerが隠れて見えなくなった場合は、Z座標の前後関係が逆になっている可能性があります。
BlockRootを作る
次にブロックをまとめるための GO を作ります。
Hierarchy で右クリックして、Create Empty を選択します。
作成された GO の名前を
BlockRoot
に変更します。
BlockRoot も WallRoot と同じで、ブロックをまとめるための空の GO です。
この中にたくさんの Block を入れていきます。
Blockを作る
ではブロックを1個作ります。
Hierarchy で右クリックして、3D Object -> Cube を選択します。
作成されたCubeの名前を
Block
に変更します。
Transform は以下の値にします。
Position
X: -5
Y: 4
Z: 0
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 1.5
Y: 0.4
Z: 0.5
横長のブロックになったと思います。
作成した Block を BlockRoot にドラッグ&ドロップしてください。
これで BlockRoot の子オブジェクトになります。
Materialを作る
次は色を付けます。
第1回でも出てきましたが、見た目を変更するには Material を使います。
まず Project タブで Assets を開いてください。
右クリックして Create -> Folder を選択します。
作成したフォルダーの名前を
Materials
に変更します。
この Materials フォルダーの中に、今回使うMaterialを作っていきます。
Materials フォルダーを開いて、右クリックします。
Create -> Material を選択してください。
作成されたMaterialの名前を
Red
に変更します。
Red を選択するとInspectorにMaterialの設定が表示されます。
Surface Inputs の中にある Base Map の色を赤にしてください。
これで赤色のMaterialができました。
同じ手順で、以下のMaterialも作ります。
Blue
Green
PlayerMaterial
BallMaterial
WallMaterial
BackWallMaterial
色は自由で大丈夫ですが、BackWallMaterial は暗めの色にしておくと、BallやBlockが見やすくなります。
デザインってこういうこと。たぶん。
ブロックを並べたい
まず、さっき作った Block に色を付けます。
Block のInspectorの Mesh Renderer を見ます。
Materials の中に Element 0 という項目があると思います。
そこにMaterialをドラッグ&ドロップします。
ブロックが赤くなれば成功です。
ここで、ブロックを並べる前にPrefabにしておきましょう。こうすると後から編集するときに楽ができます。
Project タブで Assets を開き、右クリックして Create -> Folder を選択します。
名前は
Prefabs
にします。
そして、Hierarchy 上のブロックを Prefabs にドラッグ&ドロップします。
アイコンが青い立方体になれば成功です。
次に、Block を複製して横1列に並べます。
Block を選択して、Ctrl + D で複製してください。
複製したブロックのX座標を変更します。シーン上で Ctrl + ドラッグするときれいに動かせます。
1列できたら、2列目を作っていきましょう。
左端のやつを複製して、一つ下に持ってきます。ついでに Material も Blue にしますか。
これも Prefab として保存したいですよね。ドラッグ&ドロップで Prefab フォルダに持っていきます。
すると……?
なんか警告みたいなのが出てきましたね。心配しないでください。これはエラーではありません。
「Prefab Variant にしますか?」と聞かれています。
Prefab Variant とは、Prefab の中のテンプレート機能みたいなものです。
今回は Prefab Variant にしたいので、真ん中の「Prefab Variant」を選択します。
すると、Prefabs フォルダに Block Variant が生成されます。分かりやすいように BlueBlock とリネームしておきましょう。
また、Prefab の Block 上で右クリックして Create -> Prefab Variant からも作ることができます。
もう一つ作っておきましょう。名前は Green にして Material を Green に変更します。
ではブロックを並べていきますよ。
2列目は Blue を置いて、Y座標を 4 にしてみますか。
3列目は Green を置いて、Y座標を 3 に。
最終的に、赤、青、緑の3列ができればOKです。
ここまでできたら一旦保存しましょう。
Ctrl + S
もう聞き飽きたかもしれませんが、聞き飽きるくらいでちょうどいいのさ。
PlayerとBallとWallにも色をつける
ブロックだけ色がついていて、PlayerやWallが灰色のままだと少し寂しいので、他の GO にもMaterialを設定します。
Player を選択して、Mesh Renderer の Materials に PlayerMaterial をドラッグ&ドロップしてください。
Ball を選択して、同じように BallMaterial を設定します。
RightWall, LeftWall, TopWall, BottomWall には WallMaterial を設定します。
BackWall には BackWallMaterial を設定します。
Wallの色は好きに作ってみてください。
カメラを調整する
このままだとGameビューで見づらいかもしれません。
ということで、カメラを調整します。最初にやっても良かったかもねこれ。過去の私に言ってください。
Hierarchy から Main Camera を選択してください。
Transform を以下の値にします。
Position
X: 0
Y: 0
Z: -10
Rotation
X: 0
Y: 0
Z: 0
Scale
X: 1
Y: 1
Z: 1
次に、Cameraコンポーネントの設定を変更します。
Projection: Orthographic
Size: 6
なんか画面が平べったくなりましたね。
Projection を Orthographic にすると、遠近感のない表示になります。
Size はカメラに映る範囲です。
今回のステージだと 6 くらいにしておくと全体が見えると思います。
もし見切れている場合は、Size を少し大きくしてください。
Playerを操作できるようにする
ここからScriptを書いていきます。
まず Project タブで Assets を開いてください。
右クリックして Create -> Folder を選択します。
フォルダー名を
Scripts
に変更してください。
Scripts フォルダーを開きます。
右クリックして Create -> MonoBehaviour Script を選択します。
作成されたScriptの名前を
Player
にしてください。
名前を変更したら、ダブルクリックしてエディタで開きます。
最初に入っている英語のコメントは消して大丈夫です。
コードを以下のように変更してください。
using UnityEngine;
using UnityEngine.InputSystem;
public class Player : MonoBehaviour
{
[SerializeField] private Rigidbody _rb;
[SerializeField] private float _moveSpeed = 10f;
private void Reset()
{
_rb = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
float x = 0f;
if (Keyboard.current.aKey.isPressed)
{
x = -1f;
}
else if (Keyboard.current.dKey.isPressed)
{
x = 1f;
}
_rb.linearVelocity = new Vector3(x * _moveSpeed, 0f, 0f);
}
}
さて、少し中身を見ていきましょう。
using UnityEngine.InputSystem;
これはNew Input Systemを使うために必要です。
第1回でも Keyboard.current が出てきましたね。
今回も同じようにキーボード入力を受け取ります。
[SerializeField] private Rigidbody _rb;
[SerializeField] private float _moveSpeed = 10f;
SerializeField を付けることで、private の変数でもInspectorから設定できます。
_rb にはPlayerの Rigidbody を入れます。
_moveSpeed はPlayerの移動速度です。
private void Reset()
{
_rb = GetComponent<Rigidbody>();
}
Reset() は、このScriptを GO に追加した時などに呼ばれます。
ここでは、同じ GO に付いている Rigidbody を自動で取得しています。
private void FixedUpdate()
FixedUpdate() は物理演算のタイミングで呼ばれます。
今回は Rigidbody を使って動かすので、Update() ではなく FixedUpdate() に書きます。
Update() は毎フレーム呼ばれますが、物理演算とはタイミングが違います。
if (Keyboard.current.aKey.isPressed)
{
x = -1f;
}
else if (Keyboard.current.dKey.isPressed)
{
x = 1f;
}
Aで左、Dで右。人類はついに棒を左右に動かす力を手にしました。
最後に、
_rb.linearVelocity = new Vector3(x * _moveSpeed, 0f, 0f);
ここでPlayerの速度を設定しています。
linearVelocity は移動量ではなく速度なので、位置を直接動かす場合と違ってTime.deltaTime をかけません。第一回のコードと比較してみてください。
コードが書けたらUnityに戻ります。
少し待つとUnity側でコンパイルが走ります。
Consoleに赤いエラーが出ていなければOKです。
次に、Player GO に Player Scriptをドラッグ&ドロップで貼り付けます。
Inspectorを確認してください。
Player Scriptの中に
Rb
Move Speed
が表示されているはずです。
Rb にPlayerの Rigidbody を入れます。
自動で入っていればそのままで大丈夫です。
入っていなければ、Playerの Rigidbody コンポーネントをドラッグして入れてください。
Move Speed はとりあえず 10 にしておきます。適当です。
ここまでできたら実行してみましょう。
画面中央上部の▶再生ボタンを押します。
AキーとDキーでPlayerが左右に動けば成功です。
動かない場合は、以下を確認してください。
Player GO にPlayer Scriptが付いているか
Player ScriptのRbにRigidbodyが入っているか
PlayerにRigidbodyが付いているか
Use GravityがOFFになっているか
Consoleにエラーが出ていないか
特にConsoleの赤いエラーは無視しないでください。
Unityが読めと言っています。無視したら可哀想。
だけどたまに意味不明なのあるし……しょっちゅう無視してるなんて教える側としては言えないし……なんて言ってたら日が暮れる。
Ballを動かす
次にBallを動かします。
Scripts フォルダーを開いてください。
右クリックして Create -> MonoBehaviour Script を選択します。
作成されたScriptの名前を
Ball
にしてください。
ダブルクリックして開きます。
コードを以下のように変更してください。
using UnityEngine;
public class Ball : MonoBehaviour
{
[SerializeField] private Rigidbody _rb;
[SerializeField] private float _moveSpeed = 7f;
private void Reset()
{
_rb = GetComponent<Rigidbody>();
}
private void Start()
{
Vector3 direction = new Vector3(1f, 1f, 0f).normalized;
_rb.linearVelocity = direction * _moveSpeed;
}
private void FixedUpdate()
{
if (_rb.linearVelocity.sqrMagnitude > 0)
{
_rb.linearVelocity = _rb.linearVelocity.normalized * _moveSpeed;
}
}
private void OnCollisionEnter(Collision collision)
{
if (!collision.gameObject.CompareTag("Player")) return;
Vector3 direction = (collision.gameObject.transform.position - transform.position).normalized;
_rb.linearVelocity = -direction * _moveSpeed;
}
}
今回のBallは、ゲーム開始時に右上方向へぶっ飛んでいくようにします。
Vector3 direction = new Vector3(1f, 1f, 0f).normalized;
これはBallが飛んでいく方向です。向きだけ取り出したいので、.normalized を付けてベクトルを正規化しています。
_rb.linearVelocity = direction * _moveSpeed;
ここでBallの速度を設定しています。
direction が方向、_moveSpeed が速さです。
private void FixedUpdate()
{
if (_rb.linearVelocity.sqrMagnitude > 0)
{
_rb.linearVelocity = _rb.linearVelocity.normalized * _moveSpeed;
}
}
ここではBallの速さを一定にしています。
物理演算で跳ね返ると、誤差や環境などによって少しずつ速度が変わることがあります。
今回はブロック崩しなので、Ballの速度が勝手にどんどん遅くなったり速くなったりすると困ります。まあそれはそれで面白そうですがね。
linearVelocity の大きさが0の時だけは、正規化すると変なことになる可能性があるので、sqrMagnitude > 0 で確認しています。
private void OnCollisionEnter(Collision collision)
{
if (!collision.gameObject.CompareTag("Player")) return;
Vector3 direction = (collision.gameObject.transform.position - transform.position).normalized;
_rb.linearVelocity = -direction * _moveSpeed;
}
ここでは、衝突時にどの方向へ飛んでいくかを計算しています。
private void OnCollisionEnter(Collision collision)
これは、Ball が何かにぶつかったときに実行されるメソッドです。
if (!collision.gameObject.CompareTag("Player")) return;
ここで、当たった相手が何なのかを判定しています。Tag というものを比較して、それが Player でなければこのメソッドを早期に抜けます。つまり、これ以降のコードは実行されません。
これを「早期リターン」と言ったりします。
if (collision.gameObject.CompareTag("Player"))
{
Vector3 direction = (collision.gameObject.transform.position - transform.position).normalized;
_rb.linearVelocity = -direction * _moveSpeed;
}
このようにも書くことはできますが、ネストが深くなって読みにくいコードになるので、暇なときは早期リターンしておきましょう。
Vector3 direction = (transform.position - collision.gameObject.transform.position).normalized;
_rb.linearVelocity = direction * _moveSpeed;
板の中心座標からボールの座標へのベクトル(正規化) × 速度 でボールの跳ね返り方向を計算しています。
コードが書けたらUnityに戻ります。
Consoleに赤いエラーが出ていないか確認してください。
問題なければ、Ball GO に Ball Scriptをドラッグ&ドロップで貼り付けます。
Inspectorで Rb にBallの Rigidbody が入っているか確認してください。
Move Speed はとりあえず 7 にしておきます。
ここまでできたら再生してみましょう。
Ballが右上へ動き出せば成功です。
人類はついに球を右上に飛ばす力を手にしました。文明の進歩です。
ただし、まだこの時点ではうまく跳ね返らないかもしれません。
次に跳ね返り用の設定をしていきます。
Physics Materialで跳ね返るようにする
Ballが壁やPlayerに当たって跳ね返るようにするために、Physics Material を作ります。
見た目の色を変える Material とは別物です。
名前が似ていますが、役割は違います。
普通の Material は見た目担当です。服です。
Physics Material は物理担当です。性格です。
今回作る予定の Physics Material は、摩擦ゼロで反発最大。かなり陽気な性格をしています。
Project タブで Assets を開きます。
右クリックして Create -> Folder を選択します。
フォルダー名を
PhysicsMaterials
にしてください。
PhysicsMaterials フォルダーを開きます。
右クリックして Create -> Physics Material を選択します。下の方にありますね。
作成されたPhysics Materialの名前を
Bouncy
に変更します。Vaundyじゃないよ。
Bouncy を選択して、Inspectorで以下のように設定してください。
Dynamic Friction: 0
Static Friction: 0
Bounciness: 1
Friction Combine: Minimum
Bounce Combine: Maximum
摩擦を0にして、跳ね返りを1にしています。めっちゃツルツルでめっちゃボヨンボヨンなボールになりますね。
次に、この Bouncy をColliderに設定します。
Ball を選択して Inspectorの Sphere Collider を見ます。
Material という項目があるので、そこに Bouncy をドラッグ&ドロップします。
実行して確認する
ここまでできたら、実行して確認します。
確認することは以下です。
AキーでPlayerが左に動く
DキーでPlayerが右に動く
Ballが右上方向に動き出す
Ballが壁に当たって跳ね返る
BallがPlayerに当たって跳ね返る
BallがBlockに当たって跳ね返る
全部確認できれば、今回の大きな目標は達成です。
……とか思ってたらなんかボール上の方で止まってるんだが。
Ballの moveSpeed を 7 とかにしたら跳ね返ってきました。まあ色々試してみよう。
跳ねる角度がちょっとおかしくなることがあるみたいだ。
今回のまとめ
今回はブロック崩しの土台を作りました。
具体的には、BreakoutScene を作り、Player、Ball、Wall、BackWall、Blockを配置しました。
さらに、Materialを使って見た目を整え、RigidbodyとScriptを使ってPlayerとBallを動かしました。
PlayerはAキーとDキーで左右に動きます。
Ballはゲーム開始時に右上へ動き出し、Physics Materialによって壁やPlayerに当たると跳ね返ります。
次回やること
第3回では、今回作ったブロック崩しをゲームとして完成させていきます。
予定している内容は以下です。
BallがBlockに当たったらBlockを消す
残りBlock数を数える
全部壊したらクリアにする
下にBallが落ちたらゲームオーバーにする
リトライできるようにする
UIを表示する
今回の状態では、BallがBlockに当たっても跳ね返るだけです。
次回はそこに「壊す」という処理を追加します。
第1回で出てきたComponentの考え方がかなり重要になります。
今回のSceneは次回そのまま使うので、最後に必ず保存してください。
Ctrl + S
連打しましょう。
Gitを使える人はCommitしておきましょう。
あとがき
第2回はブロック崩しの土台作成でした。
正直、今回やった内容は「ゲームを作ってる!」という派手さは少なめですが、すべてのゲームはこのレベルの開発から始まるんです。
それでは今回はここまで!
お疲れ様でした!
もし時間が余ったら
予行とかやってる訳じゃないので、この資料をどのくらいで完遂できるか分かりません。
ということで、もし時間が余ったら第3回の内容かブロック崩しに入れたいアイデアを即興で組み立てて見ましょう。
例えばボールが分裂するとか。










