自分のノートPCや自宅にPCがある受講生はこの授業で扱うUnityと同じバージョンのUnityをダウンロードして自習できるようにしてください。
物理エンジンに頼ったゲーム企画の例
1限クラス
3限の抽選漏れでこちらに移動した受講生への対応
ChatGPTでコード生成してスクリプトの動作確認 → 第1回課題制作&提出
コード解説
3限クラス
ChatGPTでコード生成してスクリプトの動作確認 → 第1回課題制作&提出
コード解説
以下の資料に従ってUnityの基本操作を練習する。
余裕が有れば適当に各自で練習内容をアレンジしてよい。授業で扱っていない機能を使用してもOK。
この作業は第2回と第3回に渡って行う。第3回で出来たところまでを提出する。
Unity Hubから新規プロジェクトを作成する
テンプレート → コア → Universal 3D
プロジェクト名 GP02
公式資料を元に主なウインドウの機能を実演で説明する。
https://docs.unity3d.com/ja/2023.2/Manual/UsingTheEditor.html 旧バージョン 日本語
https://docs.unity3d.com/6000.0/Documentation/Manual/UsingTheEditor.html 新バージョン 英語
おすすめ記事
【UnityC#講座】Sceneビューのショートカットやお役立ち機能
シーン編集のショートカットが詳しく載っている。旧バージョンのUI
初心者が覚えておくべき11のUnityエディタ機能【Unityの使い方】
各ウインドウの機能が網羅的に載っている。
Unity で使える便利なショートカットキーまとめ【作業効率化】
シーンビューでオブジェクトをスナップ配置する方法
説明はデフォルトレイアウトで行うので同じ状態にしておくとよい(必要があれば)
シーンビューのオーバレイツールをデフォルトにする
ゲームオブジェクトとコンポーネントについて
https://docs.unity3d.com/ja/2022.3/Manual/GameObjects.html
プリミティブゲームオブジェクトについて
https://docs.unity3d.com/ja/2021.2/Manual/PrimitiveObjects.html
GameObject -> 3D Object -> Cube でCubeをシーンに配置
Cubeを左クリックで選択して
インスペクターからTransformコンポーネント
プロパティ Position の X の値 Y の値 Z の値を 全て1 に変更する
Sphere をシーンに配置
シーンギズモ(右上のアイコン)のXアーム Yアーム Zアームをクリックして配置関係を確認
alt + 左クリック + ドラッグ でCubeとSphereを斜め方向から見る位置に視点を回転移動
Qキー(View tool) → マウス左クリックでシーンビューを右方向にドラッグして視点をスライド移動
Cylinderをシーンに配置(シーンビューの中心点に配置される)
Cylinderを選択して、Transformコンポーネントをメニューから Reset する(Sphereと重なる)
HierarchyのSphereをダブルクリック(中央にズームして表示される)
マウスホイールを回転してズームアウト
シーン再生中にUnityエディタに着色して作業ミスを減らす ←説明忘れてた
日本語の文字を表示できた ←ついでにゲーム画面の背景色の設定方法を紹介
シーンパネルの操作の復習から再開
ツールなどのオーバーレイがリセットされるので毎回調整する
オブジェクトの選択と表示方向の変更
Alt + 左クリック 複数のオブジェクトを選択した場合はそれらの中心を基点に回転
右クリック 編集画面を表示しているカメラ(シーンのMainCameraではない)つまり編集者の視点でカメラを振り回す(さらにWASDキーでフライトモード移動)
オブジェクトの移動・回転・スケール https://docs.unity3d.com/ja/2022.3/Manual/PositioningGameObjects.html
適当に移動・回転・拡大縮小を試す
ショートカットキー W E R
コンポーネントのプロパティの編集 https://docs.unity3d.com/ja/2022.3/Manual/EditingValueProperties.html
Directional Lightゲームオブジェクトを選択→Inspectorから
LightコンポーネントのEmissionプロパティのTemperatureから色温度を変更
公式資料を元に実演で説明する。 https://docs.unity3d.com/ja/2022.3/Manual/SceneViewNavigation.html
編集モード
2D と 3D の切り替え
編集視点の切り替え
gizmoのアーム x y zをクリック
gizmoを右クリック → Free や Top などの視点メニュー
パースの切り替え(遠近法のOnとOff切り替え)
gizmoアイコンの中央部分クリック または
Persp / Iso アイコンをクリック
マウス操作
オブジェクト選択
左クリック 選択
Shift + 左クリック 追加
Ctrl + 左クリック 選択切替
左クリック→ドラッグ 範囲選択
画面のズーム
マウスホイール 画面の中心にズーム
マウスホイール + Altキー マウスカーソルに向かってズーム
画面の回転
alt キー + 左クリック + ドラッグ 画面の中心で回転
右クリック + ドラッグ 編集者の視点で回転
右クリック + WASD QE 視点方向に WS 前後 AD 左右 QE 上下 移動
画面のスライド
中央クリック + ドラッグ ドラッグした方向にスライド
+ shift キー 移動量増加(高速化)
alt キー + 右クリック + ドラッグ ズーム(マウスホイールと同機能)
+ shift キー ズーム量増加(高速化)
Q W E R T Y オブジェクト操作モードの切り替え
F 選択したオブジェクトをシーンビューにフィット
※Hierarchyでゲームオブジェクトをダブルクリックと同様
ゲームオブジェクトを選択 + シーンビューにマウスを移動 + F ゲームオブジェクトをシーンビューの中央に配置
Shift + F focus lock オブジェクトの移動にシーンビューが追随
Control + A 全オブジェクトの選択
Control + I オブジェクトの選択を反転
応用 Control + A → F で全オブジェクトをシーンビューに表示
Hierarchyでオブジェクト選択 + 右クリックのメニュー
ショートカットも覚えておくと便利
Move To View Ctrl + Alt+F オブジェクトをビューの中心に移動
Align With View Ctrl+Shift+F オブジェクトをビューの視点の位置に移動 カメラを移動した場合はゲームビューとシーンビューが一致する(画角は別)
Align View to Selected ビューをオブジェクトに移動 カメラを選択していた場合はビューをゲームビューと同じ位置に移動(画角などは別)
ゲームオブジェクトの移動ツール(ショートカットキー W)で使用する特殊な配置方法
https://docs.unity3d.com/ja/2022.3/Manual/GridSnapping.html
ユニットスナップ: 一定量スキップしながらの移動
Ctrl + ドラッグ
サーフェーススナップ: オブジェクトどうしが重ならずに接触するように移動可能
Shift + Control でハンドルに表示された四角枠をドラッグして移動(または回転)
頂点スナップ: オブジェクトの頂点を基準に移動(頂点を合わせる様な移動が可能)
オブジェクトの頂点をマウスでポイントし V を押しながらハンドルに表示された四角枠をドラッグ
V + Shiftで頂点スナップモードにする
ハンドルに表示された四角枠をドラッグして移動(オブジェクトの頂点が配置の基準になる)
V + Shiftで頂点スナップモードを解除
スクリーンスペースモード: シーンビューの奥行方向を無視して配置(シーンの3D空間ではなく画面(スクリーン)に配置した状態で移動)
Shift + ハンドル(または中心)をドラッグ
Unityはゲームオブジェクトの物理的な挙動(落下・衝突・跳ね返り・摩擦)を制御する物理エンジンを内蔵する。
ゲームオブジェクトを物理シミュレーションの対象に設定する手順を示す。
gameObject (Cubeなど)を Sceneに追加
Scene編集ウインドウから gameObjectを選択 → Inspector から
add Component
Physics → Rigidbody
Rigidbodyをコンポーネントに持つgameObjectは物理シミュレーションの対象となり重力の影響でゲーム中に落下や衝突するようになる。
床を追加
Plane を上で追加したgameObjectの下に配置する。
Planeは片面ポリゴンで厚さは0で裏側からはレンダリグされない。
照明の向きを変更
Sceneに最初から配置されているDirectional Light の方向を Inspector から修正する
Y軸やX軸の数値を調整(入力するか または ラベルをドラッグ(Shift + 変化量増加)
床(Plane)、Cube、カメラの位置を調整してゲーム再生画面で落下する様子が見えるようにする
シーンを再生して動作を確認
落下物が床に衝突して止まったら成功
メニュー Edit → Preferences → External Tools
を開いて
External Script Editor に Visual Studio 2022
を設定する
※ Visual Studio Code から変更する
方法1
hierarchyで Plane を選択
add Componet
ボタンを押して new Script から
スクリプト名 GP02
を追加(Create and Add)
検索機能
new
で検索してもいい
AssetsにC#スクリプト GP02 が追加された様子
方法2
ProjectのAssetsを選択
+ボタン -> Scripting -> MonoBehaviour Script
スクリプト名 GP02
または
右クリック Create -> Scripting -> MonoBehaviour Script
スクリプト名 GP02
シーンビューのPlaneにDnDで追加
どのオブジェクトに追加するかよく確認する
3通りの方法
シーンの Hierarchy のPlane に DnD
シーンビューの Plane に DnD
Plane のInspectorに DnD
以下のように Plane の Inspector にCP02(Script)コンポーネントが追加される
追加したGP02スクリプトは基本コードが記述済み
クラス宣言
クラス名 GP02 は UnityのゲームオブジェクトMonoBehaviour のサブクラス
メソッド
Start() シーンが再生される直前に1回だけ実行される初期化用
Update() シーンが画面に描画ざれるたびに繰り返し実行される。標準の描画頻度は 60 fps
ProjectのGP02.csスクリプトをダブルクリックしてVisual Studioから編集する。
アカウントの作成は不要
Visual Studio から以下のコードを追加する。
クラス定義のスコープ({ }の範囲)の中に追加。
※ 正しい位置に追加する ※
メソッドの解説
目的「床Planeに衝突した落下物CubeがPlayerタグを持っていたら消去」
OnCollisionEnter はダイナミックな(動く)gameObjectに衝突が発生した際に呼び出されるメソッド(オブジェクト指向プログラミングの用語。C言語の関数に相当)
このメソッドは引数 collision に衝突した相手のオブジェクトがセットされた状態で実行される。
CompareTag は衝突したオブジェクトに設定されているタグ(Tag)と引数のタグが一致するか判定するメソッド(戻り値は True か False のBool型)
if文でCompareTagの判定結果によって特定のオブジェクトを破壊(再生シーンから削除)する。
Destroy()メソッドはゲームオブジェクトをユニティのステージから消す(メモリから消す)メソッド。
シーンの再生中はDestroyしたオブジェクトはシーンのHierarchyからも消える。
再生を停止するとDestoryされたオブジェクトはシーンに復活する。
検索キーワード: unity オブジェクト 衝突 削除
参考ページ: https://tech.motoki-watanabe.net/entry/2019/01/25/150108
(1/3) 落下物(CubeやSphereなど適当に選んだ3Dオブジェクト)をシーンに加える
3D Object から Sphere をヒエラルキーに追加
位置とサイズを調整
(2/3) 剛体に設定
addComponentから Physics → Rigidbody
(3/3) オブジェクトにPlayer タグを設定する
SphereのInspectorからTagを Untagged から Player に変更(メニューで選択する)
再生ボタンでシーンを再生する。
ゲームビューでPlayerタグを設定したSphereが床と衝突したタイミングで消えたら成功。
HierarchyからもSphereが消えることを確認する。
シーンの再生を停止するとSphereはHierarchyに復活して場所も元に戻る。
プロジェクトをビルドしてゲームデバイス(スマフォやWindowsなど実機)で実行可能なファイルを生成する
ビルドの前に編集中のシーンを
Fileメニューから名前を付けて保存(Save as)
または、
Projectウインドウの Assets > Scenes の中のSampleSceneの名前をクリックして変更
シーン名 GP02
Fileメニュー → Build Profiles からビルドプロファイルパネルを開く
Scene List を選択してビルドに含まれるシーンを確認する。
GP02
が含まれていなければ add Open Scenes ボタンを押して編集中のシーンをビルド設定に加える。
https://docs.unity3d.com/ja/2020.3/Manual/BuildSettings.html
Build Profilesパネルの build ボタン を押す。
ビルドする場所を選択
ビルドファイルの保存場所について※1
ユーザーホームディレクトリや受講生が作成したこの授業用のフォルダの中に、このプロジェクトのフォルダ「GP02」がある。
その中に新規フォルダ を作成して名前を付け替える
フォルダ名 build
buildフォルダを選択して フォルダを選択 ボタンを押す。
ビルドが正常に終了したことをUnityエディタのステータスバーで確認する。
エラーが表示されていたらUnityプロジェクトやビルド設定を調べて修正する。
ビルドが正常に完了すると実行ファイル GP02.exe がファイルエクスプローラーに表示される。
GP02.exe をダブルクリックして実行する。このファイルはUnityエディタを閉じても独立して実行することができる。ビルドしたゲームを他のPCにコピーする際は buildフォルダ全体をコピーする必要がある。GP02.exeだけではゲームは起動できない。
今回のプロジェクトではシーンの終了条件をプログラムしていないのでゲームを終了させることができない。
Alt+F4キーを押して強制終了する。
Window Modeでゲームを実行するように修正する。
メニュー Edit → Project Settings → Player
ネットで「Unity キーボード入力 オブジェクトの回転」で検索して見つけたコードをGP02.csに組み込む。
例)【Unity】キーボードのキー操作でCubeオブジェクトを移動、回転、大きさを変更するやり方【使い方】https://lanstar-blog.hatenablog.com/entry/444834702.html
キー入力と回転に関するコードを抽出して以下に記載した。
動作確認1
シーンを再生する。
床に落ちたSphereやCubeは動きが止まった後では床を傾けても落下しない。
SphereやCubeが床に衝突する以前に床が傾いていた場合は落下する。
※物理シミュレーションの衝突判定のタイミングについて後ほど解説する。
床は片面ポリゴンなので裏側からは見えない。
動作確認2
シーンを再生したままシーンビューを表示して、床に落ちたオブジェクトをマウスで少し移動させる。
→床を転がり落ちる。→衝突判定と物理シミュレーションは動作している。
なぜそうなるのか?
→スクリプトによる床の移動・回転は物理シミュレーションに組み込まれないため。物理エンジンは床が動いていないものとしてシミュレートしてしまう。
シーン GP02 → Plane → Inspector
add Component から Physics → Rigidbody
を追加する
InspectorからRigidbodyコンポーネントの
Is Kinematic を On
に設定する
UnityではRigidbodyを持たないゲームオブジェクトは動かないゲームオブジェクトとして扱われる。
そのためスクリプトで床を回転させても床の状態の変化は物理エンジンに伝わらず水平の初期位置のままとして処理される。
床にRigidbodyを追加すると物理エンジンからは動くオブジェクト( dynamicオブジェクト)として処理される。スクリプトによる 移動・回転も物理演算に組み込まれる
確認
Is Kinematic がon
→ 床(plane)はRigidbodyなのに重力で落下しない
→床(plane)は他のオブジェクトとの衝突で動かない
→Use GravityのOn/Offは影響しない(落下しない)
実験&解説動画
実験
前述の様にスクリプトでオブジェクトの座標を直接移動したり回転させる場合はRigidbody+Is Kinematic Onの設定でOK。
以下で特殊な設定について動作を確認しておく
床が物理判定の対象にり衝突処理も機能する。他のオブジェクトがめり込んだ配置になっていると再生時に床が吹き飛ぶことがある
床の位置を調整して他のオブジェクトにめり込まないようにする
床の衝突判定方法を変更する
Plane のInspectorから
Mesh Collider の
Convex を On
に設定する。(Convex:凸形状)
https://docs.unity3d.com/ja/2018.4/Manual/class-MeshCollider.html
Is Kinematic がoff で Use GravityがOn
→ 床は落下する。床は他のオブジェクトとの衝突で動く
Is Kinematic がoff で Use GravityがOff
→ 床は落下しない。床は他のオブジェクトとの衝突で動く
床の衝突範囲の調整
Mesh Collider の Convex をOnにすると PlaneのScaleに対応したMesh Colliderが自動生成され、シーンビューで緑の枠で表示される。
Scale Y が 1 になっているので衝突範囲に狂いが生じている。
Scale Y を 0.01
に修正する。
参照ページ: https://teratail.com/questions/24071
このサイトのコードを参考にして作業を続ける。
マテリアルの準備
https://docs.unity3d.com/ja/2022.3/Manual/Materials.html
マテリアルを新規作成するにはUnityのメニューまたは プロジェクトビュー のコンテキストメニューから Assets->Create->Material
Albedo の色設定アイコンから適当に異なる色を設定する。
同様の操作を繰り返してマテリアルを3個作成する。
名前も適当に付けておく。
color1
color2
color3
など。
床のオブジェクトに組み込んだ衝突判定スクリプト GP02.cs スクリプトにコードの例を参考にしてメンバー変数を2つ追加する。
Material配列型 mats 要素数は10
int型 count 初期値は 0
メンバー変数: スクリプトがアタッチされたゲームオブジェクト毎に独立した個別の変数。
アクセス修飾子: public と private を指定できる。public を指定したメンバー変数はUnityエディタに接続されInspectorのスクリプトコンポーネントのスロットから編集できるようになる。
詳細についてはこちらを参考に。https://papersloth.hatenablog.com/entry/2020/05/25/135813
マテリアルをC#スクリプト GP02 に渡す
プロジェクトウィンドウの各マテリアルを 床のGP02 スクリプトのInspector に表示されたmats 欄にドラッグ&ドロップ(〇アイコンから選択でもOK)して設定する。
↑「アタッチ」と言います。Unityでオブジェクトに他のオブジェクトやスクリプト、素材などを紐づけすることです。
参照:Unityのパブリックなフィールドとシリアライズなフィールドについて https://ekulabo.com/public-or-serializefield
コード例
キーボード入力のフォーカスが Gameビューに当たっていないと反応しない
Gameビューをマウスでクリックしてからプレイボタンを押して動作を確認する必要がある
(余談)
※ GetComponent<Renderer>().material = mats[count];
の代わりに、Start()メソッドで
mat = GetComponent<Renderer>().material;
Update()で
mat = mats[count];
としても一見うまく動くように見えるが期待通りの動作(色の変更)は起きない。
原因:
Renderer クラスの material プロパティから値を取得する際に、Materialオブジェクトがコピーされて元のMaterial(Rendererで使用される)とは別のMaterialとして mat 変数に保存されるためである。
RendererにはコピーしたMaterialは渡されていない。
Unity API Reference
https://docs.unity3d.com/2023.3/Documentation/ScriptReference/Renderer.html
Rigidbodyにしたオブジェクトを選択して、Ctrl+Dで同じ位置に多数複製。再生すると爆発した様に散らばる。
落下物の増加。gameObjectは3DでCollisionを持つタイプにする。Playerタグを付けるものとつけないもの、マテリアルを設定して色を変えたものなどいくつか用意する。
床の回転のコードを Z と C キー で Z軸 で回転 (反時計回り と 時計回り)するように修正する。
キーボードで操作するプレイヤーオブジェクトをシーンに加える(ヒント)。第4回からのRollaBallチュートリアルでも扱う。
衝突発生で効果音を出す(GP01のコード参照。ヒント)
応用1で追加したコードは無制限に床を回転させてしまう。床が回転可能な角度を範囲制限をする(一定以上動かさない)コードを追加する。
プレイヤーを追跡するオブジェクトをシーンに配置する(ヒント)
ネットで検索してUnityのシーン設定やC#スクリプトを組み込んで動かしてみて下さい。
スクリーンショット(1/2)
取り組んだ内容が分かるように適当に編集画面や実行画面をスクショする。
複数のスクショを1枚の画像にまとめてもよい。
ファイルをWebclassの第2回課題 問1に提出する。
ステップ再生を利用するとゲームのシーンをフレーム単位で進めることができる。
下の例では、床はもっと傾けて(キーボード操作の効果)、ボールはDestroyされているところまで進めてスクショすると作業内容がより伝わる。
Packageファイル(2/2)
シーンの再生をストップ
シーンやプロジェクトを保存
メニュー Assets から Export Package...
パッケージの保存先は自分で選ぶ(デスクトップでもOK)
ExportするAssetを確認して不足があれば追加する。
シーンやマテリアル、スクリプトなどすべて含めておくこと。
パッケージ名 GP02 を入力して Export ボタンを押す
※拡張子は unitypackage の状態で保存してください。
※※ 間違えて.slnファイルを保存しないでください。
保存した GP02.unitypackage ファイルをWebclassの第2回課題 問2に提出する。
チャレンジに挙げた工夫などを評価する。
GP02.cs と GP02.unityのファイルが含まれていることを確認する。
ファイルが足らない場合はProjectsのAssetsフォルダを選択してからExport作業を再度行う。
第3回: 2024年度の水1クラスはここまで進んだ。
ビルドでWindowモードで実行は説明だけでスキップした。
kinematicの実験はスキップした。
応用1まで実演した。受講生には応用2も案内して配列の文法だけ説明した。
チャレンジの実演
R T で床を左右に回転(スクリプトでRotate 50 をコピペして -50に修正)
できたところまででExportして終了
SNAP!入門の課題1を案内した