この記事は LITALICO Engineers Advent Calendar 2021 8日目の記事になります。
アドベントカレンダーで、エンジニアの皆さんがそれぞれ輝かしい内容の記事を書いていらっしゃるなか、自分は開発技術面の話から少々外れ、どちらかというと教育論っぽい話をさせていただこうかなと思っております。
流し読みしていただけるだけでも十分ありがたいです、どうかよろしくお願いします。
1.はじめに
まずは軽く自分の素性をお話しさせていただきます。LWO(リタリコワンダーオンライン)所属の@Butterfly-Dreamと申します。
LWOでは、下は小学生、上は高校生までのお子さんに主にプログラミングを指導しております。scratchも扱うのですが、最近は主にUnityを使ったゲーム制作の方法について指導する割合が多くなってきました。
そういう仕事柄、小学生・中学生のお子さんにテキスト型言語の構築法を指導する機会がかなりあります。そんな教育現場で常々痛感しているのは、自分たちメンター側とお子さんとの、理解の土壌となる知識の格差です。
中学生以上のお子さんならまだしも、特に小学生のお子さんとなると、座標の概念・負の数・変数の概念といった基礎的な数学分野の知識もまだ未習得、という例も少なくありません。
ましてそのうえでテキスト言語独自の手法を習得するとなれば、未経験の大人がプログラミングを独学するときと比較して、いったいどれだけの心理的負担がお子さんにのしかかってくるのか…。
もちろん、お子さんのわからないところを指導するのが我々メンターの仕事ですし、「ここがわからない」という声を聞けば、当然すぐに駆けつけて逐一説明を施します。
しかし。
「わからないところ」を説明するだけで、本当にそれはお子さんの十分な理解につながるのでしょうか?
授業で説明をした後、お子さんは教わったことを活かして、自分なりに応用するまでに至れるでしょうか?
まぁ、一回説明しただけでは無理だよね。
というのは、この記事を読んでくださっている皆さんと自分で共有できる所感ではないかなと思います。
たしかに自分も、プログラミングを一回説明聞いただけで覚えたわけではなく、何度も手を動かして、デバッグを繰り返してスキルアップしていった記憶があります。
ですが、先述した通り理解の土壌となる知識が不足しているために我々よりもプログラミングの習得に難があるお子さんたち。できうる限りその負担を軽減するアプローチをするべきなのは言うまでもありません。
さて、では一体どのように指導すれば、お子さんにとって一番ベストな形でUnityにおけるプログラミングへの理解を深められるでしょうか。
この問題、賛否両論があるかと思いますが、現状自分が考えている解答が、タイトルにもあります、「体系的に」学ぶ、ということなのです。
2.「体系的に」学ぶ、とは
前項で長々と語りましたが、ここからが記事の主題です。さて、「体系的」とは、「体系」とはいったい何でしょうか。
完全に私事ですが、私の人生史上、「体系的」という言葉の初見は大学受験勉強時に買った数学の参考書の序文だったと思います。詳しくは忘れましたが、「受験に必須の事項を体系的に学んでいく」云々と書いてあったような…。
その後、(文系の)大学に進学し、言語学の授業を受講した際「語彙体系」なる言葉に出会うに至りました。その時、言語のプロフェッショナルである大学教授から、直々に「体系」という単語の意味について解説を受けるという良い機会に恵まれました。
いや、まぁ、「体系」という言葉の意味自体は、大学教授から説明を受けるまでもなくちゃんと辞書に載っている言葉です。なので、ちょっと辞書から意味を引用しておきましょう。
辞書的には、「体系」には二つの意味があるようです。
(1)個々別々のものを統一した組織。そのものを構成する各部分を系統的に統一した全体。
*現代経済を考える〔1973〕〈伊東光晴〉・一・一「まず第一に使用する水を循環させる計画を改め、新しい水を取り入れ、これを使用後捨てるという体系にすればよい」
(2)一定の原理によって統一的に組織された知識の全体。
*改訂増補哲学字彙〔1884〕「System 系、統系、門派、教法、制度、法式、経紀、体系、教系」
*物理学と感覚〔1917〕〈寺田寅彦〉「一層思考の経済上有利な体系が出来得るかどうか」
*竹沢先生と云ふ人〔1924~25〕〈長与善郎〉竹沢先生の散歩・六「一つの哲学と云ひ得る体系を成してゐない」
"たい‐けい【体系】", 日本国語大辞典, JapanKnowledge, https://japanknowledge.com , (参照 2021-12-06)
別に語の意味用法について論じているわけではありませんので、二つの意味用法の異同などについては省略しましょう。今回は二番目の意味の「体系」を扱います。
私なりの例えで、「体系」について説明してみようと思います。一番わかりやすいのは…日本史ですね。
例えば794年の平安京遷都、例えば1560年の桶狭間の戦い、例えば1867年の大政奉還。
大学受験を控える高校生は、教科書の裏にある年表を血眼でみてこれらの事項を一つでも多く覚えようとしますが、そんな瞬間記憶で網羅できるほど日本史という教科は甘くありません(経験談)。
では実際にどうやって習得するのかというと、年表に書かれるほどに重要な事件・事項について、それが起こるに至るまでの経緯であるとか、その後の影響などについて学び、記憶のとっかかりをできるだけ広くしておくわけですね。
そう、これがいわゆる、「体系的に」学ぶ、ということです。
一つ一つの単語・事項をそれ単体で覚えるのではなく、何かしらのとっかかりや共通点と一緒に習得する。そうして完成した「知識の全体」として重要な部分を記憶する。
日本史でいえば、「なくよウグイス」などの語呂合わせ記憶習得もあると思いますが、これも何かしらの共通点を見出して知識を有機的につなぎ合わせているという点では「体系」から離れるものではありません。
そろそろ、プログラミング指導の話に戻ってみましょう。
Unityで扱われるテキスト言語であるC#、C#には本当にたくさんのメソッドが登場します。
それらの知識を単体ずつで習得するのは、UnityのC#を学び始めたお子さんにとって大きすぎる負担となりえるでしょう。
そこで「体系」が出てくるわけですね。
一つずつ習得するのではなく、共通点やとっかかり、何かしらの原理に従って連鎖的に絡めて指導されることで、最終的に全体としての「体系」を習得する。
…なんか、小難しいですかね?💦
まとめますと、知識を単体で覚えるんじゃなくて、複数の知識と絡めて習得しろ!と言っているだけなんです。
ではこの後は、実際にどのような形でUnityの基礎部分を体系的に学ぶべきか、実際のUnityの用語を提示しながら私の現状の結論を解説していこうと思います。
3.Unity基礎スキル体系の構造
実際の授業では、私は自分の体系構造に則ったオリジナルサブテキストをお子さんに提示しています。しかしそのサブテキストは、LITALICOのテキストのソースコードを多分に使用しているため、残念ながらこの場で公開することはできません。
なので、ここではそのサブテキストの目次だけご紹介しようと思います。
この目次こそが、自分の今考えうる限りのUnityスキル体系であるわけです。
# 0-1.コメントアウト
# 0-2 デバッグ
# 1.C#の基礎文法
## 1-1.変数
### 1-1-1.変数とは
### 1-1-2.変数の型
#### 1-1-2-1.代表的なc#の型(float型,int型,string型,bool型)
#### 1-1-2-2.Unityの機能の型(GameObject型,Rigidbody型など)
#### 1-1-2-3.自作スクリプトの型
### 1-1-3.変数の使い方(宣言→代入→計算)
## 1-2.演算子
# 2.スクリプトの基本構造
## 2-0.【大原則】コードの最後は…;(セミコロン)
## 2-1.【大原則】コードは{ }のなかに書く
## 2-2.関数
### 2-2-1.Start関数
### 2-2-2.Update関数
### 2-2-3.当たり判定の関数
#### 2-2-4.自作の関数
#### ★関数の作成→呼び出しの手順
## 2-3.アクセス修飾子とシリアライズ化(public,private,[Selialize])
# 3.プログラミングの基本三大処理
## 3-1.順次処理
## 3-2.条件分岐処理(分岐処理)
### 3-2-1.if文
#### 〇複雑な条件分岐(if文の中にif文)
### 3-2-2.if-else文
## 3-3.繰り返し処理(反復処理)
### 3-3-1.Update関数
### 3-3-2.InvokeRepeating
# 4.Prefab(プレファブ)システム
## 4-1.Prefab(プレファブ)とは?
## 4-2.プレファブの作り方
## 4-3.コードでクローンを増やすメソッド(Instantiate)
## 4-4.コードでクローンを減らすメソッド(Destroy)
こんな感じですね。
用語そのものは解説するまでもないと思うのですが、自分なりに工夫している部分を解説させていただきます。
3-1.サブテキストの意義
これは宣伝でも何でもないのですが、LITALICOには優れたUnityゲーム制作のテキストがあります!!
私が自作したサブテキストと区別するために、この真なるテキストをメインテキストと以後呼ぶことにします。メインテキストでは主に、ブロック崩しゲームとか、アクションゲームとか、何かしらのゲームの作り方を順序良く解説していく、というような構成になっております。
ゲーム制作の学習たるもの、ゲームを作ってなんぼという考えを地で行くメインテキストに私ごときが異議を申し立てるのは不遜に過ぎるというものです。
ではなぜサブテキストなんて作ったんだというと、これはテキストを卒業してオリジナルゲームを制作していくお子さんのためのものです。
先述の通り、メインテキストは一つのゲームの制作手順で扱ったメソッドその他を解説しているため、お子さんがオリジナルゲーム制作中に、知識の確認として振り返るという用途には少々向いていない部分があります。
それを補強しつつ、不足している知識を「体系的に」習得させるアプローチとして、このようなまとめテキストをお子さんに配布している次第です。
3-2.コメントアウトとデバッグ
この二つが妙にサブテキストの上部に浮上していますが、これは単純によく授業でこの用語を扱うからですね。
「じゃあそこ、消すと戻すの大変だしコメントアウトしよっか」「あー、じゃあデバッグしてみよう。Debug.Logをそこに書いてみてー」といった具合に。
デバッグの項ではデバッグという用語そのものの概念について解説しているとともに、Unity最頻出のデバッグプログラムであるDebug.Log("");
の紹介までしています。
3-3.C#の基礎文法
この辺から、かなりソースコード多めで解説を施している部分になります。
「C#の基礎文法」と題して、コードを書くうえでは避けては通れない「変数」・「演算子」の解説をしております。
3-3-1.変数
よく変数は「空っぽの箱」と紹介されますが、特に小学生ならもっとわかりやすい表現があると私は考えています。
1+1=□
2+1=□
算数のドリルでよく見る表記ですね。
「この□、式によって数字が変わるよね?これが変数だよ!」てな感じが私式ですかね。
変数って、要は変数自体に何か数値的意味はないということがわかればいいと思います。「□はそれだけでは何の意味もないよね?」とわかればよろしい。
3-3-2.演算子
これについては、頑張って表を作成してみました。
分類 | 演算子 | 意味 |
---|---|---|
計算で使う | + | 足し算 |
- | 引き算 | |
* | かけ算 | |
/ | 割り算 | |
% | 割り算の余り | |
+= | +□□ずつ変わる(□□ずつ増える) | |
-= | -□□ずつ変わる(□□ずつ減る) | |
++ | +1ずつ変わる(1ずつ増える) | |
-- | -1ずつ変わる(1ずつ減る) | |
比べるときに使う | == | 同じ |
!= | 異なる | |
< | 小さい(小なり) | |
<= | 同じか小さい(小なりイコール) | |
> | 大きい(大なり) | |
>= | 同じか大きい(大なりイコール) | |
代入で使う | = | 代入する |
「+=」や「-=」は厳密には代入演算子だろ、とか言っちゃあいけません(笑)
イングリントとデクリントが控えているなら、これを並列に並べたほうが、お子さんには絶対にわかりやすいと思います。
授業の経験で言うと、if文の条件節中で代入演算子の「=」を使うお子さんが多いこと、多いこと…。
「=」は代入で、比較の時は「==」を使うんだよ、算数と違うから慣れないかもしれないけど頑張ろう、みたいなことをよくしゃべります。
3-4.スクリプトの基本構造
3-4-1.【大原則】コードの最後は…;(セミコロン)
これは定番なので、しっかり書いておきました。
まぁ、偉そうに書いてますけど、自分も個人的にUnity動かすときは、忘れているときもしばしば…(目逸らし)。
3-4-2.【大原則】コードは{ }のなかに書く
正直自分は、小学生のお子さんに、柔然にC#のclassについて解説できる自信がありません。
別にプログラミングで絶対的に用語を記憶しないといけない、という規則もないですし、ここはわかりやすく{ }の存在を強調して解説することにしています。
よくある話ですが、テキストなどに書いてあるソースコードを、自分のスクリプトのどこに写経すればいいのかわからない、という問題はここの理解を深めることで対処可能です。
「一番外側に{ }があるよね、ここからここまでがスクリプトの範囲だよ。ほら、ここにスクリプトの名前と同じ単語書いてあるよね」ってな感じです。
3-4-3.関数
あまりに使いすぎるせいで、授業でも平易な言葉を使わず自分はこの単語を前面に出しています。
関数は、コールチンなども後で出てくることを考えると「void」の有無で判別させるのも怖いので、
「一番外側の{ }がスクリプトの範囲だって言ったよね、その次、二番目に外側の{ }が関数だよ!」
と指導しています。
3-4-4.アクセス修飾子とシリアライズ化(public,private,[Selialize])
アクセス修飾子とシリアライズ化の話を個別にするのではなく、敢えて三つを並列に配置して解説しています。これも「体系的」の一環ですね。
- public…ほかのスクリプトからアクセスできるよ!Unityエディタからドラッグ&ドロップできるよ!むやみやたらに使うと怖いよ!
- private…ほかのスクリプトからアクセスできないよ!デフォルトはこっちだよ!
- [Selialize]…これをprivateの前につけてると、privateなんだけどUnityエディタでドラッグ&ドロップできるよ!
こんな感じで(もうちょっと言葉足していますが)解説しています。
3-5.プログラミングの基本三大処理
これが私の体系のなかの真骨頂ですかね。
全てを切り離して理解するのではなく、つなげて習得する。
サブテキストにはこんな自作した図を掲載して各々解説しています。
3-5-1.順次処理
意外と落とし穴になりやすい部分なので、ちゃんと解説しています。
↓↓
プログラムは上から下に、流れるように処理されていくということ。
原則として、逆流して処理される(下から上にさかのぼる)ようなことはあり得ない。
using UnityEngine;
public class Test : MonoBehaviour
{
int Marcy;
// Start is called before the first frame update
void Start()
{
Marcy = 3;
Marcy = 1;
Marcy = 2;
}
}
こんなスクリプトがあったとしたら、最終的にMarcyは2になる。
3→1→2と変わるのであって、2→1→3と遡るわけではない。
↑↑
このソースコードは自分で作ったやつなので、実際にサブテキストにある文面をそのままコピペしてみました。
どうですかね?わかりやすい…ですかね…?💦
3-6.Prefab(プレファブ)システム
これが私の体系のなかの真骨頂ですかね(二回目)。
システム、と仰々しく書いてありますが、こう題することで三つの知識を体系化できるんですよね。
- Prefabの作り方(エディタで、ヒエラルキーのゲームオブジェクトをAssetファイル下までドラッグしてきて…etc)
- Instantiate
- Destroy
後半二つは別にPrefabだけでしか使えないものではありませんが、Unity初学者の場合、正直Prefabと一緒に使う事例の方が多いでしょう。
ならば一緒に覚えてしまおう、というわけですね。
「Prefabは弾とかモンスターとか、複製したいものがあったときにそれの親玉になるやつだよ!そうそう、そうやってヒエラルキーに投下してあげたら手動で増やせるんだけど、面倒だよね?コードで増やしてみよっか!」
ってな具合です。
3-7.その他諸々、不足している部分について
さて、Unity経験者の読者様におかれましては、上記の項目で不足している部分があるのではとお思いの方もいらっしゃるかと思います。
一例をあげるとしたら、反復処理の項目ですね。forも、whileも、foreachも何も書かれていませんが?となると思います。
どうして書いてないのといいますと…メインテキストにないからですね!
あくまでサブテキストは、メインテキストを卒業したお子さん向けの、ステップアップのテキストなので、見慣れないコードをたくさん書くわけにはいかないのです。
どうしてもそういう部分はあるかと思いますが、どうか暖かい目でご了承いただけると幸いです。
4.終わりに
…思ったより長い文面になってしまった…。
ということでここまで、自分のUnity学習における「体系的」指導について書かせていただきました。
この記事が何かしら皆様のお役に立てたらとてもうれしいですが…あまりに基礎的な話過ぎてそんな機会もないような…。
来年またカレンダーにお誘いいただける機会があったら、もっと華々しい技術で持って皆々様を圧倒したいと思いますので、どうかよろしくお願いします!!
明日のLITALICOアドベントカレンダーは@sayaka_hashiさんです。どうか、お楽しみに、です!
では皆さん、またどこかでお会いしましょう~。