Roll a Ball Tutorial 2023
紹介: https://twitter.com/R_Nikaido/status/1314160723077992448 『EXO ONE』ボールが転がるだけのゲームが面白そう
演習で扱うチュートリアル
新版RollaBall https://learn.unity.com/project/roll-a-ball (メニューは日本語、動画は英語)
古いチュートリアル
旧版RollaBall https://learn.unity.com/project/roll-a-ball-tutorial-jp 玉転がし(日本語版)
ビジュアルスクリプティング版チュートリアル
https://learn.unity.com/project/bolt-roll-a-ball-tutorial (日本語版)
ゲーム画面の構成とプレイヤー(1/2)
ゲーム画面の構成とプレイヤー(2/2)
スクリプトのライフサイクルの概要を読んでおくとよい。
UnityのC#スクリプトのメソッドの役割が解説されている。主なものを以下に示す。
Awake
Start
FixedUpdate
OnTrigger系
OnCollision系
OnMouse系
Update
LateUpdate
ゲーム画面の構成とプレイヤー
Roll a Ball プロジェクトを作成する。D:ドライブの自分の演習用フォルダ「Game3121888」などに作成すること。
Unity Hub → 新しいプロジェクト
サンプル → 3D Sample Scene(URP)
テンプレートをダウンロード を押す
URPは Universal Render Pipeline の略でUnityが推奨しているレンダーパイプライン(CG描画方式)
通常のUnity コア 3D テンプレートはビルトインレンダーパイプライン(組み込みパイプライン)でUnityに依存したCG描画になる。
URPではゲームデバイスごとに最適化された描画が可能。シェーダーのカスタマイズもできる。ハイエンド機向けゲームにはHDRPが別に用意されている。
プロジェクト名 RollaBall
保存場所 D:ドライブの自分用のフォルダ
バージョン 2022.3.7f1 LTS
テンプレートに含まれる素材(Assets)を片付ける
Project の Assets フォルダに
フォルダ名 Templates
を作成し最初からAssetsに入っていたフォルダやファイルを全てTemplatesに移動する。
1. ゲーム画面の構成
1. ゲーム画面の構成
新規シーン作成 File → New Scene
Scene Temlatesの選択は「Basic(Built-in)」でCreateする。
File → Save でシーンを名前を付けて保存する。
シーン名 MiniGame
フォルダ Scenes を作成してMiniGameを移動する(Save時に新しいフォルダを作成することもできる)。
プロジェクトに素材別のフォルダ
Scenes
Materials
Scripts
Input
を作成して素材を整理できるようにしておく。
シーンにオブジェクト(Ground と Player)、マテリアル(Background と Player)を作成する。
フォルダ Scenesのシーン Minigame を編集
Hierarchyに以下の2つを追加
新規作成:
オブジェクト Ground
3D Object -> Plane
Transform Scale x 2 y 1 z 2
オブジェクト Player
3D Object -> Sphere
Transform Position x 0 y 0.5 z 0
調整:
オブジェクトDirectional Light
Color 全て255 (白色)に変更
Transform Rotation X 50 Y 50 に調整
新規作成 フォルダ Materials
新規作成 マテリアル Background
Surface Inputs
Base Map
RGB を それぞれ130に変更
Metallic Map 0
Smoothness 0.25
ゲームオブジェクトBackgroundにマテリアルBackgroundをDnDで設定。
新規作成 マテリアル Player
Base Map
RGB を それぞれ 0 220 255 に変更
Metallic Map 0
Smoothness 0.75
ゲームオブジェクトPlayerにマテリアルPlayerをDnDで設定。
2. プレイヤーの移動
2. プレイヤーの移動
シーンのゲームオブジェクトPlayer に Rigidbody を追加
add Component -> Physics -> Rigidbody
Is Kinematic OFF のまま変更なし。第3回のコードでは物理エンジンによるオブジェクトの移動は行わないのでONに設定した。
Input Systemのセットアップ
メニュー → Window → Package Manager
Packages を Unity Registry にセット
Input System をインストール
再起動の確認プロンプトが表示される → Yes で再起動を許可 → Sceneファイルを保存
File → Build Settings
Architecture が Intel_64bit であることを確認(32bitになっていたら変更)
Hierarchyの Player にPlayer Inputコンポーネントを追加
Add Component → Input → Player Input
Create Actions ボタンを押す
フォルダ名 Input 作成
RollaBall.inputactions を保存
Player Input の Actions に RollaBallがセットされていることを確認
例) Input Systemのセットアップ + Assetsフォルダの整理 + C#スクリプトの設定
Playerオブジェクトに
Add Component から
New Scritpt
スクリプト名 PlayerController
を追加する(公式のRoll a Ball チュートリアルの以下のコードをコピーしてVisualStudioから編集)
プロジェクトに Scripts フォルダを作成して PlayerController を移動
PlayerオブジェクトのC#スクリプトコンポーネント
speed フィールドの調整 値 10
PlayerController スクリプトの解説:
GetComponent<Rigidbody> 物理エンジンを利用するためのインターフェースを取得する
Vector3 3次元ベクトル。ここではボールに力を加える方向をx y z の成分を持つベクトルで決める
AddForce ボールに力を加える(引数のベクトル方向に引っ張る)
FixedUpdate メソッドでAddForceを使う理由:
物理シミュレーション完全マスター https://learning.unity3d.jp/1167/
InputActionとC#スクリプト
Playerオブジェクトに追加したPlayer Inputコンポーネントでは標準の移動方法はOnMoveメソッドのInputValue で X Y の2次元ベクトルになっている。
操作方法は ASDWキー と 矢印キー の組み合わせ(同時押し可能)で移動ベクトルXYを与えるようになっている。
作業のバックアップとして Assetsメニューから Export Package しておく。ファイル名は適当でよい。保存場所はデスクトップも選ぶことができる。個人用のバックアップとして各自で保管しておくとよい。
進捗管理: 2023年度の第4回はここまで
Unityの挙動とC#スクリプトの解説を入れて5分時間が余る程度。
カメラとプレイ領域、収集するオブジェクトの作成、回転用スクリプトの追加
カメラとプレイ領域
1.カメラの移動
Inspectorから位置と角度を調整
Main Camera
Position X=0 Y=10 Z=-10
Rotation X=45 Y=0 Z=0
Hierarchyで
Player を親オブジェクトとして、その子供にカメラを設定
動作確認(カメラも回る)
Main Camera を元の階層に戻す(親子関係は解除する)
オブジェクト Main Camera
Add Component → New Script から
スクリプト名 CameraController
を追加
Scripts フォルダに CameraController を移動
VisualStudioで編集
以下のスクリプトではMain Cameraのpositionを LateUpdate メソッドで移動させている。
他のゲームオブジェクトのUpdateメソッドの完了後にLateUpdateメソッドは処理される。
ゲームオブジェクトの位置関係に応じてカメラの位置を決めることができる。
ここでは、Playerが移動した後でカメラを移動してゲーム画面内に捉えることができる。
Main Camera オブジェクトを選択
Player ゲームオブジェクトを CameraController スクリプトコンポーネントの Player スロットに設定
【Unity】同じコンポーネントが複数アタッチされるのを防ぐ方法 https://ekulabo.com/disallow-multiple-component
【Unity】狙った順に処理したい時はスクリプトの実行順を指定する https://ekulabo.com/execution-order
2. プレイエリアの構成
空のゲームオブジェクトを作成して四方の壁をグループ化する
Hierarchy -> Create Empty を追加
Walls に名前を変更
Wallsの子としてCubeを追加
Wallsを右クリック
3D Object -> Cube
キーボード Fキー でフォーカスを合わせる
West Wall に名前を変更
Scale を(0.5, 2, 20.5)
Position の X に -10 を設定
Edit > Duplicate で East Wall を作成 X を10に変更
残り2つの壁を作成(スケール変更や回転を利用)
以下、スケール変更で作成する例
North Wall
Scale を(20.5, 2, 0.5)に変更
配置は X の代わりにZ方向で指定する。
X 0
Z 10
South Wall をNorthWallをコピーして作成
Z -10
壁のInspector の Collider で Is Trigger がオフになっていることを確認する。
実行して動作確認(壁に衝突して抜けられない)
Global と Local 座標での回転について確認する
Layout を 2 by 3 に変更
シーンを実行して Player の挙動をシーンビューで確認。
回転モードを Global と Local に切り替えて比較する。
TransformのRotation の表示もしている。
参照: Global と Local https://gametukurikata.com/basic/worldlocal
Center と Pivot https://qiita.com/eewano/items/6892a366b005ba8ff4e0
LayoutをDefaultに戻す
2 by 3 や 4 Split などのレイアウトがメニューに表示されない場合がある。
その際はメニューから、Reset All Layouts で復旧できる。
オブジェクトの収集、スコアの記録、ゲームのビルド
- 収集するオブジェクトの作成
Player を非アクティブにして一時的に非表示にする
Hierarchyの機能の確認
目のアイコン 表示・非表示 切り替え(シーンビューに対してのみ)
指のアイコン シーンビューで選択可・不可 切り替え(誤操作防止)
シーンにピックアップ用アイテムを配置する
Hierarchy -> 3D Object -> Cube
名前 PickUp に修正
目立つように姿勢を変更
Y 0.5
Scale x y z すべて 0.5
Rotation x y z すべて 45
※ここでPickUp オブジェクトの移動モードの Global と Local 座標を確認
↓の画像ではPickUpが複数配置されているが、この段階では1個だけ配置しておく。後の工程でPrefabを用いて複製する。
Global座標
Local座標 PickUpのギズモに注目
マテリアル(Material) PickUp を作成
色は壁やプレイヤーと見間違えない色なら何でもOK
RGB 255 200 0
Smoothness 0.25
PickUpオブジェクトにマテリアルをDnDで設定する。
回転用スクリプトの追加
Rotator を新規作成し、Scriptsフォルダへ移動
スクリプトは短いので入力してみてもよい。(Visual Studioではコード補完機能を利用可能)
オブジェクトの回転スクリプトは Update メソッドに記述する
RotatorスクリプトをPickUpゲームオブジェクトにアタッチ(DnD)する。
シーンを再生して動作確認
Player オブジェクトをアクティブに戻す
Prefabの作成、Pick Upを12個配置、Pick Upの収集
Prefab プレファブ(組み立て済み部品)の作成
プロジェクトのAssetsフォルダに Prefabs フォルダを作成
PickUp オブジェクトをシーン(Scene)またはヒエラルキー(Hierarchy)から DnD(ドラッグ&ドロップ)
Prefab化したPickUpオブジェクトがHierarchyで青文字に変わる。
「>」をクリックするとPrefab編集モードになる。シーンビューのメニューから階層を辿って元のシーンビューに戻す。
空のゲームオブジェクトを Hierarchy に Create Empty から追加する
オブジェクト名 PickUp Parent
Transformを Resetしてシーンの中心に配置PickUp オブジェクトをPickUp Parentの下の階層に配置
PickUpをHierarchyのPickUp Parentの階層の下にDnDして移動する。
確認: 親オブジェクトを移動しても、PickUpの Transform Position は変化しない。
シーンの座標 Global座標から → 親オブジェクトを基準にした Local座標
Edit > Duplicate (Ctrl + D)で PickUpを複製する。時計の文字盤の様に 12個 配置する。
※PickUpはGlobal座標で移動すること。Local座標ではY軸方向にも動いてしまう。
オブジェクトの編集結果をPrefabに適用する。
方法1:
どれか1つのPickupインスタンスを選択
マテリアルを変更
Inspectorの Overrides から Apply all で全プレハブのインスタンスに対して変更を適用
方法2:
Prefab を open して選択モード または select で PrefabのInspactor を開く
Prefabを編集して閉じる(シーンをクリック)
実験: PickUpのPrefabの色を変更してすべてのPrefabインスタンスに適用してみよう。
Materialを新規作成して色を適当に選ぶ。
PickUpのPrefabのMaterialsに新規作成したMaterialを設定する。
オブジェクトを円周上に配置する裏技
Inspectorのプロパティの値を関数で求める
オブジェクトを Ctrl + D で複製して まとめて選択
Position の X に cos(pi/6*#)*7
Position の Z に sin(pi/6*#)*7
2. Pick Up オブジェクトの収集
PlayerController を編集する。
以下のOnTrigerEnter メソッドを追加する。
公式チュートリアルではこのコードは2回に分けて記述しているが、ここでまとめて作成する。
Hierarchyから
PickUpインスタンスをどれか1つ選択
Prefab編集モードに入る
PickUpオブジェクトにタグを追加して設定する
Inspectorの Tag が Untagged に設定されている(タグ無し状態)ので修正する。
1/4ステップ
Add Tag をメニューから選択
2/4ステップ
タグを新規登録する。
Tagsが List Emptyと空の状態なので、 + ボタンを押して
タグ名 PickUp
を大文字小文字に注意して入力し、Saveする。
3/4ステップ
PickUpのPrefabインスタンスを選択する
4/4ステップ
InspectorからTagを PickUp に変更する。
PickUpのInspectorから Box Collider の Is Trigger を有効にする
Is Trigger がon のオブジェクトは衝突しても通過できるようになる。
衝突の検出自体は有効のまま。
Prefab編集モードからシーンビューに戻る。
Prefabの編集 と Prefabインスタンスの編集の違いについて
Prefab編集モードに入らずシーン上のPrefabインスタンスを直接編集することができる。
以下の例は、PrefabインスタンスのPickUpゲームオブジェクトのInspectorからIs TriggerをOffにしている。
Prefabの設定(Is Trigger)が上書されていることを示すために青くマークされている。
※インスタンス側で設定を上書きされた項目はPrefabの設定を変更しても影響を受けない。
※つまりPrefabを変更してもインスタンスに変更は起きない。
対処方法1: PrefabのメニューからOverrides > Apply All する。
対処方法2:Prefabインスタンスで上書きした設定を右クリックして
Apply to Prefab でPrefabの設定をインスタンスの設定に合わせて修正
または
Rerert でインスタンス側の設定をPrefabの設定に復旧
させる。
Prefabの解除方法
(誤ってPrefab化したなどで)Prefabのゲームオブジェクトを通常のゲームオブジェクトに戻すことができる。
HierarchyからPrefabを右クリックして Prefab -> Unpack
Unpack CompletelyするとPrefabの階層(PrefabにPrefabを内蔵して組み立てられた)を辿って内部のPrefabも元に戻る。
物理演算パフォーマンスの改善
PrefabsフォルダのPickUp をダブルクリックで開いて編集する。
PickUp に Rigidbody を設定(Add Component)
Is Kinematic を ON
PickUpをRigidbody Kinematic オブジェクトとして扱うようにする。
進捗管理: 2023年度の第5回はここまで進んだ
水曜日クラス確認事項 PickUp は Rigidbodyかつkinematic か?
スコアとテキストの表示、ゲームのビルド
3. スコアとテキストの表示
PickUpにPlayerが接触した際のスコアカウントのコードを追加する。
拾ったPickUpの数を表示するコードを追加する。
PickUpを全て拾ったらメッセージを表示するコードを追加する。
公式チュートリアルでは上記の3ステップに分けて逐次コードを追加している。ここでは纏めてコードを追加(太字の部分)してもOK。
PlayerControllerスクリプトを編集する。
UIを追加する
Hierarchyの +ボタンからUIオブジェクトを追加
Hierarchy -> UI -> Text - TextMeshPro
Import TMP Essenstials
TMPパネルを閉じる
Canvas や EventSystem も自動的に追加されるがこれらを削除してはいけない。
EventSystem を選ぶ。
コンポーネントのStandalone Input Moduleが古いままでエラーになっている。
以下のボタンをして修正する。
Replace with InputSystemUIInputModule
Canvasの下層の Text(TMP) の名前を変更
名前 CountText
CountTextオブジェクトをダブルクリックしてフォーカスする。配置場所の確認。
Canvasオブジェクトをダブルクリックしてフォーカスする。配置場所の確認。
3DシーンとUI画面の位置関係の確認:
UIのCanvasを選択して F back view から確認する。
ゲームの実行画面でズームしているとUIがフレームアウトして見えない場合があるのでx1倍で表示を確認する。
キー T を押してRect Toolで、UIテキストのサイズやPivotを編集できる。
シーンビューを 2D モードに切り替える。
CountTextオブジェクトを選択する
Inspectorから調整
プレイスフォルダーテキスト(初期値: New Textの部分)を書き換える。
Count TextRect Transformコンポーネントの Anchor Presetメニューを開く
アンカーの設定(Shift + Alt キーで)左上隅をアンカーポイントに選択する。
Altキー同時押しでテキストUIの位置も移動する。
Shiftキー同時押しでPivotも変更される。
余白調整
Pos X 10
Pos Y -10
Playerオブジェクトを選択してInspectorからPlayerControllerスクリプトを表示しておく
CountTextオブジェクトをHierarchyからDnDしてInspectorのCountTextスロットにセットする
シーンを再生して動作確認。「Count: 0」と表示されることを確認する
※ シーンの再生後、エラーでゲームは停止しする。WinText用のGameObjectを以下の工程でアタッチすることでエラーを修正する
同様にして WinTextオブジェクトを UI TextMeshProで作成する
テキストの色を黒に変更
Vertex Color をクリックしてカラーピッカーで選ぶ
フォントサイズ 32
ボールド体(太字) B
テキスト配置 alignment center(ボタン)
プレースフォルダのテキスト You Win!
Pos X 0
Pos Y 130
(位置を中央に移動)
サイズとテキストエリアのサイズに注意する。大きなサイズのフォントがテキストの表示範囲からはみ出ると非表示状態になる
その場合はテキストエリアを広げて対応する
先程と同様にして PlayerControllerスクリプト に WinTextオブジェクトをアタッチする(PlayerオブジェクトのInspectorをロックしておくと楽)
ピボット(pivot 基準点)の補足:
アンカー 中央
ピボット 中央 ( x 0.5 y 0.5)
Pos X 0 Pos Y 0
アンカー 左端
ピボット 中央 ( x 0.5 y 0.5)
Pos X 100 Pos Y 0
アンカー 左端
ピボット 左端 ( x 0 y 0.5)
Pos X 0 Pos Y 0
シーンビューを3Dに戻す。
シーンを再生してアイテムを全て拾う。スコアがカウントアップされる。
すべてのアイテムを収集後に「You Win!」メッセージが表示されることを確認する。
4. ゲームのビルド
RollaBall プロジェクトのフォルダに buildフォルダを新規作成してビルドする。
File -> Build Settings
から
ビルド設定パネルを表示して不要なシーンを削除
ここで作成したシーンMiniGameを
Add open Scenesボタン
で追加
課題提出
中間課題として RollaBallプロジェクトのAssetsをExportして、Webclassの第7回課題(4・5・6回の内容を含む)に提出する。
ファイルサイズが大きくなるのでExportする際に Templates と TextMesh Pro を除外してExportすること。
ファイルサイズがWebclassにアップロードできる容量を超える場合は、レポートフォルダに提出用のフォルダに提出する。
例)必要なAssetを含めること。TemplatesとTextMesh Proのチェックを外す。
Exportする際に、以下のような警告がステータスバーに表示されるが無視してよい。
採点に際して、TextMesh Proのパッケージ依存は講義担当者側で解決する。