ゲーム制作   Unity ソフトウエア 

Unity ソフトウエアでゲーム制作#1モグラたたき編(4.スクリプト)

キャッチ画像モグラたたきスクリプトとDebug.log

本投稿は2024年9月時点の内容になります。アップデートにより変更となる場合があります。また環境によって違いがあると思いますのであくまで参考として、ご了承ください。

様々な書籍、ブログや動画を参考にさせていただきました。多すぎて一つ一つは紹介できませんが感謝です。

初心者の自分がUnity ソフトウエアでゲームを作ってみました。とりあえずシンプルなものということでモグラたたきに挑戦です。ゲーム作ってみるかという感じになったときに、いいタイミングで某ゲームのイベントシナリオ内ミニゲームにモグラたたきが実装されていたのでUIとかエフェクトとか、諸々の仕様をぱくって参考にして作ってみましたよ。様々なHowToの中の選択肢のひとつとして、同じ初心者さんの参考になればよいです。

\ チェック /

用語を解説しつつスクリプトにチャレンジしていきます

今回は結構きついです。書いてる本人の頭の中もケイオスでした。なので必要なところだけチェックして読み飛ばしてもらってOK Death!

本記事のポイント

  • ゲームオブジェクトとコンポーネント超概要解説、ついでにゲームオブジェクトの名前変更
  • スクリプトの作成
  • クラス、MonoBehaviourの超概要解説
  • スクリプトをコンポーネントとしてのアタッチ(紐づけ)して、実行します
  • デバッグログの出し方がわかる
  • trasformの罠問題を考える

ゲームオブジェクトとコンポーネント

ゲームオブジェクトって何だろう?

まず前回シーンに配置したユニティちゃんを選択して、インスペクターを見てみましょう。

\ 前回をチェック /

ゲームオブジェクトとコンポーネントを見てみる

ゲームオブジェクトとコンポーネントの関係をみてみる

  1. ユニティちゃん(ゲームオブジェクト)を選択
  2. インスペクターを見ると「Transform」、「SpriteRenderer」という項目が確認できると思います。シーンに配置された物体(ゲームオブジェクト)はこれらの部品(コンポーネント)が集まって出来ています。
  3. 選択しているついでに、ゲームオブジェクトの名前を変更してみましょう。インスペクターの一番上の欄が名前なので、これを変更します。名前の変更はインスペクター以外、ヒエラルキーでもできます。

ゲームオブジェクトとコンポーネント

ゲームオブジェクトとコンポーネント概要

  • GameObject (ゲームオブジェクト) はキャラクター、小道具、背景などを表す Unity の基礎となるオブジェクトです。今回のユニティちゃんのスプライトもゲームオブジェクトです。シーンはこのようなゲームオブジェクトの集まりで構成されます。
  • ゲームオブジェクト自体に機能はほとんどありません。コンテナ(箱)のようなもの、もしくは自動車のフレームみたいなものをイメージするといいかもしれません。そこにコンポーネントという部品が付くことで様々な性能、機能が付きます。
  • ゲームオブジェクトには必ず空間中の情報を付与するTransformコンポーネントが付きます。

スクリプトを作成してみよう

スクリプトを作成してみましょう。

スクリプトを作成してみよう

  1. まずはスクリプトを整理するためにプロジェクトに「Scripts」フォルダーを作成しました。
  2. プロジェクトで 右クリック>作成>C#スクリプト をクリック
  3. 今回は「Test」名前で作成しました。
  4. スクリプトをダブルクリックするとVisualStudioが開きます。コーディングして保存するとUnity エディターでコンパイルしてくれます。

コンパイルとは

  • Unity プロジェクトではC# プログラミング言語をサポートしているので、基本スクリプトはC#で書いていきます。コンパイルとは人間ベースの言語で書かれたもの(今回はC#という文法で書かれたもの)をコンピューターが理解できる形に翻訳することをイメージしてもらうと良いかもしれません。

クラス継承とMonoBehaviourについて

作成したスクリプトの中身を見てみます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Unity プロジェクトでスクリプトを作成すると、必ず「:MonoBehaviour」と付きます。

これはMonoBehaviourというクラスを継承した派生クラスだよという意味です。クラスとはオブジェクト指向プログラミングにおいて、オブジェクトの設計図に相当するものです。

初学だと何のことかよくわからないですよね。マケイヌもそうです。なので、ここからは、初心者のマケイヌならではのイメージで書いていきます。

クラスて何(初心者解説)

クラスとは(初心者的イメージ解説)

  • ロールプレイングゲームをプレイする方はよくジョブ/クラスてよく聞くと思いますが、そのクラスに近い感じでイメージしています。
  • 特定のパラメータやスキル(プログラミングだとフィールドとかメソッド)を持ったキャラクターテンプレート(設計図のニュアンスを入れるならキャラクターシートて感じかな?)のイメージ
  • 名前やHP、MPといったステータスがあり魔法が使える魔導士テンプレートがクラス。
  • 魔導士を元にさらにスキルなどを加えた白魔導士、黒魔導士などのテンプレートが派生クラス。
  • 魔導士テンプレートに具体的な名前、数値を入れた実態のあるプレイヤー(クラス:魔導士)がオブジェクト/インスタンス

なんとなくイメージ持てましたか?もっとしっかり知りたい方はオブジェクト指向について書かれた書籍やブログで学習しましょう。ちなみにマケイヌは学習したくありません!

MonoBehaviourて何(初心者解説)

以上を踏まえたうえでMonoBehaviourの解説です。

Monobevavior概要

  • MonobevaviorはUnity スクリプトの基本クラス。デフォルトですべてのUnity スクリプトがここから派生します。
  • スクリプトをコンポーネント(ゲームオブジェクトに機能を持たせる部品)とするためのフレームワークを提供してくれる。
  • Start、Updateや衝突判定など数多くの便利なイベントへのフックを提供してくれる。

はじめのうちは基本的にMonobevaviorを使っていく方向で良いでしょう。

スクリプトを書く、ついでにデバッグログを出してみる

スクリプトを書いてみます

具体的にスクリプトを書いてみます。

ついでにデバッグログの出し方も解説します。プログラミングをしていると必ずうまくいかなくなります。その時に変数が正しい値になっているかとか、関数が実行されているかとか、調べる定番の方法がログを出すことです。簡単なので覚えましょう。

ユニティちゃんを左右反転させるコードを書いていきます。

public class Test : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //Vector3型のtransform.localScaleの値をscaleに代入
        Vector3 scale = this.transform.localScale;
        //scaleのx方向を-1
        scale.x = -1.0f;
        //厳密には元の倍率を生かすべきなので
        //scale.x=-scale.x;の方がより好ましい
        
        //scaleの値をtransform.localScaleに代入
        //これで反転します
        this.transform.localScale=scale;

        //transform.localScale.xの値をログに出力します
        Debug.Log("xの倍率は:"+ this.transform.localScale.x);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

スクリプト解説

  • 7行目:scaleにゲームオブジェクトのlocalScaleを代入
  • 9行目:scaleのx軸成分に-1を代入(x軸に沿って反対方向に向ける)
  • 14行目:ゲームオブジェクトのlocalScaleにscaleを再代入
  • 18行目:コンソールにログを出すにはDebug.Logを書きます

スクリプトをコンポーネントとしてアタッチしてみる

スクリプトをゲームオブジェクトにアタッチして実行しよう

  1. スクリプトを保存したらUnity エディターに戻って、ユニティちゃんを選択し、プロジェクトの「Test」スクリプトをインスペクターにドラッグアンドドロップしアタッチします。(インスペクターの「コンポーネントを追加」からも可能です)
  2. 再生ボタンをクリックします。
  3. ゲームが再生されてユニティちゃんが反転しました。
  4. コンソールタグをクリックするとちゃんとログが出ているのが確認できます。必ず最後に停止ボタンをクリックしてゲーム再生を終わらせましょう。

うまく反転できましたね。

transformの罠問題

trasform.position.x問題

今回はうまくいきましたが

実は「transform」には初心者がハマりがちな罠があります。先ほどのコードで一足飛びに次のように書いたらどうでしょう?

this.transform.localScale.x=-1.0f;

一見間違ってなさそうですが、「transform.localScale.x」は変数ではないから変更できないと怒られてしまいます。どうやらプロパティを通じて、構造体のメンバーにアクセスすると出るエラーのようです。これ「trasform.position.x」とかもやりがちです。

どうしてうまくいかないのか

  1. Vector3が参照型のクラスではなく値型の構造体(struct)だから
  2. 「trasform.position」とか「trasform.localScale」がVector3型のプロパティなのに、その中のフィールド変数にアクセスしてるから

はい、よくわからないですよね。

構造体と値型

構造体とは関連あるものをまとめたクラス似たものです。ただしクラスは参照型で、構造体は値型としてふるまいます。

値型はメモリーに値そのものを格納します。代入などしたときは値のコピーを渡すイメージです。(参照型は格納された住所を渡すイメージ)。値型なんていうと難しそうですがintとかで実は結構普通に使ってます。

int x;

x=1;

foo(x);
Debug.log("x:"+x);

void foo(int y){
  y=y*10;
}

fooを通過したxの値は?

  • xは1です。fooにはx のコピーが渡されているのでfooの外にあるx本体は変化しません。
  • もしもintが参照型だったら?xは10です。fooには参照が渡されるので参照元のxも変化します

なんとなくイメージできましたか?

プロパティとは

次にプロパティです。プロパティとはクラス内で限定公開されている変数に外からアクセスして取り出したり、書き込んだりする仕組みみたいなイメージです。

public class foo
{
    // 隠蔽(privateに)された変数
    private int bar;
    
    //アクセスして取り出したり、書き込んだりする仕組み
    public int Bar 
    { 
        //取り出す
        get { return bar; }
        //書き込む
        set { bar = value; } 
    }
}

上記ではint 型ですが、「transform.position」や「trasform.localScale」は構造体のVector3型を取得したり書き込んだりします。このとき上記したように構造体は値型なので取得する側はコピーを渡されます。

transform.position.xはコピーの中身?

もう一度問題のコードを見てみます

this.transform.localScale.x=-1.0f;

とか「transform.position.x=」とかすると、プロパティとしてVector3のコピーを渡しただけだから、その中身のxに代入しても意味ないよ、とエラーになるのかなと思われます。

もっと厄介なtransform.position.Set

ちなみにもっと厄介なのが、Vector3にx、y、zの成分を渡すSet(x,y,z)メソッドです。それを使って

this.transform.position.Set(-1.0f,0,0,);

などとしたらコンパイルはされるのに何も起きないとなってハマります。

おそらくこれも同じ理由で、それ渡したコピーの値変えてるだけだけど、プロパティ的にVector3型できちんと代入しないと意味ないけど?まあでもこの人この値変えただけのコピーどこかで使うつもりかも?とりあえずコンパイル通しとくかて感じでなのかなと思います。

さてざっくりとした理解で長々と書いてきましたが結局どうすればいいのか?

transformの罠問題はどうすればいいのか

答えはシンプルにVector3型をしっかり代入するです。

transformの罠問題

  • transform.positionやtransform.localScaleにはVector3型をしっかり代入

今回参考にした動画です。

まとめ

あいまいな理解の解説にお付き合いいただいた方ありがとうございました。あくまで初心者がイメージ優先で書いたので、至らない部分が多々あると思います。ご容赦ください。

まとめ

  • ゲームオブジェクトはコンポーネントの集まりである。
  • スクリプト作成はプロジェクトで右クリック、アタッチはインスペクターにドラッグアンドドロップ。(インスペクターの「コンポーネントを追加」でもできる)
  • 初心者は基本MonoBehaviourを継承してOK。
  • Debug.Log()でコンソールにログが出せる。
  • transform.positionやtransform.localScaleにはVector3型を代入する。
  • もっと詳しく知りたかったらオブジェクト指向やC#の書籍などで学習しよう
ユニティちゃん公式ホームページへ
ユニティちゃん公式ホームページ
ユニティちゃんライセンス
ユニティちゃんの画像、素材、ライセンスロゴはユニティちゃんライセンス条項を元に使用しています

\ Unityのスクリプトを書くのに役立ちます /

もっと早く教えてほしかった!Unity C#入門

MARU

マケイヌ的おすすめ度

わかりやすい度

目指せ脱初心者

〇おすすめポイント

ボリューム大でC#学習にもよく使う関数のチェックにもOK

×よくないポイント

始めたばかりの人にはちょっと難しい

おすすめ記事

 

プロフィール

マケイヌ

人生のメインストリームから外れた40代の♂。

90年代オルタナにはまり、文字通りメインストリームから逸脱。 その後もたびたび人生から逃亡。

心が動いた作品の紹介や 自分のちいさな経験、HowToを発信できればと日々模索中。

1年後までにイラストと写真のポートフォリオをつくりたい。

記:2019年12月

▼プロフィールはこちら

Follow me

アーカイヴ