【Unity】オブジェクトの取得

 前提が必須ではないが「【Unity】Unityの取得がざっくりわかるはなし」も合わせて読んでおくことを推奨する。

 オブジェクトの取得にはいくつか手段があるが大きく分けると2つ。
①事前に手動で登録
②スクリプトで自動取得

 それぞれ場面に応じて使い分けが必要だが、特に事情がなければ①の方がとっつきやすい。

①事前に手動で登録

 方法は主に以下2パターン。宣言のときに一言つけるだけでInspector【インスペクター】ウィンドウにドラッグ&ドロップ用の枠が作られる。取得したオブジェクトで何をするかで最適な記述は変わってくる。よくわからないうちはpublicでよい。

//スクリプトで取得したオブジェクトのコンポーネントや値をいじりたいとき
public GameObject kaeru;

//スクリプトから変更を加えないとき
[SerializeField] GameObject kawaz;

②スクリプトで自動取得

 方法はいくつかあるが扱いやすいのは以下サンプル。シーン中のアクティブなオブジェクトをオブジェクト名で検索する。処理負荷が大きいため毎フレーム実行することのないように工夫が必要。Start【スタート】関数で最初に取得して使うのが一般的。

//オブジェクト名で検索
GameObject kaeru = GameObject.Find ("KaeruSan");

【Unity】コンポーネントの取得

 GetComponent【ゲットコンポーネント】関数を使う。

オブジェクト.GetComponent<コンポーネント名>()

 以下は具体的なサンプル。TextオブジェクトにText【テキスト】コンポーネントと自作のスクリプトを追加してある。自作のスクリプトからTextコンポーネントのtextプロパティを書き換えるサンプルプログラム。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;  //UIを使うのでこれを追加

public class kazoeru : MonoBehaviour{
    void Start(){
        gameObject.GetComponent<Text>().text = "otameshi";
    }
}

 尚、GetComponentは探し出すような処理であるため、Update【アップデート】関数の中など繰り返し頻繁に利用したい場合は負荷軽減のためにスクリプト内で別途宣言した変数に代入して利用するのが一般的である。以下にそのサンプルを示す。

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

public class kazoeru : MonoBehaviour{

    Text kerokero;  //Text型変数kerokeroの宣言

    void Start(){
        //↓変数kerokeroにコンポーネント代入
        kerokero = gameObject.GetComponent<Text>();  
    }

    void Update(){
        //keorkeroのtextプロパティに文字列代入
        kerokero.text = "otameshi";  
    }
}

【Unity】スクリプトの全体レイアウトのはなし

 Unityでスクリプトを書く際のセオリーをまとめました。厳密なルールはほとんどありませんが、NGを覚えるよりBestを覚えるほうが得策です。
 まずスクリプトを作成すると下記のようなソースコードが自動的に書かれた状態になります。スクリプトの作り方を知りたい方は「【Unity】スクリプトの作成と追加」を参考にしてください。

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

public class otameshi : MonoBehaviour{
    void Start(){
    }

    void Update(){
    }
}

 otameshiの部分はスクリプトのファイル名で作られているはずです。その中のStart【スタート】関数とUpdate【アップデート】関数はよく使うので書いてくれている部分です。使わなければ書かなくても構いません。逆に必要であれば他の使える関数を使うこともできます。自分で関数を作ることもできます。それを踏まえて全体のレイアウトを図にまとめました。

using なんたら
 あまり書き換えることはありません。名前空間などと呼んだりしますが共通の言葉をまとめた辞書のようなものだと思っておいてください。

クラス宣言
 あまり書き換えることはありません。クラス名とファイル名は同じにするルールです。基本的に自動生成されたままで構いませんが、ファイルを複製などした場合はご注意ください。

変数宣言など
 そのクラスで使う変数の宣言などを書きます。Update関数内で宣言すると毎フレームリセットされてしまうので、ゲーム中保持したい変数などはこのエリアで書きます。

Start関数
 最初に一度だけ実行されます。これから使うオブジェクトやコンポーネントの設定などを書いたりします。ゲームの開始時というと少し語弊があるのですがいずれ他の記事にまとめられたらと思います。

Update関数
 起動中常にずっとやる処理を書きます。毎フレームですので設定が60fpsなら1秒間に60回処理することになります。リアルタイムな変化を作る部分ですので一番書き込む部分と言っても過言ではありません。

その他の関数
 自作した関数は勿論、最初から書かれていなくてもいくつか使える関数があります。便利なものでいうとAwake【アウェイク】関数、OnEnable【オンイネイブル】関数、FixedUpdate【フィックスドアップデート】関数、LateUpdate【レイトアップデート】関数などがあります。習得してしまえばより詳細にタイミングをコントロールできますが、最初から覚える必要は全くありません。

 少し長くなってしまいましたが、実際に書きながら少しずつ実感の湧いてくるものになります。一度に覚えようとせず実践しながら都度この記事の図を確認しに来ていただければと思います。

【Unity】スクリプトから大きさを変更する

  「【Unity】スクリプトから位置座標を変更する」とほぼ同じだがscale【スケール】ではなくlocalScale【ローカルスケール】を使う点に注意。
 手順は大きく以下3つ。
①仮の変数に今の座標取得
②仮の変数の値を変更
③オブジェクトの座標に仮の変数を代入

 代入という言葉がわからない場合は「【C#】代入のはなし」を参照。またVector3【ベクタースリー】という言葉がわからない場合は「【Unity】Vector3がざっくりわかるはなし」を参照。さらにTransform【トランスフォーム】コンポーネントについては「【Unity】位置、回転、大きさを変える」も参照しておくことを推奨。

Vector3 kero = new Vector3(1, 1, 1);  //①仮の変数宣言&初期化
kero.x = 2;                           //②変数keroのx座標を2に書き換え
gameObject.transform.localScale = kero; //③位置座標に変数keroを代入

 本来スクリプトからコンポーネントの変数にアクセスするときは同じオブジェクトであってもコンポーネントの指定や取得をしておく必要があるが、Transformは基本的にどのオブジェクトにも標準搭載なので省略できる。

 よくある落とし穴のポイントとして以下のように直接localScale【ローカルスケール】の座標を変更したくなるが、これはできない仕様。Vector3で代入できるので仮のVector3型変数を作っている。

//エラーになるパターン
gameObject.transform.localScale.x = 1;

 また、勘のいい方ならscaleを使うと思ってしまうが、localScaleを利用する。これはオブジェクトを子オブジェクトとして設定した際親オブジェクトに連動してサイズが変わるため、全体から見たサイズ情報とオブジェクト自身が持つサイズ情報を区別するためにあると思われる。

【Unity】スクリプトから回転・姿勢を変更する

 「【Unity】スクリプトから位置座標を変更する」とほぼ同じだがrotation【ローテーション】ではなくeulerAngles【オイラーアングルズ】を使うことに注意。
 手順は大きく以下3つ。
①仮の変数に今の座標取得
②仮の変数の値を変更
③オブジェクトの座標に仮の変数を代入

 代入という言葉がわからない場合は「【C#】代入のはなし」を参照。またVector3【ベクタースリー】という言葉がわからない場合は「【Unity】Vector3がざっくりわかるはなし」を参照。さらにTransform【トランスフォーム】コンポーネントについては「【Unity】位置、回転、大きさを変える」も参照しておくことを推奨。

Vector3 kero = new Vector3();  //①仮の変数宣言&初期化
kero.x = 1;                           //②変数keroのx座標を1に書き換え
gameObject.transform.eulerAngles = kero; //③位置座標に変数keroを代入

 本来スクリプトからコンポーネントの変数にアクセスするときは同じオブジェクトであってもコンポーネントの指定や取得をしておく必要があるが、Transformは基本的にどのオブジェクトにも標準搭載なので省略できる。

 よくある落とし穴のポイントとして以下のように直接eulerAnglesの座標を変更したくなるが、これはできない仕様。Vector3で代入できるので仮のVector3型変数を作っている。

//エラーになるパターン
gameObject.transform.eulerAngles.x = 1;

 また、勘のいい方はrotationで動かせるかと思ってしまうがこれもエラー。transform.rotationはVector3ではなくQuaternion【クオータニオン】という型で保存されている。普段私達が使っているオイラー角で代入するためにはeulerAnglesを指定すればよい。

【Unity】スクリプトから位置座標を変更する

 手順は大きく以下3つ。
①仮の変数に今の座標取得
②仮の変数の値を変更
③オブジェクトの座標に仮の変数を代入

 代入という言葉がわからない場合は「【C#】代入のはなし」を参照。またVector3【ベクタースリー】という言葉がわからない場合は「【Unity】Vector3がざっくりわかるはなし」を参照。さらにTransform【トランスフォーム】コンポーネントについては「【Unity】位置、回転、大きさを変える」も参照しておくことを推奨。

Vector3 kero = new Vector3(0, 0, 0);  //①仮の変数宣言&初期化
kero.x = 1;                           //②変数keroのx座標を1に書き換え
gameObject.transform.position = kero; //③位置座標に変数keroを代入

 本来スクリプトからコンポーネントの変数にアクセスするときは同じオブジェクトであってもコンポーネントの指定や取得をしておく必要があるが、Transformは基本的にどのオブジェクトにも標準搭載なので省略できる。

 よくある落とし穴のポイントとして以下のように直接position【ポジション】の座標を変更したくなるが、これはできない仕様。Vector3で代入できるので仮のVector3型変数を作っている。

//エラーになるパターン
gameObject.transform.position.x = 1;

【C#】代入のはなし

 プログラムをソースコードで書き始めて違和感のあるポイントの1つ、イコール記号”=”についての記事です。
 ”=”自体は算数や数学で見慣れた記号ですがプログラムではそもそも別物です。ニュアンス的に共通する部分もありますがそもそも別物として学びなおしたほうがむしろわかりやすいかと思います。尚、これは”代入“という変数の操作ですので先に「変数がざっくりわかるはなし」をご一読いただければと思います。

 算数や数学での”=”は等価を表します。等価というのは”=”の右と左が同じという意味です。特に算数では”計算式=計算結果”という使い方がメインだと思います。

 一方でプログラム(この記事ではC#)での”=”は代入という操作を意味します。
  「変数がざっくりわかるはなし」 と同様にコップを例に出して話を進めると、コップに入れておく水の量を変える操作です。例えば空のコップaがあるとして

a = 50;

のような記述のイメージは下の図のようになります。

 他にもいくつか例を並べてみましょう。

 あまり実感が湧きづらいかとは思いますが要は代入とは
「コップの中を今から言う量にしてくれ」
という命令です。

 つまり量を明確に指定する必要があります。「50にしてくれ」「20と30を足した量にしてくれ」「あっちのコップbと10を足した量にしてくれ」といった具合です。
 指定した量だけ注ぎ足したり捨てたりしたいときは最後の例のように「今のコップaから20だけ引いた量にしてくれ」という表現になります。量の計算にそのコップ自身も使えるわけですね。

 いかがでしたか?始めは記号からイメージがしづらいですが慣れてしまえばそれほど難しいものではありません。序盤にも書きましたがとりあえず算数の”=”と別物と思って使っていればすぐにマスターできると思います。

【Unity】Vector3がざっくりわかるはなし

 先にざっくり言ってしまうとVector3は
3座標よくばりセットです。

 意味がわからないと思いますので噛み砕いていきますが、座標や次元という言葉がピンとこない方は先に「座標と次元がざっくりわかるはなし」をご一読ください。また、変数についても「変数がざっくりわかるはなし」でご一読いただければと思います。

 XYZで示される座標は3つ揃ってやっと1つの情報になっています。もし突然「3階に集合」と言われてもどこのビルかわからなければ誰も到着できないようにどれか1つの座標情報だけでは活用先は限られます。

 そこで3つの変数をセットにしているのがVector3です。
 色々と便利な機能もあるのですが、本来の役割は本当にただそれだけです。

少し具体的に

 全ての座標を0でatsumareという名前で宣言する(作る)場合次のように書きます。

Vector3 atsumare = new Vector3();

 最初からXYZ =(30, 50, 3)で宣言したいときは

Vector3 atsumare = new Vector3(30, 50, 3);

 XYZそれぞれの値を知りたいときは次のように書けば利用できます。

atsumare.x
atsumare.y
atsumare.z

 特定の座標の値を変えることもできます。

atsumare.x = 100; //X座標を100にする
atsumare.y = atsumare.y + 1; //Y座標を1増やす 

 また、変数otameshiにatsumareのx座標を入れたいなら

float otameshi;
otameshi = atsumare.x;

 このようにVector3の名前に.xや.yを付け足すだけで普通の変数と同じように座標を操作することができます。

 1つよくある落とし穴のポイントとしてはTransform【トランスフォーム】コンポーネントで定義されているPosition【ポジション】などはVector3型ですが直接座標を操作できない点です。

//よくあるエラーのパターン
gameObject.transform.position.x = 100;

 これは一旦別のVector3型の変数を宣言してそれを代入することで解決できます。

//エラー回避サンプル
Vector3 otame = new Vector3(100, 0, 0); //(100,0,0)で初期化
gameObject.transform.position = otame;

//X座標以外いじりたくないなら
Vector3 otame2 = gameObject.transform.position; //ポジションを代入
otame2.x = 100;                                 //X座標だけ100に
gameObject.transform.position = otame2;

 勿論上記のサンプルは一例です。使い所や作りたいプログラムによって最適な書き方は変わります。

変数がざっくりわかるはなし

 プログラムをつくる上でほぼ避けて通れない概念の1つ、「変数」についての記事です。

 先にざっくりしたイメージでいうと
変数コップみたいなものです。

 コップは中に色んな量の水を入れておけます。
 変数の機能はシンプルにただそれだけなのです。大きく2つにわけてまとめてみました。

①量を変える
 水の量を増やしたり減らしたりできるように、変数の数値も変えることができます。+10したり100ぴったりにしたりという命令ができます。

②量を読み取る
 水がどのぐらい入っているか測ることができるように、変数の数値も読み取ることができます。注意したい点は水の量を変えてしまうとさっきまでの量がわからなくなることです。逆算しない限り今の量しか読み取れません。

 プログラムではこのコップ同士を比べたり、その結果に応じて命令を変えたりして変数を利用します。活用法は色々あるのですが、最初はざっくりコップのようなものだと思っていただければ大丈夫です。

座標と次元がざっくりわかるはなし

 ゲーム作りではとても重要な概念の1つ、「座標」についての記事です。

 先にざっくり言ってしまうと、
座標とは「ココ!」を正確に伝えるための決まりです。

 意味がわからないと思うので噛み砕いていきます。
 あなたは今まっすぐな一本道を歩いているとします。駅から伸びる道沿いには建物が並んでいますが、どれがゴールかわかりません。しかし「駅から50m」という情報を持っていればどうでしょう。これならなんとなくわかるかもしれません。
 もし駅に立てる看板に何の図もなく「ココ!」という文字しか書かれていなかったら誰もゴールできません。でも看板に「この先50m」と書いてあればみんなゴールできそうですね。この50mのように数値で伝えることができるのが座標です。

 続いて今度は下の地図のようなゴールを看板で伝えてみましょう。

  トータル80mでも交差点がいくつかあればどこで曲がっていいかわからなくなってしまいそうです。 30mと50m、どうしても2つの数値が必要になりそうです。このようにそれぞれ別の意味を持つ2つの数値が必要になるものを二次元と呼んだりします。逆に言うと「平面上のココ!」は2つの数値だけで伝えることができるのです。

 さて、ゴールに到着しても建物が40階建てのビルだとしたらどうでしょうか。高さを伝える必要がありますね。今度は第3の数値として「何階か?」という情報があれば良さそうです。こうなると別の意味を持つ数値が3つになったので三次元です。二次元のときと同様に「空間上のココ!」3つの数値があれば伝えることができます。

 このように数値で伝えるための決まりが座標です。
 実際はもっと少ない情報で正確に伝わるように単位を統一したり符号を付けたりします。次元は英語でDimension【ディメンション】なので2D、3Dなんて呼んだりもします。
 冒頭に書いた 「ココ!」を正確に伝えるための決まりという意味がなんとなくイメージできていれば幸いです。