次の記事はこちら
こんにちは栞です。
突然ですがイライラ広告です。
https://www.instagram.com/p/C88oH-zg5Sn/?utm_source=ig_web_copy_link
引用元。インスタの広告です
「このネジ外しゲームを自分のイラストでつくってみたら面白そうでは?」
そんなことを思いついてUnityに手を出し、今月15日にプログラミングスクールに課金してきました。
経緯などくわしくはこちらをご覧ください。
で、3日が経過しました。
とりあえず現段階の制作物がこちら。
最低限のゲームの要素を備えたゲームですが
一応これでも上記のブログのチュートリアル内容は完走したかたちになります。
わりとここまでは楽勝でした。
Unityのインストールがなんなら一番難しかった。
でもここからがまた難所のようで、スクールの課題として
「ここに自分のオリジナルの要素を加えよ」
というものが与えられました。
これを達成するためには
直感的にゲームを制作できるUnityをいじるだけでなく、
C#というちゃんとした言語を使わないといけないらしいです。
ここまでもC#は記述してはいたのですが、
すべて上記ブログのコピペでした。
なので文法とかまったく知らない状態。
他人様のブログを読んでいても
目が滑って仕方がないので
ちゃんとC#を知ることにしました。
これがちょうど3日目ですね。
ちなみに1日目はインストールと各種設定、
2日目はたまころゲームのチュートリアルでした。
上の動画で、動いてる玉あったじゃないですか。
あれを制御するスクリプト(プログラミングのコード)がこれなんですが
ちょうど半分くらい、37行目までのコードを理解するのにだいたい半日ほど要しました。
なかなか学習コストが重いです。
この記事の最後にせっかくなので板書を残します。
Unityスクール所感
1,2日目はスクールの講師の方にSlackで聞いていたのですが
正直に言うと愛想がなく、本業の片手間で答えてる感がムンムンするので
今日はずっとClaudeにお世話になってました。
スクールの意味とは。
おおげさですが、お客様に愛を注ぐって大事だと思います。
Unityのインストールに手間取ったのも
講義動画が5年前のもので
UIなどが色々変わっていたからというのが大きいです。
シンプルに私がIT音痴って可能性も全然ありますが。。。
そろそろ撮りなおせば質問回答の工数も減るのに…
と思いつつ質問してました。
雑音もけっこう入っちゃってるし。
まあでも競合他社より7万円ほど安いのでそんなもんなんでしょうか。
お客様に愛を注ぐ、レバレッジを利かせる。
他山の石とします。
Claudeが凄い
スクール講師よりよっぽど講師してます。いまのところ。
速くて正確。
AIはよく誤情報を投げてくるみたいなことを言われますが
素人目線では完璧です。
ときどき個人ブログなども見て
情報が合致しているか確認するのですが大丈夫です。
「初学者は~~という理解でも大丈夫ですか?」
みたいないかにも人間くさい質問にも答えてくれるのが良いですね。
コミュニケーションをとってる感じがします。
ChatGPTとかGeminiはどんな感じなんでしょうか?
Claudeは一番人間に近くて文脈理解に長けているらしいので使っているのですが…
すぐ聞けるので聞いてみました。
ChatGPT
自己評価高めですね。
Gemini
ChatGPTになにか恨みでも
Claude
🐵
ちなみにAIに聞くときはキーボードでうつのではなく
VoiceInという音声入力の拡張機能を使うのをおすすめします。
少々の誤変換はAIが文脈を読んで勝手に直してくれるので
とても便利ですよ。自由にできる時間が浮くのってうれしいですよね。
あと手の疲れも軽減されます。
まとめ
ということでUnityゲーム制作3日目のログでした。
はやく自分のイラストを使ったミニゲーム的なものを量産したいです。
ほぼ自分用ですが、たまころゲームのコードの板書をのせときます。
どうやら板書ばかりするのではなくて
実際にコードをいじって実装してみるのが良いらしいので
明日はC#をいじる日にします。
あ、まちがってる点があれば
教えてもらえると助かります!!
それでは!
イラストもちゃんと描いてくのでご安心を。
コメント
コメント一覧 (2件)
Unity3Dをゲームを作るための道具として捉えるだけでなくその論理を学習されている姿勢が素敵で、応援しております!Unityにおける2Dゲーム作成のチュートリアルは、本記事のようなStart() Update()や言語としての仕組みの理解を終えたあとはだいぶ3Dと異なってきますのでご留意いただきつつ進められるのがよいかと思います。
開発の裏側が公開されるとフェチのためのゲームなのにif分岐の多さやフラグ多用などがないか気になってしまうという職業病があるので、そういった悩みに直面されたときは投稿いただけると対処法を提案できるかもしれません…?
職業病ついでに技術的なコメントを以下に記します。
>副作用、void
voidを返すメソッドは確実に副作用を利用していると考えてよいですが、値やオブジェクトを返すからといって副作用がないとは限りません。副作用とは「メソッドの引数に与えたものが実行前と実行後で変わってしまっている」あるいは「そもそも与えてもいないものを書き換える」という挙動のことを指します。例にあるadd(a, b)は副作用がなく、何度実行しても引数aやbとして渡した変数は変わりません(これは値渡し/参照渡しやimmutableという別の話も混ざってきます)が、int addScore(int score) { total = total + score; return total; }はtotalというフィールドに勝手に加算するので、intを返しますが副作用があります。
ゲームを動かすのに用いることの推奨に関しては解説?の意図がわかりませんが、ゲームという開発分野では同一のキャラ(インスタンス)が時間を経てHPが減り持ち物リストが増え・・・のように状態を書き換えたい場面が多いということは言えると思います。
しかし、持ち物リストにアイテムを追加する場合にvoid add(Item item)としなければならないという必然性はなく、ダンジョンの前層突破報酬を与えて、次の層までの間に倒れてしまったら突破報酬を与えた直後の状態に巻き戻る、というゲームを作りたい場面ではその層の攻略中に使ったアイテムが巻き戻しの際に消えてしまっては困るので、ItemListクラスにpublic ItemList with(Item item)というメソッドを作り、中ではItemListインスタンスを書き換えるのではなく複製したItemListにアイテムを追加したものを返すことにしておけば、savedItemList = currentItemList.with(new Item(“xの加護”))のようにしたあと、currentItemListからアイテムが消費されてもsavedItemListは影響を受けません。まあsavedItemListへの代入は副作用なので、withは副作用がないけど結局ゲームの進行に影響を与えるためには副作用を使うことは避けられないという意図なのかもしれませんね…
ただ、副作用は本当に必要な場面以外は避けて、基本的には副作用なしに値を返すメソッドを多く使うのが開発分野を問わないセオリーです。
>SetCountText()
サンプルに元から入っているコードだと思いますがちょっと微妙なコードで、カウント表示のテキストを設定するということは伝わるのですが、引数がないので「何という内容を入れるの?」がわからないのですよね。中身を見てみると実はscoreの値を入れていましたと判明するのですが、こういうメソッドはずっと後に読み返したとき、どこの値と結びついているのか思い出すのに時間がかかり開発効率を妨げることになってしまいます(仕事だと、さらにこのメソッドが様々なscore値だった場合に問題ないかテストするためのコードを書くのですが、これはテストしづらいものでもあります)。SetCountText(score)ならばスコアをカウント表示にセットしていそうだなと読んだだけで思い出せるのでおすすめです。
>Input.GetAxis スタティックメソッド
オブジェクト指向のプログラミング言語では、基本的に具体的なものに何かを命じる(「ボールのRigidBody」に「これだけの力を加える」)のですが、時に具体的なものがないことがあります。好例がMath.Minで、currentMoneyとmoneyLimitのうち小さい方の値を取得したいとき、currentMoney.Min(moneyLimit)「現在の所持金」に対して「最小値を、所持金上限を使って求める??」と文章に直すとよくわからないことになるため、そうではなく「数に関する概念(Math)の一種である、より小さい方(Min)というものを、現在の所持金と所持金上限という2つについて考えてみる」と表現できるようにstaticメソッド=呼び出すのにインスタンスが必要にならないメソッドとして提供されています。
さてInput.GetAxisですが、これは明確にInputが概念であると言えるかはやや怪しい部分があり、Unityの設計思想上の決定によりこうなった可能性があります。Inputって、実際には「マウスのInput」「ゲームパッドのInput」「スマホジャイロのInput」などがあり得るのでインスタンスメソッド(非staticメソッド)でも文章の筋は通るんですよね。ただ、Unityとしてはあらゆるコントローラーの入力をまとめて仮想的な「Unityゲームに対するプレイヤーの入力」という概念としてまとめたかったのかなと思います。
>new Vector3(…) なぜここで急にインスタンスの取得?
インスタンスの生成をする理由としては、RigidBody.AddForceの引数として与えるためにVector3型が必要であり、Input.GetAxisではVector3は得られないからという以上の意味合いはないですね…
AddForceが(float x, float y, float z)という引数を取るメソッドであればmoveHorizontal, moveVerticalをそのままxとzに当てはめればよいことになります。しかし、力を与えるというのは3次元空間での方向を定めて行うことなので、次元をまとめた単位であるVector3を引数にとる方が自然であることからこのような設計になっていると考えられます。なおVector3自体はメモされている通り単位のない量ですが、AddForceの実装コード中では渡したVector3のx軸、y軸、z軸それぞれの大きさ×1ニュートンの力を加える意図として解釈されます(係数が1Nなのはドキュメント読んでみて私も初めて知りました)
また、speedというフィールド名がミスリードなのですが、実態としては「力の倍率」です。ボールをspeed(m/sec)で(物理演算を無視して)動かすという目的では使われていないことから速度ではなく、また力と解釈するのであればspeedフィールドに10lbf(重量ポンド)を代入することでInput量×10lbfを加えたいという望みを実現できるはずですがそれはできず、あくまでfloatは10.0という単位のない数値しか表現できないためです。
>rbはインスタンス […] GetComponent関数もインスタンス化させる作用
細かい話ではありますが、rbはRigidBodyインスタンスに対する参照であり、GetComponent<RigidBody>はPlayerControllerが取り付けられたGameObjectインスタンスに取り付けられている(かもしれない)RigidBody(Component派生クラス)を探して最初に見つかったものの参照を返すことを行っています。したがって、インスタンス化は行われていません。
コメントありがとうございます!とても心強いです。
こまかく返信しようにも限界があるのでゆっくり咀嚼させていただきます!