【Unity入門】UnityのC#基礎【変数と簡単な演算】

前回は文字を出力して、オブジェクトを移動させるところまでいきました。今回はC#の基本的なことをやっていきたいと思います。

この記事は本のように順を追って解説しています。この記事は途中のページになります。この記事を見ていて、現在の状況がわからない場合や忘れてしまった事などが出てきたら↓のリンクから目次ページへ飛べますので立ち戻って見てください。

<プログラムの流れ>

関数の中の処理の順番

プログラムの世界では処理の順番というものがあり、基本的に上から下へ流れていきます。
例えば↓のように書くと

script_number

↓このように表示されます

log order

上から順番に処理されていることがわかります。

ただ、この順番というのは関数の中だけの話なのでStartとUpdateを反対にしてもStartから処理されます。

関数はどこかから呼び出されたら処理されます。Unity側がStartの方を先に呼び出しているわけです。そのため関数を書いた順序は処理順に関係ありません。

スクリプトが複数ある時のStartとUpdate

ところでスクリプトが2つあるとどうなるのでしょうか。ちょっとやってみましょう。

order script log

↑1個のゲームオブジェクトに新しくスクリプトを作って更にアタッチしてみました。
片方を0として、もう片方を1とします(適当です)
この状態で再生すると↓のようになります。

log start update

1のStart→0のStart→1のUpdate→0のUpdate→1のUpdate→・・・・
ってなっています。
Unityはファイル毎にStart→Updateと呼んでいるわけではなく、全部のスクリプトのStartを呼んで、その後全部のスクリプトのUpdateを呼んでいます。

ちなみに1と0が逆になっているように見えますが、どのスクリプトの関数から呼び出すかはランダムです。ランダムといっても常に変動するわけではなく端末ごとに変わります。自分のPCでは1→0でしたが、他の人のPCでやると0→1になる可能性があります。

このようにプログラムには処理をする順番があるということを覚えておいてください。

Point

・プログラムは関数の中では上から下に向かって処理していくよ!
・関数は何かから呼ばれる事で処理されるよ!
・Unityが定義した特別な関数は、Unity側が呼び出す順番を決めているよ!
・この特別な関数は同じ種類の場合どれが先に呼ばれるのかは端末によるよ!

<変数>

変数とは

プログラムを覚えていく上でこの変数というものは重要です。変数というのは箱のようなものと覚えておいてください。といってもよくわからないと思うので実際にみてみましょう。

int

↑なんか関数の外に int a = 1;と書いてあります。これが変数です。
intというのは箱の形です。aというのは名前です。今回は適当に名前をつけました。

これは「intの形をしている箱を作り、aという名前をつけました。そしてその箱に1を入れました」という意味になります。

intってなんやねんって話になりますが、これは「整数型の箱」という意味になります。なので↑は「整数が入る箱aを作り1を入れました」ということになります。この箱の形の事をと言います。

このように変数は○○が入る箱で、名前は自分で決めることができます。
この○○というのは箱の形だと思ってください。決められた形の物を入れることができるのです。

箱と例えましたが、実際はメモリ領域の事をさします。↑の宣言では「整数が入るだけのメモリ領域を確保しaと名付けました、その中に1を入れました。」ということになります。

変数は何に使うのか

じゃあ、この箱何に使うの?って話になるのですが、この箱があるととても便利です。
単純に状態を記録しておくことにも使えますし、↓のようにも使えます。

debug log int

classの中で、関数の外に書いてある変数全部の関数で使用することができます。なんかこれだとあまり意味がないのでこう変えてみましょう。

Convenience of variables

stringというのは文字列の箱です。文字の箱ではなく文字列の箱なので注意しましょう。
さて、やたら長い文章ですが、こんな長い文章Debug.Logの中にいちいち書くのはめんどくさいです。そこで変数に突っ込んでしまえば何回でも使い回すことができます。

Point

・変数は箱みたいな物だよ!
・箱には形があるよ!
・箱の形の事を型と言うよ!

さて、まだまだこれを使うメリットがわからないと思うので次は演算をやってみたいと思います。

<演算>

基本的な四則演算と余り算

演算というとなんか難しいように聞こえますが、ようは足し算とか掛け算とかそういうやつです。

・足し算 : a = 1 + 1;
・引き算 : a = 1 – 1;
・掛け算 : a = 1 * 1;
・割り算 : a = 1 / 1;
・余り算 : a = 1 % 1; (1割る1の余りは0なのでa=0)

と表されます。

ちなみに、C#で「=」は「等しい」という意味ではなく「代入する」という意味になります。 例えば

int a = 1;
a = a + 1;

という不思議な式が成り立ちます。数学ではa=a+1なんて式は成り立たないのですが、C#ではaにa+1を代入するという意味なので、aには2が入ります。

等しいを表すには

等しいかどうかというのは「==」で表します。

ただしプログラムの世界では「等しいという事実」があっただけではコンピュータはどうしていいかわからないので(事実ではなく命令が必要)

int a == 1;

と書いてもエラーになります。等しいかったら○○をするというような書き方をする必要があります。この解説についてはまた次の機会にしたいと思います。

計算式の省略

ちなみに、前回「+=」というわけわからん記号を使いましたがあれは計算式を省略しているだけです。

a = a + 1;

の場合

a += 1;

と書けます。代入時に自分と同じ箱を使う際は「記号=」で省略することが可能です。
-=とか*=とか/=とか%=とかもできます。

インクリメント・デクリメント

1足すだけとか1引くだけなら更に省略することができます。

a = a + 1;

++a;

と書いても同じ意味になります。

a = a - 1;

--a;

と同じ意味になります。

ちなみに1で掛けようが割ろうが余ろうが結果が変わらないので「**」とかはありません。

//だったらコメントになっちゃうし

この++をインクリメント、–をデクリメントと言います。

インクリメントとデクリメントは変数の後に書く事もできます。

a++;
a--;

こんな感じです。

変数の前に書くか後に書くかでちょっと意味が違うので気をつけてください。

int a = 0;
int b = ++a;

と書いた場合bは1になります。

int a = 0;
int b = a++;

と書いた場合bは0になります。

これは、++aは演算を先に行うと言う意味で、a++は演算以外の処理を先に行ってから演算を行うと言う意味になります。

そのため、a++と書くとプラス1される前にbに代入されてしまうので、aは1になってますが、bは0になるのです。

覚えておきたい

・足し算は「+」
・引き算は「-」
・掛け算は「*」
・割り算は「/」
・割り算の余りは「%」
・「=」は代入
・「==」は等しい

Check

・変数自身への計算は「記号」=で省略できるよ!(例 a+=1)
・++変数で変数を1増やせるよ!この処理は先に行われるよ!
・変数++で変数を1増やせるよ!この処理は後に行われるよ!
・–変数で変数を1減らせるよ!この処理は先に行われるよ!
・変数–で変数を1減らせるよ!この処理は後に行われるよ!

<小数点以下の計算>

float

さて、ここで少し疑問に思った人もいると思います。

intは整数型の箱だけど、少数以下が出たらどうなんの?って話です。

結果は切り捨てになります。箱の中に入らないのです。

int a = 1 / 2;

と書いた場合、a は 0になります。小数点は切り捨てなので0.5は0になります。

じゃぁ、小数点以下が欲しい時はどうすればいいのって話になるんですが、ちゃんと小数点以下が入る箱があります。

といっても、小数点以下が入る箱の種類というのはたくさんあるので、一番よく使われる型を紹介します。float型です。

float a = 1 / 2;

とした場合、a は 0になります。

ん?0?0.5じゃないの?って話なんですが、これにはワケがあります。

実はC#というのは暗黙的に型変換というのを行なっていて、箱の形を自動で判断して計算してくれています。つまり↑の式では

float a ← これは小数点以下が入る箱
1 ← これは整数
2 ← これは整数

1 / 2 は整数同士の計算ですので自動でint型として判断されます。

ようは

float a = (int)1/ (int) 2;

となっているので、1/2をした際に切り捨てられて0になった後、float型に代入されたという形になります。

サフィックス

では少数を扱うにはどうすればいいかといいますと、最後にfをつけます。

float a = 1f / 2f;

と書きます。

最後にfとつけることで、これはfloat型ですよと明示することができます。
これで、aは0.5になります。

このように数字を扱う型の場合、数字の最後に型の頭文字を書くことその数字の型を表す奴のことをサフィックスといいます。

ちなみに

float a = 0.5 / 0.1;

と書くと今度はエラーになります。これは箱の種類が違うからですね。

少数の後に何もサフィックスをつけないdouble型という奴で扱われます。

floatという箱に入れようとしているのに、実際に入る数値がdouble型だから違うぜ?と言っているわけですね。

float a = 0.5f / 0.1f;

が正解です

double型かfloat型か

サフィックスなんてつけるくらいならdouble型でよくね?って話なんですが、なぜfloat型の方がよく使われるかというと、float型よりdouble型の方がデカいからです。

float型の有効桁数は7桁です。一方double型の有効桁数は16桁です。

一応float型は3.4×(10の-38乗)から3.4×(10の38乗)まで表現できますが、○○○E+△△みたいな指数表現になる上に○○は7桁までです。double型は1.7×(10の-308乗)から1.7×(10の308乗)まで表現できます。

このように表すことができる桁が違います。何故このような違いが起きるかといいますと、コンピュータのメモリ領域や計算速度が限られるからです。

メモリは無限ではないので、小数点以下無限桁数持つわけにはいかないのです。また、CPUの処理能力も限られるので無限桁数の計算などできません。そのため、型によってどれぐらいまでの桁数計算できるかあらかじめ決めておいて、その分だけのメモリを確保しようというわけです。

そのため、float型の方が表せる桁数が少ないですが、double型より小さく、メモリ効率がよく使いやすいのでfloat型の方がよく使われるということです。

7桁以上の桁数を使う場面というのはそこそこ限られていますからね。もちろん桁数が必要な時はdouble型を使用した方がいいです。7桁目まで計算しているとはいえ、あぶれた桁数は切り捨てられているので計算に誤差が生じる場合があります。その点で言うとdouble型の方が計算精度が高いです。

ちなみに

float a = 0.5 / 0.1;

がエラーだったのは小さい箱にデカい中身をぶち込もうとしたのでエラーだったわけです。

逆だとC#が自動で変換してくれます。

double a = 0.5f / 0.1f;

だった場合はエラーになりません。ただし、int型の時みたいにfloat型が持ってない桁は切り捨てられますが。

Point

・変数の型には大きさがあるよ!
・大きさが違うとC#が自動で変換してくれるよ!
・変換された時に余分な情報は切り捨てられるよ!
・型が大きい物から小さい物への変換はできないよ!
・数字の後に型の頭文字をおく事で数字の型を指定できるよ!

<変数の範囲>

関数の外に変数を書くと全部の関数で使う事ができると解説しましたが、関数の中で使う事もできます。

scorp

↑のように関数の中に書く事もできます。関数の中に書いた場合は、その関数の中でしか使う事ができません。

変数名は基本同じ名前の物を使うことはできないのですが、変数の有効範囲が違えば同じ名前を使う事もできます。

この変数の有効範囲をスコープと言います。

また、このスコープは{ }で囲まれた範囲になるので、{ }の中に書いてある変数は{ }の中でしか使えません。

{ }内を有効範囲と書くと{ }の中ならどこでも使えそうですが、変数を書いた位置から下じゃないと使えないので注意してください。関数の外に書いた変数はその限りではないのでこれも注意してください。

Point

・変数には有効範囲があるよ!
・有効範囲の事をスコープと言うよ!
・スコープは変数を書いた位置から } が書いてある位置までだよ!
・関数外に書いた変数は書いた位置に関係なくclass内で使う事ができるよ!

<配列>

たくさんの変数が欲しい時

時に変数をたくさん用意したい時という場面があると思います。そういった場合、たくさん箱を用意してあげないといけないのですが、いちいち

int a = 1;
int b = 2;
int c = 3;
//・・・(以下略)

と書いていては大変です。
そういった場合は配列を使いましょう。

int[] a = new int[3];

↑のような感じで書きます。これはint型の箱が3つあるという意味になります。

これの使い方は

型名[] 変数名 = new 型名[用意する数];

になります。

new新しく作成するという意味です。

↑の状態では箱を用意しただけですので中身を入れていきます。

int[] a = new int[3];
a[0] = 1;
a[1] = 2;
a[2] = 3;

と書きます。これで先ほどと同じように3つの箱に数字を入れることができました。

変数[何番目か] = 入れる値;

で箱の中に中身を入れる事ができます。ただし、この何番目かというのは1からではなく0から始まります

↑の例では3つの箱を用意していますが、0,1,2で3つの箱になっています。そのため

a[3];

と書くと、3つしか箱用意してないのに4つ目やんけという事でエラーになります。

またいっぺんに入れることもできて、

int[] a =  {1,2,3};

と入れても箱の中に値が入ります。

箱の箱・配列

この

int[] a = new int[3];

のaは値ではなく箱の箱として扱われます。

なんかややこしいですが、「a[番号]」が箱であって、「a」は[番号]が入る箱なわけです。

このような箱の箱の事配列といいます。

そのため

int a = new int[3];
++a;

みたいなのはエラーになります。aは値ではないので。

ちょっと発展系になるのですが、箱をたくさん並べることもできます。

int[,,] a = new int[3,4,2];

↑のように書くと箱が3つの箱の中にさらに4つの箱があり、さらに2つの箱があるという意味になります。

Array

たくさんあったので書ききれなかったですが、○が値入れる事ができる箱とすると↑のような形になります。

一番上の箱がaでその中に3つ箱があって、さらにその中に4つ箱があって、さらにその中に2つ箱があって、その中に値を入れる事ができるよう感じです。

なんだかよくわからないという人はいづれ使うときになったら実戦で解説しますのでこんなものがあるよって事だけ覚えておいてください。

<既存クラスの変数を扱う>

さて、前回

transform.position += Vector3.right;

これを使ってCubeを移動させてたと思うのですが

move

transformもpositionもrightも変数です。

前回オブジェクト指向は「設計図」と「実態」と例えていました。class ○○○というのは、「これは○○○という名前の設計図ですよ」と言っていました。変数は箱のようなものだと例えていました。

オブジェクト指向はこの設計図型の箱を用意することができます。

最初ややこしいと思いますが、なんとなく覚えてください。なんとなくで大丈夫です。

transform variable

Transformは位置、回転、大きさの情報を保持するclassです。(コンポーネントでもあります。というかコンポーネントは全てclassです。)
Vector3は3つの数字の情報を保持するclassです。(x,y,zなどを表すのに使います)
これらの形の箱を用意して、その中に値を入れているわけです。

transformというのはTransform型の変数名前がtransformです。この名前誰が決めたんだよって話なんですが、MonoBehaviourを継承しているからです。MonoBehaviourがtransformという変数を持っていて、継承しているから使えるわけですね。

正確にはMonoBehaviourが持っているわけではなく、MonoBehaviourも継承によってtransformを元のスクリプトから得ていてます

さて、ではpositionという変数はどっからきたんだって話なんですが、これはTransformという設計図Vector3型の箱「positon」を持っているからです。

あなたが書いたclass(設計図)にTransform型の変数(箱)があり、名前をtransformと言います。その箱の中に更にVector3型の箱「positon」が入っています。マトリョーシカみたいですね。

Contents of class

↑のように箱の中に箱が入っている感じです。

箱の中のものを参照する際は「箱の名前.箱の中身」とします。「.」で内部へアクセスする形です。

本来は変数(箱)にインスタンス(実体)を入れなければいけないのですが、今回はMonoBehaviourが自動でやってくれています。

このようにTransformVector3もclassなので設計図なのですが、その設計図を元にした形の箱を作ることができます。

プログラムはこのように設計図を作って、その設計図を利用した箱を用意して、その中に実体を入れて使うといった行いを頻繁にするので覚えておくといいでしょう。

ちなみに、Vector3.rightというのはC#があらかじめ中に(1,0,0)という実体を入れてくれているので何もしなくても最初から使えます。

<まとめ>

さて、ここまで色々解説してきましたが、なんだかよくわからないよという人は「設計図」「箱」「実体」っていう3つのワードをなんとなーく頭に入れながら、人のやっている事を真似していけばなんとなーくわかってくると思うので今はなんとなーくの理解で大丈夫です。

苦手な意識がある人もわからない人も、あーわからんと投げ出さずにとりあえずなんとなく真似てみましょう。

最後に今回出てきた覚えておいて欲しい型について書いておきます。

覚えておいて欲しい型(値を入れるもの)

・int・・・整数型
・float・・・有効桁数7桁の浮動小数点型
・double・・・有効桁数16桁の浮動小数点型
・string・・・文字列を表す型

覚えておいて欲しい型(class型)

Vector3・・・x,y,zの3つの数字を便利に取り扱える型
Transform・・・位置、回転、大きさの情報を取り扱う型

Check

型名[] で配列というたくさんの箱を用意する事ができるよ!

型の中でもいろいろ種類があって、↑の2種類は型であってもちょっと違うので分けて書いてあります。何故違うのかはまた後々解説していきます。

<わからない事があったら>

このサイトの説明ではよくわからなかったとか、もっと知りたい事などがあれば、また別の勉強方法があるので違った切り口を使ってみるのもいいと思います。

<オススメの本>

本で詳しい解説がされているので書籍を買ってみるというのも手の一つです。最近はKindle版があるので届くまで待つ事もなく場所も取らないのでとても良いです。

<オンラインスクール>

オンラインスクールでは人に質問する事ができるので、行き詰まってしまった方にオススメです。 無料体験もあるので試しに見てみるのも手ですよ




次回もプログラムの解説は続きますのでよろしくお願いします。




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