おはよう、現在ゲーム制作にUnityを使っている。
ウディタからUnityに切り替えて3か月がたち、
だんだん操作がわかってきた。
一方C#スクリプトは基本しかわかっていないが、
3か月もたつとだんだん「すべきこと」が見えてきた。
いかに3か月程度でスクリプト文法を身に着けるか?
発展途上ながらもわかった部分について書いていく。
なぜC#は難しい?
Unityに触れるまで、私はC#を一度も触れていない。
初めて親しむ言語の勉強で、
まずは基本中の基本「スペル」から知らねばならぬ。
C#といってもUnity独自の関数や表現がある。
スクリプトリファレンスを調べたら、数多くあり絶望した。
解説動画を見ても、何をやっているのかよくわからない……
なぜ狙い通りのプログラミングを行うのに、
それをしなければならないのか?
理由がわからず、絶望が多かった。
プログラミングの役割

Unitで行うべきプログラミングはいろいろある。
色々が頭を悩ます要因だが、突き詰めていけば一つ。
「メイン装置の補助道具」
例えば向きによってキャラの立ち絵を変えたいとする。
3Dなら移動によって向きを変えたいとする。

SpriteRendererというコンポーネントにFlipという場所がある。
(日本語表示だと反転と書いてある場所だ)
※SpriteRenderer(スプライト)とは画像の向きや色などを決める道具
アニメ表示する時にも「分割」できる機能がある。
Unityで使う英単語は基本スペルが長いため、
スペルミスによるエラーを起こしやすい。英単語はコピペしよう!
作成時は自分でチェックを入れると左右に反転できるが、
ゲームプレイ時はボタン入力によって変えたい。
※画像を固定したまま左右に動くだけ。
プログラミングを組んで、
ボタンと同時に向きを変えていかねばならぬ。
そこでUnity内から「作成」でC#スクリプトを作る。
一度名前を決めたら削除しない限りエラーを起こすので注意。
作成したら、主人公や敵キャラなど、
「動かす対象」に向けてスクリプトを代入(アタッチ)させる。
代入前後でいいから「コンポーネントを追加」して、
SpriteRendererを入れるといい。
あくまでもスクリプトは「メインでできない細かい設定」を、
サクサク行うためにやる補助手段だ。
一つのスクリプトが一つについた。
「このC#はここでしか機能しませんよ」と意思表示できたわけだ。
簡単に作成していく。
public class PlayerMove : MonoBehaviour
{
private SpriteRenderer spR;
void Start(){ //剛体を呼び出す
this.spR = GetComponent<SpriteRenderer>();
} //start
void Update()
{ //左右入力で動く
float x = Input.GetAxisRaw("Horizontal") ;
//向き反転かどうか
if ( x < 0 ){
spR.flipX =true;
} else if ( x > 0 ){
spR.flipX =false;
} //flip if
} //Update
} //public class playerMove
※//は「コメントアウト」を示す。
プログラミングは「定義→分岐(あれば)→代入」からなる。
初期値にprivate SpriteRenderer spR; と入力し、
「SpriteRenderer用として、spRという箱(変数)を使います」と宣言する。
数学で言うなら、次のようにざっくり捉えてほしい。
「横座標軸の定義(→SpriteRenderer)をX(→spR)と置きます」
最初に定義をしなければ、スクリプト側がエラーを出してくる。
私たちは座標といえば「xy軸」と定めているけど、
場合によってはuv、ReIm軸など色々あるからね。
プログラミングの難しさは私たちの脳内にある。
脳内では「すでにわかってる、定義するまでもない」決め事を、
こちら側で定めていかねばならないんだ。
プログラミングを行えば、いかに脳みそが便利で優れているか!
嫌というほどわかるよ。
最初に定義を行った。次に入ろう。
void Start{spR = GetComponent<SpriteRenderer>();}と書いて、
spRはComponent<SpriteRenderer>から値をとります・変えますよ。
宣言していくわけだ。再び定義するわけだ。
getComponentは「コンポーネントを追加」し、
SpriteRendererをインスペクター内に入れていないと無意味だ。
※void Startはゲームプレイボタンを押したとき、
すぐさま反映するための道具と思ってほしい。
次にvoid Update{
float x = INput.GetAxisRaw(“Horizontal”);
//ボタンを定義する。左右の矢印キーを押したら、キャラが動く
//値は-1か0か1のどれか。
後は条件分岐を行って、向きを決めていく。
if (x < 0 ) { //左向き
spR.flipX =True;
} else if (x > 0 ) { //右向き
spR.flipX =False; }
} //Updateはここまで
キャラが最初から右向きなら、trueとFalseを反対にすべし。
また数学の座標を思い浮かべてほしい。
マイナス座標なら左、プラス座標なら右だ(YやZも同じ)。
始めて手を出した人は一つ疑問が出るだろう。
「flipXってどこから持ってきたんだ?」

上記画像はUnityマニュアルから持ってきた、
英語(正式)verのSpriteRendererだ。
日本語では「反転」と書かれた部分が、
英語では「Flip」と書いてあるね。
上記プログラミングにて、ボタンを左に押すと、
True=チェックボタンを入れた状態となり、向きが変わる。
一方右にボタンを押すと、
False=チェックボタンを外した状態となり、向きはそのままだ。
スクリプトは「コンポーネント設定だけでは無理な細かい役割」を、
支えてくれる素材として考えるといい。
もちろんUIなど例外(監督要素など)もあるけど基本は「補助」だ。
スクリプトリファレンスの観方

Unityは独自のスクリプトがある。
独自だからこそ迷うし、何をしたらいいかわからなくなる。
特に上記画像左のリスト欄を見たら……絶望だ。
リファレンスがあったとしても
「何をすればいいかわからない」から問題だ。
そこで記事を書いている自分も理解するため、
先ほど載せたSpriteRendererを見ていこう。
一つずつ分けてみていくと……
- 変数
- 継承メンバー-変数
- Public 関数
- Static 関数
- Operator
- メッセージ
分かれていて、何がなんだかわけわからないね。
そこで一緒に見ていこう。
変数とは?

変数は「Unity内で定義しなくても最初から使える道具」だ。
スクリプトでなく普通の編集画面にて
SpriteRendererをコンポーネントに追加し、見てほしい。
変数は上記画像の部分と見事に対応しているんだ。
(自分は日本語で設定しているけど、変換すればわかるよね)
spR.flipX =True;を見てほしい。「flipX」と書いた。
上記変数にも「flipX」の項目があるのを確認してほしい。
Unity内であらかじめ定義してくれているから、
わざわざ冒頭でflipX=適当な変数;とおかなくてもいい。
実際にflip.Xをクリックすると、超簡単な説明が出ているが……
よくわからないので、グーグルやほかの人のやり方を参考に、
プログラミングを創っていくといい。
継承メンバーとは

次に継承メンバー-変数だ。
継承とはメンバー変数やメソッド(関数)など、
あるクラスの引き継いで、新しいクラスを作る行為だ。
……いまいちよくわからない。
数か月たって継承を作り、やっと体で理解できた。

継承は親元を作って「ここだけ変えたい」子を創る。
それぞれ親を創るやり方もありだが、
それぞれ親を創ると、必ず重複する関数が出てくる。
敵のスクリプトを創るにあたり、敵も数種類分けると、
歩いたり、壁との当たり判定などで別の敵スクリプトと重なってしまう。
重なりを一つにまとめる役割こそ継承の働きだ。
記事を書いてから数か月後、継承にて苦労したので記事を書いた。
パブリック(Public)関数とは

続いてパブリック関数を見ていきたい。
対象物を動かす際に必要なRigidbody2D.AddForceがある。
最初に private Rigidbody2D rb2D;を出して箱rb2Dを用意し、
Startでrb2D = gameObject.AddComponent<Rigidbody2D>();を用意。
rb2Dはコンポ―ネットにくっつけたRigidbody2Dにのみ働くよと宣言。
後はアップデート関数(void Update)にて、
Vector2 force = new Vector2 (0.0f,1.0f);
rb.AddForce (force);
newと新しくもうけ、自分で数値を入れていいんだ。
新たに座標を設定するよと表示したのだから。
と入力すれば、.AddForceは上向きに動く。
変数.Public関数という形で書けるのね。
Public関数は初期設定やスタート関数におかず、
いきなり変数.Public関数という形で使用できるのね。
スクリプト:Rigidbody2D
継承メンバーパブリック(Public)関数とは

Public 関数にはもう一つ、継承からのパブリック関数がある。
継承型Public 関数で一番使うのがGetComponentだろう。
パラメーターがあり「type」と書いてある。
先ほどのスタート関数(ゲームプレイ時、すぐ軌道するプログラム)で
{spR = GetComponent<SpriteRenderer>();}書いたね。
現時点で()が空欄であり、typeは何も入れていない。
何も入れていない=すべて入れるよ。と思えばいい。
リファレンスでは
HingeJoint hinge = gameObject.GetComponent(typeof(HingeJoint)) as HingeJoint;
hinge.useSpring = false
※asはas演算子であり、データ型を変換できる装置。
hingeからHingeJointへ強引に変えたとみていいのね。
スタティック(Static)関数とは

Static 関数とは「あれば勝手に働く関数」と定義しておこうか。
例えばDestroyがある。
パラメーター「()の中身」は「対象物、時間」に分かれている。
公式の使い方だと対象物は必須だが、時間は必須でないみたいだ。
Destroy(gameObject);
Destroy(GetComponent<Rigidbody>());
Destroy(gameObject, 5);
void Update () { Destroy (this.gameObject); }
記述したとしよう。
敵キャラAにスクリプトをくっつけた(アタッチ)状態で、
ゲームプレイボタンを押すと、敵キャラAは即座に消える。
SpriteRenderer内においてDestroy関数を使ったら、
SpriteRenderer.Destroyと示していなくても、
「あ、Destroyはワイの領域にあるプログラムね。
わかった、命令通りに消しておく(Destroyとしての仕事を行う)わ」
限定して働いてくれるプログラムだと思ってほしい。
Static 関数はほかでも使えるからこそ、少しややこしい。
一方、一つ設定すればすべて消してくれるから便利ともいえる。
オペレーターやメッセージ

オペレーターを見ていくと、単純に論理演算に関する記述であり、
他の部分でも併用ができる。
スプライトにはもちろん、リジット他にも影響を与えますよと見ていい。
メッセージは現時点で正直わからん(すまぬ)。
重要は変数とpublic,static
リファレンスを調べたおかげで、
Unityスクリプトで重要な部分は三つとわかった。
主に三つの部分–変数、public、static–に注目し、
一つずつ改造をこなしていくといい。
特にstaticは別のシーンファイル(scene)に移動する時、
例えばHPをそのまま引き継ぐ時に使える。
またゲームプレイ中かどうかを識別する時も使える。
さらに別スクリプトから変数や関数を参照する時にも使える。
これらは後で述べる関連記事に書いたから、読んでほしい。
後はエラーについてどう対応すればいいかがわかれば、
スクリプト編集にあまり困らなくなるだろう。
スクリプトの勉強法

最後に2か月の間行ったスクリプトの勉強について触れる。
まず一冊の本を購入し、YOUTUBEにある基本動画を見て、
実際にスクリプトを打ち込んでいく。
難しく考えず、習うよりも真似る。
真似てだんだん疑問を抱きだしてから、設定についていろいろ書き込む。
といっても私の記憶力だと数秒で忘れてしまうから、
何度も使っては振り返って、体に覚えさせていくしかない。
ある程度慣れてきたら、今回の記事のように、
「なんとなくわかっている」分野をきちんと掘り下げていく。
わからない場合は検索サイトを使って、
スクリプトを調べたのち、スクリプトの基本用語を改めて調べる。
スクリプトがわかれば、後はゲーム完成まで早い……はず。
ちなみにスクリプトでわかっている部分について、こちらにも記事を書いた。
他スクリプトファイルからの参照方法、軽量化などを載せているよ。
後はアニメーションについて「遷移なし(矢印を引かない)」で、
スクリプトのみで動かす方法も載せている。
ぜひ参照してほしい。
