ゲームエンジン基礎Ⅰ⑥(2025/07/11)

今日の用語

・GameObject(ゲームオブジェクト):
 UnityのSceneに配置されているオブジェクトのこと
 (機能をまとめておく箱)

・Component(コンポーネント):
 GameObjectに付与されている機能のこと

・Script(スクリプト):
 ソースコード(プログラムファイル)C++ ⇒ C♯ が命名の理由らしい(噂)
                   ++

・Sprite(スプライト)/Texture(テクスチャ):
 画像のこと(.png,jpg等)
 2Dで使うものはSprite。3Dの面に張り付けるものはTexture。

・変数系…
 宣言:変数をつくること
 代入:変数に値をいれること
 参照:変数の中身を確認すること

※UnityにAutoSaveはないので、随時Ctrl+Sで保存しながら進めていくこと


いまから動くものを作っていく

Sprite内に絵素材を取り込み

アセットのInspectorから PixelsPerUnit と FilterMode を変更する。
※Pixels Per Unit:
 Unityの単位はメートル単位。1メートルに何ピクセルを収めるか、という設定。

素材をHierarchyにドロップ。(この時点で、png素材をもとにゲームオブジェクトを生成する)

SpriteEditorを起動。Sliceしていく。

一枚の画像ファイルをSliceして、それぞれをAssetとして使うことができる。

空オブジェクト:
ComponentがなにもついていないGameObject。ほかのObjectをまとめておくなどに使う。

Uintyは、ゲームオブジェクトとコンポーネントの組み合わせ。
Componentを把握することが、習熟の近道。

・Renderer:描画系
・Colider:当たり判定(Script側で距離計算しても可)

InspectorからRigidbody2D AddComponent。(ちなみにRigidは「剛体」)。



Mass:質量(オブジェクト衝突時の結果に影響)
GravityScale:(重力定数9.8*x倍)
Damping:抵抗(オブジェクト移動時の抵抗)
(LinearDamping:落下、移動に対する抵抗
 AnglarDamping:衝突などの時の回転に対する抵抗)

※この場合、たとえば地面を設けない場合などは、無限に落ちてゆく。
 この場合、座標や加速度が型の上限を超えると「StackOverFlow」などのエラーが起きる。
 動作が遅くなったり、落ちたりする。
 画面外に出た際に止めたり、消したり、という処理を必ず行う。

Squareを作成。

キャラクターにColliderをAddComponent。

SquareオブジェクトにもColliderをAddComponent。

※あまりに加速した状態で衝突すると、突き抜けてしまう状況が発生するので注意(壁抜け)。※RigidBodyとColliderとRendererが分離されている理由
・当たり判定、物理現象、表示、演算をばらばらに使うことが、ゲーム制作上はよくある為。

この時点までで、地面に立てる。

スクリプトを作っていく(MonoBehaviourScript)。

スクリプト作成の時、名前を決めるが、それがそのまま[class名]になり、csファイルが生成される。

※スクリプト内の「public class ******:MonoBehaviour」の*******と
 ファイル名******.csが一致していないと動作しない。

 ファイル名を変えたりする場合にはスクリプト内のclassも修正すること。

今回は「PlayerController」に変更してみる。

※プログラムの読み方

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
⇒まずは{}で囲まれた「ブロック」を確認する。この囲まれた範囲が命令の塊。
 ブロックの先頭に「名前」がある。
public class{}からC#のプログラムは始まる。これがclass。
void Start(){}などは「メソッド(関数)」。
この中に処理を記載してゆく。

※プログラムにおいてはスペースが大事。ファイル名などにスペースは入れない。(使うなら-,_)

デバッグログを出してみるコードを追加。

    void Start()
    {
        Debug.Log("プレイヤー:開始");
    }

これを保存して実行しても何も起こらない。MonoBehaviourScriptを動作させるためには「アタッチ」が必要。

プレイヤーにアタッチする。

それでStart()メソッドは1フレーム(1回だけ)実行されるため、Consoleには一回だけ表示される。
なお、Debug.Log();は「DebugというClass内のLog()というメソッドを呼ぶ」という命令になる。

今度はUpdateにデバッグログを追加してみる。

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        Debug.Log("プレイヤー:開始");
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log("プレイヤー:実行中");
    }
}

デバッグログが毎フレーム出力される。

次に、入力に反応するスクリプトを組んでいく。
 ・●●が押されたらー条件分岐 という構成が多くなる。

    void Update()
    {
        bool click = false;
        if (click == true)
        {
            Debug.Log("プレイヤー:実行中");
        }
    }

この例では、consoleには何も表示されない。
では、clickに「マウスボタンの入力」を反映させてみる。

    void Update()
    {
        bool click = Input.GetMouseButtonDown(0);
        if (click == true)
        {
            Debug.Log("プレイヤー:実行中");
        }
    }
//GetMouseButton():マウスボタンを押している間(ずっと)
//GetMouseButtonDown():マウスボタンを押した瞬間(一度のみ)
//GetMouseButtonUp():マウスボタンを離した瞬間(一度のみ)
//なお、()内の数字は、0:左クリック、1:右クリック、2:センタークリック となる。

これで「クリック時にコンソールログが表示される」状況になった。

※ゲーム制作においての根幹はif文。これでプログラムの「流れの制御」を行う。
 他の命令は「楽にする」文。まずifに慣れること。

各Componentには、Scriptからしかアクセスできない機能が多々ある。
今回はRigidbody2DのなかでAddForceを使ってみる。

これを追加したスクリプトを書いてみる。

    void Update()
    {
        bool click = Input.GetMouseButtonDown(0);
        if (click == true)
        {
            Debug.Log("プレイヤー:実行中");
            GetComponent<Rigidbody2D>().AddForce(new Vector3(0,25,0),ForceMode2D.Impulse);
        }
    }

GetComponent<Rigidbody2D>().AddForce()
new Vector3 … Vector3を作成。
”.”が接続。”,”が区切りを意味する。

これで、クリック時に「跳ぶ」ようになった。
今度は、X軸をランダムに設定してみる。

    void Update()
    {
        bool click = Input.GetMouseButtonDown(0);
        if (click == true)
        {
            Debug.Log("プレイヤー:実行中");
            GetComponent<Rigidbody2D>().AddForce(new Vector3(Random.Range(-5,5),5,0),ForceMode2D.Impulse);
        }
    }

次に、四方を壁で囲む。
Squareオブジェクトをコピーしてペースト。サイズと座標を編集してプレイヤーの周りを囲む。

衝突判定を追加する。

    void OnCollisionEnter2D(Collision2D collision)
    {
        Debug.Log("当たった!!");
    }

オブジェクトに当たったら、Logが表示されるようになった。
次に、「床に当たった時だけ」「壁に当たった時だけ」などの条件分岐をつけてみる。

    void OnCollisionEnter2D(Collision2D collision)
    {
        Debug.Log("当たった!!");
        if (collision.transform.name == "Square")
        {
            Destroy(gameObject);
        }
    }
//Destroy(gameObject);の場合、gameObjectは、スクリプトがアタッチされたgameObjectを破壊する。衝突した相手を破壊したい場合、Destroy(collision.gameObject);と記載する。

これで、床(Square)に触れたときにDestroy(gameObject);が動作して、プレイヤーが消滅する。
次に、クリック時に回転も加えてやる。

    void Update()
    {
        bool click = Input.GetMouseButtonDown(0);
        if (click == true)
        {
            Debug.Log("プレイヤー:実行中");
            GetComponent<Rigidbody2D>().AddForce(new Vector3(Random.Range(-5, 5), 5, 0), ForceMode2D.Impulse);
            GetComponent<Rigidbody2D>().AddTorque(Random.Range(-25,25));
        }
    }

これでジャンプ時に回転も付加されるようになった。

今日はここまで。

コメント

タイトルとURLをコピーしました