前書き
Unityでゲームを作る時にコピペしていると読んでいて理解できないプログラムがあるなあ。そもそもこの文字って何?
と、プログラミング初学者の人達に聞かれがちだったことをまとめていたメモを掘り出したので、折角ならと公開してみる。
Unity以外のプログラミング言語にも使えるくらい基礎的な場所だが、独自解釈なのでもし何か勘違いしている箇所があればコメントしてほしい。
変数
プログラムを書くときに絶対出てくるであろう変数という存在は一体何なのか。
数学の方程式を習っている人はいわゆるxのようなものだと思って欲しい。
簡単にいうと数値や文字などの値を入れるための箱のようなものである。
例えば、ももが一個、りんごが二個あるとする。その合計値を求めるときにどうするのか?
1 + 2 = 3と求めるのではないだろうか。
これをプログラム上で扱うときには一度、変数という箱に入れると便利になる。
peach = 1
apple = 2
peach + apple
というように書くのだ。
結果的に同じじゃない?わざわざ入れる必要ある?
この変数が効力を発揮するのは、数値が変わるとき同じ式を使えるというところにある。
ももが二個になった時、りんごが一個になった時、数式で書くと全て書き直すことになる。
だが変数を使うとどうか、
peach = 2
apple = 1
とすれば全く同じ式を使って求めることができるのだ。
型
では上記の変数はただ名前をつけてあげれば使えるのか?
使える言語もある。でもUnityで使われているC#でのプログラミングではあらかじめ「型」というものを定義してあげる必要がある。
変数は箱のようなものといったが、型とはいわゆる箱のサイズや形を決めるものだ。
現実世界でも飴玉一つを入れる箱と、ベットを入れる箱とではサイズも形も異なるはず、それと同じであらかじめ入れるものに合わせた箱を用意してあげる必要がある。
よく使う型には以下のようなものがある。
型名 | 意味 | 使用例 |
---|---|---|
int | 整数 | 1 |
float | 少数 | 1.5f |
string | 文字列 | "hello" |
bool | 真偽値 | true |
Vector3 | 三次元ベクトル | new Vector3(0,0,0) |
では型を知ったところで変数の宣言の仕方を見てみる。
変数はこのように宣言する。
型名 変数名 = 初期値
例1
整数型の変数xを宣言する。初期値は1にする。
// テンプレート
// 型名 変数名 = 初期値
int x = 1;
最初に = 1 を書くことで初期値として1を入れている。
一回宣言したらこのxはプログラム内で好きに使える。ただし、xに整数以外を入れようとすると怒られるから注意しよう。
例2
同じく整数型の変数xを宣言する。
// テンプレート
// 型名 変数名 = 初期値
int x;
初期値は?C#では今は一応なくても大丈夫。
ではこの時のxには何が入っているのか、それはC#が決めた規定値が入れられている。今回の場合は0である。
(規定値の参考にどうぞ
->https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/default-values)
他の値を使いたい時はちゃんとxに別の値を入れ直さないといけない。
関数
メソッドとも呼ばれる。C#だとメソッドの方が主流かもしれない。
毎回毎回同じことを指示するのは大変だなって時に便利なもの。
アクセス演算子 返り値 関数名(引数){
// 実行したい内容を書く
}
こんなの見たことない?いや、あるはずだ。
例えばUnityでプログラムを書こうとした時、下のような内容が最初から書かれていただろう。
void Start(){
}
このStartも実は関数なんだ。
アクセス演算子
関数や変数などがどこからなら参照できるかという制限をつけるもの。
関数や変数は何度も同じ処理をしたり、何回も同じ数字を使ったりする時に役立つという話を上に書いていた。
この"使う"が例えば同じclass内でしか使えないだとか、別ファイルからでも参照できるだとか、その範囲を決めているのがこのアクセス修飾子だ。
参考までによくみるものの意味だけ下記にまとめておく。
(より詳しく知りたい場合には->https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers)
アクセス修飾子 | アクセスの制限 |
---|---|
public | アクセス制限なし |
private | そのクラス内のみ使用可能 |
省略する場合にはprivateと同じ扱いになる。
引数と返り値
関数を使う時に値のやりとりをしたい場合に使う。
関数とは実は何かを与えられたら何かを返すという動きをするものなんだ。
引数は与えるもの。関数を実行するときに必要な値があるときにその値を書く。
返り値は返すもの。関数を実行した後に、使いたい値がある場合にその型を書く。
例を参考にしながら知ってほしい。
例1
Hello Worldをコンソールに出力する関数Hello。
Startで呼び出してみる。
意味 | プログラム |
---|---|
コンソールにHello Worldと表示する | Debug.Log("Hello World") |
void Start()
{
Hello(); // Helloを呼び出す。Hello Worldがコンソールに出力される。
}
// Helloの宣言
/* テンプレート
アクセス演算子 返り値の型 関数名(引数){
// 実行したい内容を書く
} */
public void Hello()
{
Debug.Log("Hello World");
}
例2
足し算の結果をコンソールに出力する関数Plus。
Startで呼び出してみる。
意味 | プログラム |
---|---|
x と yを足した値をanswerに入れる | answer = x + y |
コンソールにanswerの値を表示する | Debug.Log(answer) |
void Start()
{
Plus(1,2); // Plusを呼び出す。1と2を渡すことでPlusでは1+2が行われ、answer(=3)がコンソールに出力される。
}
// Plusの宣言
/* テンプレート
アクセス演算子 返り値の型 関数名(引数){
// 実行したい内容を書く
} */
// 引数に整数xと整数yをとる。
public void Plus(int x, int y)
{
// 整数型の変数answerにxとyを足した結果を入れる
int answer = x + y;
// コンソールに表示
Debug.Log(answer);
}
例3
足し算の結果を返す関数Plus。
Startで呼び出してその結果をコンソールに表示する。
意味 | プログラム |
---|---|
Plus(1,2)の返り値をanswerに入れる | int answer = Plus(,) |
コンソールにanswerの値を表示する | Debug.Log(answer) |
x + yの値を返す | return x + y |
void Start()
{
int answer = Plus(1,2); // Plusを呼び出す。1と2を渡すことでPlusでは1+2が行われ、3が返ってくるので、その結果をanswerに入れる。
Debug.Log(answer);
}
// Plusの宣言
/* テンプレート
アクセス演算子 返り値の型 関数名(引数){
// 実行したい内容を書く
} */
// 引数に整数xと整数yをとる。整数の足し算は整数になるので返り値には整数型であるintとかく
public int Plus(int x, int y)
{
// xとyを足した結果を返す
return x + y;
}
ここまで読んで、関数は何か与えて何かを返すものであるはずなのに与えているだけだったり、返しているだけだったりしていることに気づく人がいるだろう。
Start()なんてそのいい例だ。
返り値に関して、何も返さないときは
Unityで最初に用意されているスクリプト
Unityでプログラムを書こうとすると決められたプログラムが勝手に出てくるはずだ。その内容について軽く解説していく。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
// Start is called before the fiest frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
using
一番上にusing 〇〇が続いている。
これは「〇〇という機能を使いますよ」と宣言している。
ここで宣言してあげることで、色々な機能を使ってプログラミングができるようになる。
class
classとは何か、簡単に言えば設計図のようなもの。変数や関数など機能をまとめたもので、これを組み合わせてC#ではプログラムを作成していく。
public class 〇〇の〇〇にはスクリプトの名前が入っているはずで、〇〇の設計図を書きますよ。ということになる。
アクセス修飾子 class クラス名
{
}
がclassの基本的な形になっている。{}で括られた範囲が設計図の中身となっていて、基本的にclassの外にプログラムを書くことはないと思っていい。
MonoBehaviourってなに?って思う人がいると思う。
これは継承と言って、あらかじめ用意されている設計図を元にしますよ。という意味になる。初めから色々な機能が使えるんだと簡単に考えていい。
コメント
//から始まるものがある。
この記事でも大量に使っているこの//の意味はコメントである。
基本的には書いたプログラムを他の人が見やすいように残しておくメモのようなもので、//以降に書かれた同じ行の文字はコメントとして扱われプログラムとして認識されることはない。
ちなみに複数行をコメントにする場合には
/*
*/
と書くこともできる。
StartとUpdate
この二つは先ほども言っていた関数。
でもこの二つはMonoBehaviourを継承しているので、特別な機能が付与されている。
この二つ、どこでも呼ばれてないのに何故動くのか。実はこの二つはUnity側から勝手に呼ばれている。
Startはこの設計図がゲームで使われる瞬間一度だけ呼ばれる。
Updateはこの設計図がゲームで使われている間ずっと呼び出し続けられる。
他にもMonoBehaviourによって特別な機能がつけられた関数はいくつかあるので気になったら調べてみて欲しい。
Unityのプログラムの構造
結局Unityのプログラムってどうなってるの?どうやって書いていくの?
構造を理解するって意味でざっくり流れを書いてみよう。
基本全てはclassの中、classは設計図のようなもの。これからプレイヤーの設計図を書いてみよう。
public class Player : MonoBehaviour{
}
ここから外にplayerについてのことなんて書いても、設計図外の落書きのようなもの。この中に書いていく。
ではclassの中には何が書けるの?classの中にかけるものは基本的に二種類
、変数と関数である。
ではまず年齢を書いてみよう。
public class Player : MonoBehaviour{
int old; // 年齢
}
誰しも生まれた時は0歳だ。じゃあ実行時に呼ばれる関数Startのところに年齢は0にするってかこう。
public class Player : MonoBehaviour{
int old; // 年齢
void Start(){
old = 0; // 最初の年齢は0
}
}
年齢は増えていくよね。じゃあ年齢を増やす関数GetOldを作ってみよう。
public class Player : MonoBehaviour{
int old; // 年齢
void Start(){
old = 0; // 最初の年齢は0
}
public void GetOld(){
old++; // old = old + 1のかっこいい書き方
}
}
じゃあ一年経つごとに呼び出してみよう。ずっと呼び出されるのは関数Updateだ。
public class Player : MonoBehaviour{
int old; // 年齢
void Start(){
old = 0; // 最初の年齢は0
}
void Update(){
// もし一年が経過したら if文はこれ以降に解説があるから興味があれば見てみて欲しい
if(一年が経過した){
GetOld();
}
}
public void GetOld(){
old++; // old = old + 1のかっこいい書き方
}
}
という感じでプログラミングはやっていく。この中身を理解するのではなく、構造を意識して見てみて欲しい。
classの{}の中に変数、関数が入っている。関数の{}の中にさらに変数や命令が入っている。
全ての範囲は{}で区切られている。{}を意識してプログラムを見るだけでもきっとミスは減っていくはずだ。
if文
自分でプログラムを書く時に非常に役立つif文とfor文について解説していく。大抵のプログラムはこの二つの組み合わせで作れるので知っておいて損はないよ。
もし〇〇だったら▲▲するを実現するプログラム
if(条件){
// 条件を満たす時に実行したい内容
}else{
// 条件を満たさない時に実行したい内容
}
例1
もしマウスが押されたらコンソールにHello Worldと表示する。
・ヒント
意味 | プログラム |
---|---|
マウスが押される | Input.GetMouseButtonDown(0) |
コンソールにHello Worldと表示する | Debug.Log("Hello World") |
/* テンプレート
if(条件){
// 実行したい内容
}else{
// 条件を満たさない時に実行したい内容
} */
if(Input.GetMouseButtonDown(0)){
Debug.Log("Hello World");
}
例2
もし右矢印キーが押されたらこのプログラムがついているオブジェクトをx座標を0.1動かす。押されていない時にはx座標を-0.1f動かす。
意味 | プログラム |
---|---|
右矢印キーが押される | Input.GetKey(KeyCode.RightArrow) |
オブジェクトをx座標を0.1動かす | this.transform.Translate (0.1f,0.0f,0.0f); |
/* テンプレート
if(条件){
// 実行したい内容
}else{
// 条件を満たさない時に実行したい内容
} */
if(Input.GetKey(KeyCode.RightArrow)){
this.transform.Translate (0.1f,0.0f,0.0f);
}else{
this.transform.Translate (-0.1f,0.0f,0.0f);
}
if文は一つだけでなく沢山分岐することもできる。
if(条件1){
// 条件1を満たす時に実行したい内容
}else if(条件2){
// 条件1を満たさないが条件2を満たす時に実行したい内容
}else{
// 条件1も条件2も満たさない時に実行したい内容
}
例3
sumという整数型の変数があるとする。
int sum;
もしsumが1より大きかったら"クリア"、sumが0~1の間であれば"ゲーム中"、sumが0以下であれば"ゲームオーバー"とコンソールに表示する
/* テンプレート
if(条件){
// 実行したい内容
}else if(条件2){
// 条件1を満たさないが条件2を満たす時に実行したい内容
}else{
// 条件を満たさない時に実行したい内容
} */
if(sum > 1){
Debug.Log("クリア");
}else if(sum > 0){
Debug.Log("ゲーム中");
}else{
Debug.Log("ゲームオーバー");
}