はじめに
初めてこうした投稿をします。
この記事は自分と同じくUnityを触りたての人向けです。
UdemyでUnityでゲームを作ってみよう的なコースを受け一通り終えました。
受けたコースはこちらです。
投稿の理由
自分の脳内を整理するためです。
こうしたアウトプットをすると知識が定着するというのはよく聞きます。
学生時代友達に得意な科目の勉強を教えたことがありますが、浅い理解では教科書をそのまま読むぐらいしか出来ないですよね。自分の言葉で分かりやすく伝えるには相応な理解が必要です。そのため必死こいて教えるために勉強した覚えがあり、結果知識が深まった経験があります。
なのでコースを受ける前の自分が欲しいと思うようなまとめを作れば理解が深まるんちゃうか?と思い投稿しました。
後、こうやって技術記事を書くと就職に有利って聞いた。
私の知識レベル
- 仕事でVBAとpythonを少し扱ったことがあるくらい
- Javaを少し触ったことがあるのでクラスの概念はうっすらわかる
- ゲームなんて作ったことない
環境
Unity 2021.3.16f1です
受けたコースでは 2020.3.12f1 を使用していましたが、そこまで大きな違いは無かったと思います。
一部レイアウトが違うぐらいでした。
後コードエディタはVSCodeを使用しています。最初はVisual Studioを使っていましたが動作が重いのでVSCodeに乗り換えました。
まとめの対象
- 最初の画面
- Component
- Scripts
大まかに分けるとこんな感じ
Unity特有のことについてまとめます。C#のあれやこれやというのはあまり触れないと思います。
対象はプロジェクトを開いた後についてです。ですのでUnityのインストール等環境構築には触れません。
Unityのインターフェース
さてプロジェクトを開くと初期設定ではこんな感じの画面が出てきます。コースを受けた後の画面なので敵やプレイヤーが配置されています。
これがUnityの基本画面、Windowsでいうデスクトップにあたる画面です。
公式を見る限りUnityのインターフェースと呼ばれているようです。ともかく最初に出てくる恐らく一番よく見るであろう画面です。
Unity’s interface
This section provides a detailed tour of the most common editor windows, and how to make full use of them.
Hierarchy window
Scene(後述)に配置されたものを表示する場所です。
この配置されたものをGameObjectと呼びます。
ものといいましたがGameObjectは物理的に見えるものだけではありません。
例えばBGMなどの音やゲームを管理するシステムといった概念的なものも含まれます。
左上にある + マークから新しいGameObjectを作成することが出来ます。なのでSceneに新しい要素を追加しようと思ったらここでGameObjectを作り、他の画面で色々設定をしていく…ということになります。
Hierarchy = 階層 とある通りGameObjectの関連付けができます。
例えばPlayerがいてそいつが持っているSword、いう感じです。こうして関連付けると一緒に動かすことが出来たりします。
Scene view
真ん中にあるのがScene view
ここはSceneを視覚的に見たりGameObjectの配置位置を決めたりすることが出来ます。
Scene って何だよ、となるかもしれないので例を挙げますと
これはタイトル画面のSceneです。そしてHierarchy Windowにはタイトル画面に配置されているGameObjectが表示されます。
プレイヤーと敵などが配置されており、実際にプレイヤーを動かしたり敵に攻撃したりするSceneになっています。Hierarchy1にはプレイヤーや敵に関するGameObjectが表示されています。
と、場面に応じてSceneを作り管理することが出来ます。
マリオのような面クリ型のゲームなら 1-1 のScene 1-2のScene…という風に作ることが出来ると思います。(実際の開発現場ではどのように管理しているかはわかりませんが…)
よく使うのはこのToolsでしょうか。ここで移動や回転拡大等を選択すると、Hierarchyで選択しているGameObjectにその操作が行えます。
Toolsにはショートカットキーが割り当てられているのでそれを使えると幸せになれるかもしれません。
Q ハンドツール
W 移動
E 回転
R 拡大/縮小
T Rect Tool
Y Transform
Game view
このGame viewでは実際にplayする環境でどのように表示されるか、という画面です。
デフォルトではSceneの隣にあります。
色々編集してこの画面で実際どうなっているかを確かめるために使うのが主な用途かと思います。
上の再生ボタンをクリックすると実際に操作をして動かすことが出来ます。
敵が倒され赤いポーションみたいなやつが出てきたときに、Hierarchyの方も連動してGameObjectが動いているのが確認できます。Play中Hierarchyはリアルタイムで更新さるので、Play中GameObjectがどうなっているかの参考になるかと思います…(私はまだそのレベルまで達していない…)
Project window
Windowsでいうエクスプローラーみたいなやつです。
画像とかBGMとかスクリプト(後述)とかのファイルを扱えるところです。
ゲームに使う素材をここに入れて管理するみたいな使い方をします。
ここにある素材をドラックアンドドロップしてComponent(後述)に適用したりできます。
エクスプローラーからドラックアンドドロップで素材を持ってくることもできます。
音声の場合そのまま再生も可能。スクリプトならテキストエディタが開きます。
フォルダの上で右クリックをしShow in Explore を選択すると保存先をエクスプローラーで見ることが出来ます。
個人の感想ですが、保存先がすぐわかるのはいいですね。何というか安心感があります。
Console
デフォルトではProjectの横にあります。あまり講義では使わなかったので存在を忘れていました。
実際開発途中だとすごくお世話になりそうだなと思いました。
Inspector
デフォルトでは右側にあります。
Hierarchyで選択したGameObjectの詳細を見たり、設定することができます。
ここでComponentを設定しGameObjectがどのような振る舞いをするかを決めます。
日本語訳で検査官、監査人、検閲官という風に、何かを見る・監視するというニュアンスでしょうか。
少し大きくしまして…
このようにComponentの設定をいじることができます。
Componentの設定については後に書きます。
ちょっとしたことですが。数値に関しては数値付近をドラッグすると変えることが出来ます。
上のgifではPlayerの位置を変えています。
Component
GameObjectにComponentを設定していくことにより、そのGameObjectがどんなものかが決まっていきます。
例えば、どこに配置するか、どんな見た目か、どんな当たり判定か、等GameObjectがどの様なものかはComponetで決まります。
個人的に重要かなと思ったComponentをまとめていきます。2D用のものが多いです。
Transform
GameObjectが生成されると必ずついてくるComponentです。GameObjectの位置・角度・大きさを設定しています。
あらゆるGameObjectについてきます。視覚的に見えなくても(音とか)ついてきます。
The Transform is used to store a GameObject’s position, rotation, scale and parenting state and is thus very important. A GameObject will always have a Transform component attached - it is not possible to remove a Transform or to create a GameObject without one.
公式ではTransformを外すことはできないと言っています。
消してみようと右にある縦に点が三つあるやつを開いても他のComponentにはある
Remove Componentがありません。
後、ComponentはInspectorの中の表示の順番を変えることが出来るのですが、Transformは頭に固定されており表示の順番が変えられないです。
UnityからTransformを消させないという強い意志を感じます。
Sprite Renderer
まずSpriteとは公式曰く、2Dグラフィックオブジェクトらしいです。平たく言うと画像です。
Sprites are 2D Graphic objects. If you are used to working in 3D, Sprites are essentially just standard textures but there are special techniques for combining and managing sprite textures for efficiency and convenience during development.
そして Rendererとは何かを描写するプログラムの事です。
以上からSprite Rendererは画像をどのように表示するかを設定できるComponentということになります。
中身について重要そうなものをいくつか説明します。
-
Sprite
映したい画像をここに設定します。Spriteの文字の右にあるテキストボックスに画像をドラッグアアンドドロップするか、テキストボックス右端の小さい丸をクリックし画像を選択することが可能です。 -
Color
画像の色を変更することが出来ます。色だけでなく透明度も変えられます。透明度を0にすれば画像を消すことも可能です。ダメージを受けた時などの点滅に使えます。 -
Flip
Xにチェックをつけることで左右に、Yにチェックを入れることで上下に画像を反転させることが出来ます。人の場合頭から落ちる描写を入れるときなんかに使えそうです。 -
Sorting LayerとOrder in Layer
まずSorting LayerはGameObjectのレイヤーを分類しどれを優先的に画面に映すかを決定します。
下にあるやつが優先的に描画されます。
そしてOrder in Layer はSorting Layerの中での表示の順番を決めることが出来ます。
数値が大きい方が手前に来ることになります。
例えばこのキャラクターのSorting Layerは Playerと設定されており、Order in Layerは 0となっています。
こちらのSwordのSorting layerもPlayerになっておりOder in Layerは -1 です。
キャラの後ろに剣が隠れている状態になっています。
SwordのOrder in Layerを1にしました。剣が前に出てきたことがわかるかと思います。
という風に同じSorting LayerでもOrder in Layerで順番をつけることが出来ます。
……少し余談っぽくなりますがもう一つUnityにはLayerがあります。
このInspectorの上の方にある Layerは Sorting LayerとOrder in Layerには関係ありません。
Qiitaに先駆者様の記事があったのでリンクをはります。
Layerの方はカメラに移すかどうかの設定が出来たりGameObjectの衝突判定を決めたりする設定になっています。
Rigidbody
こいつは物理演算の設定を担当します。
GameObjectに質量を与えたり、重力がどれぐらいかかるかなどを設定できます。
なんだか当たり判定も設定できそうな感じがしますが、このRigidbodyでは当たり判定を設定できません。後述するColliderと組み合わせて当たり判定を設定することが出来ます。(最初Rigidbodyの説明を聞いたときこれがこれで当たり判定の設定か~、と勝手に思ってしまいました)
ジャンプするゲームだとこの設定で操作の感じが違ってくるのでよく吟味しなければいけないかもしれませんね。
さてRigidbodyの中身です
- Body type
3つの種類があります。
- Dynamic 物理演算の影響を受るようになります。3つの中で一番設定項目が多いです。
- Kinematic 外からの力で動くことはできませんが、スクリプトで動かすことが出来ます。
- Static 物理演算を全く受け付けません。壁や動かない障害物なんかに適用できると思います。
kinematic と Static は何が違うんや?という方はこちらの記事を読むといいかもしれません。
2016年(DARK SOULⅢの発売年…もうそんな前なのか)と結構古い記事ですが分かりやすいです。どうやら3種類のBody Typeが実装された時ぐらいの記事のようです。
-
Simulated
チェックを入れることで物理演算を有効にできます。 -
Mass
GameObjectの質量を決めます。色々いじってみましたが2Dではあまり重要ではなさそう…? -
Liner Drag
Drag coefficient affecting positional movement.
公式の英文をDeeplにかけると、【位置決め動作に影響を与える抗力係数】との事らしいです。
???ってなりますが摩擦や空気抵抗のようなものとらえるのがいいかと思います。Uniryの説明もそれっぽい説明が書いてあります。
Drag is the tendency of an object to slow down due to friction with the air or water that surrounds it. The linear drag applies to positional movement and is set up separately from the angular drag that affects rotational movement. A higher value of drag will cause an object's rotation to come to rest more quickly following a collision or force.
-
Angular Drag
Liner Dragの回転版です。回転しにくさといってもいいかもしれません。 -
Gravity Scale
重力です。1で1Gとなります。今お見せしているタイプのゲームでは基本ゼロになるかと思います。
試しに壁に重力を与えるとこんな感じになります。壁が画面下へ向かって落ちていきます。
下に落ちる壁。コミカルな場面で使えそう -
Constraints
GameObjectの動きを制限できます。
チェックした軸に動かなくなるようになります。
XYZにチェックを入れた場合
移動しようとしていますが移動できていません。可愛いですね
Xのチェックを外しました
X軸(横方向)の移動ができるようになりました。縦には移動できません。
Yのチェックを外すと
縦方向にも移動できるようになりました。自由になりましたね。
Zのチェックを外すと…
物に衝突すると衝突の仕方によっては回転するようになりました。どうぶつタワーバトルみたい。
この視点のゲームなら基本的にはチェックを入れて使う…はず。氷の上で滑る描写なんかに使えるかもしれませんね。
Collider
当たり判定に関する設定です。GameObjectに当たり判定を設定できます。
こいつとRigidbodyを組み合わせて別のGameObjectに衝突した際動いたりします。
プレイヤーや敵障害物壁…等当たり判定が欲しいものにはこのColliderを使い当たり判定を設定します。
例として Box Colliderを出しましたが他にも Capsule型やCircle型等いろいろな形の当たり判定を設定することが出来ます。複雑な形になればなるほど処理への負荷も高くなるので注意が必要です。
このような見た目にそぐわないクソデカ当たり判定を設定することもできます。
理不尽すぎる当たり判定ですね。
左側の敵にもColliderが設定されています。このCollider同士がぶつかるとダメージを受けたりノックバックをするようになっています。このCollider同氏のぶつかりをScriptで受け取りノックバックなどの動作につながるようにしています。
- Is Trigger
Colliderの大きさに次いで大切な設定はこれでしょうか。こいつにチェックを入れると物理的衝突が起こらなくなります。少々わかりにくいので例をマリオで出します。仮にマリオがUnityで作られていたらという仮定で書きます。
マリオやブロックはIs Trigger にチェックが入っていなくて、コインやアイテムはIs Triggerにチェックが入っています。
マリオがブロックに接触すると上に乗ることが出来たり、ブロックを破壊できたりします。これは物理的接触がありますね。
一方コインには当たり判定はあるものの、上に乗ったり、ジャンプ中に接触してもマリオの動きは阻害されないですよね。
こうした当たり判定は欲しいけど物理的な衝突は起こしたくないというときにIs Triggerは使われると思います。
Script
UnityのScriptを一言で説明するなら、「C#言語で書かれたユーザーオリジナルのコンポーネント」といえばいいでしょうか。
Unityに元々実装されている(Unityビルドイン)コンポーネントも様々な種類がありますが、それだけでは実現できないことも多いです。そこでScriptを自分で作り、実装したい機能を作ることが出来ます。
さてScriptの中身を見ていきます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
UnityでScriptを新規で作成するとこのような内容になっています。
クラス名に特に意味はありません(Unity上で新しくScriptを作った時のデフォルトネームです)
MonoBehaviour
UnityでScriptを新規作成すると必ず継承している奴です。
読み方はカタカナで表すなら「モノビヘィビァー」でしょうか。
これを継承しているおかげで後述する Start()やUpdate()などが使えるようになります。
GameObjectにコンポーネントとしてScriptをアタッチするためにも必須です。
最初のうちは絶対必要なものという認識になるのではないでしょうか。コンポーネントとして使わない場合や、Start(),Update()等を使わない場合は継承していないクラスを作る場合もあるらしいですが、それはおいおいでいいでしょう…
Start()
ゲーム開始直前に一度だけこの関数が呼ばれます。
Poopクラスを作りConsoleに何か表示してみます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Poop : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("うんち! ぷりw");
}
// Update is called once per frame
void Update()
{
}
}
このPoopScriptをPlayerにアタッチしてゲームを起動します。
このようにゲーム開始前に一度だけ実行されます。
本来ならステータスの初期化なんかに使われるようです。
Update()
こちらは毎フレームごとに実行されます。
こちらもConsoleに文字を表示して動きを見てみます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Poop : MonoBehaviour
{
int poopCount;
// Start is called before the first frame update
void Start()
{
Debug.Log("うんち! ぷりw");
}
// Update is called once per frame
void Update()
{
Debug.Log("ぶりw" + poopCount);
poopCount++;
}
}
これで毎フレーム"ぶりw"とpoopCountを表示するようになりました。そしてpoopCountは毎フレームインクリメントされます。つまりpoopCountの数はゲーム開始からのフレーム数の合計となります。
5~6秒ほどで4000近いフレームがありました。1秒間に700~800回ぐらい表示されています。
このように毎フレームごとに実行されます。本来なら入力を受け取ったりするのに使うようです。
SerializeField
変数の宣言の前に[SerializeField]とつけることでprivate変数をInspector上で編集することが出来ます。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Poop : MonoBehaviour
{
[SerializeField]
int poopCount;
// Start is called before the first frame update
void Start()
{
Debug.Log("うんち! ぷりw");
}
// Update is called once per frame
void Update()
{
Debug.Log("ぶりw" + poopCount);
poopCount++;
}
}
本来ならprivateな変数はInspector上で編集できないのですがSerializeFieldをつけることにより編集できるようになります。ゲームを作っていくうえで頻繁に値を調節したい変数はSerializeFieldをつけることになるかと思います。
ちなみにpublicな変数はSerializeFieldが無くてもInspector上で編集できます。逆にpublicな変数をInspector上に表示したくない場合は[HideInInspector]を変数の前に付けると隠せるようです。
終わり
本当はもっと色々書けるというか、書かないといけない事もあるとは思うのですが疲れたのでこのあたりにしておきます。
読んでいただきありがとうございました。