Unity練習[O1o0]
What is | This is |
---|---|
OS | Windows |
Tool | Unity Hub 3.3.0 (あとでインストール) |
手順
Step [O1o0] インストールから
Step [O1o1o0] インストール
👇 以下のホームページから、Unity をダウンロードしてほしい
📖 Unity
細かく言うと Unity Hub という名前の .exe ファイルかもしれない
👇 インストール先の例
C:\Program Files\Unity Hub
Unity Hub というアプリケーションが Windows にインストールされたと思う
英語版かと思うが、日本語化パッチのようなものは(あるのか知らないが)わたしは 当てない 。
英語の人口が 日本語の人口より多いのだから
エラーメッセージが出たとき検索して情報が多いのは 英語版 であることが多い経験則から そうする
Step [O1o2o0] 実行
Unity Hub アプリケーションを実行してほしい
プロジェクト一覧画面が出ているだろうか
これで Unity は使える状態になった
Step [O1o3o0] 学習(しない)
Unity Hub のメニューから Learn を探してクリックしてほしい
Learn - Featured
が開いているだろう
科目のようなものが並んでいて、どれを選べばいいか分からないかもしれない
分からないときの最善の方法は すべてのメニューをクリックして 開けてみればよい
TIME TO COMPLETE:
XXX minutes
といった 完了するまでにかかる時間(分)が書いてあるだろう
1時間は 60 minutes(分)だということを思い出してほしい
たとえば Beginner Course
は 2430 minutes
だから 40日と30分かかる
これは大変だ、ということが分かったところで、いったん 着手せず、別の方法を探る
Step [O1o3o0] 学習 - 推奨(使わない)
Unity Hub
の Learn - Recommended
もクリックしてみよう
Sign in
というリンクをクリックしてほしい
Unity ID
というWebサイトに飛ばされる
アカウントを作り、ここに Email と Password を入れる
するとまた Unity Hub
の Learn - Recommended
に帰ってくる
Nothing here,yet
(まだ、ここには何もない)と書いてある
Step [O1o4o0] 学習(しない)
Learn - Featured
に戻ってくる
TYPE
というものが薄い字で書かれてあり、その要素は以下のものがあるようだ
- FOUNDATIONAL TUTORIAL (基礎チュートリアル)
- BEGINNER COURSE (初級コース)
- BEGINNER PROJECT (初級プロジェクト)
- INTERMEDIATE COURSE (中級コース)
- ADVANCED COURSE (上級コース)
基礎と初級はどっちを先にやればいいのか なんの説明もないが、
-
チュートリアル
というものは ちょっとした操作説明ぐらいで大したことはやらない雰囲気がある -
コース
というものは そこに入ってしまうと長い雰囲気がある
とりあえず 手あたり次第 チュートリアルをクリックして開けて 説明だけ見ていってみる
Step [O2o0] Get started with the Unity Hub
Get started with the Unity Hub
というフィーチャーが Foundational Tutorial で、 20 minutes のようだ
とりあえず これを実践してみよう
View on Unity Learn
をクリックする
📖 https://learn.unity.com/tutorial/get-started-with-the-unity-hub#
👆 Web サイトへ飛ばされる。 Web サイトを読みながらやれ、ということらしい
じゃあ、やってみる
英語だが、ブラウザの機能で日本語訳すれば問題ない
どうも この Get started with the Unity Hub
を読めるスキルレベルを習得すれば
わたしが Qiita で記事を書かなくても良さそうな感じだ
Step [O3o0] Unity projects
Unity のプロジェクトを どのフォルダーの下に作るかだが、デフォルトだと
C:\Users\{ユーザー名}
の直下に作ってしまった。
好きにすればいいが、わたしは次は
C:\Users\{ユーザー名}\Documents\UnityProjects
とでもフォルダーを切ってその下に置きなおした。やり方は以下の通り
- Windows Explorer で 📂
UnityProjects
を作成し、その下へEssentials 3D project
を移動 - Unity Hub のプロジェクト一覧から、
Essentials 3D project
の行の […] ボタンをクリック、Remove project from list
をクリックして一覧から消す - Unity Hub の
Open
ボタンでEssentials 3D project
を選び直す
Step [O4o0] Explore the Unity Editor
👇 次は Explore the Unity Editor
というフィーチャーを開けてみる。 Foundational Tutorial で、 10 minutes のようだ
📖 https://learn.unity.com/tutorial/explore-the-unity-editor-1
画面の見方、カメラの操作の仕方などが学べた
Step [O5o0] Create with Code
Learn - Featured
に戻ってくる
Create with Code
を開く。 Beginner Course で 2430 minutes だ。
期間が長いが、ちょっと かじってみて 嫌なら止めればいい。開けてみる
📖 https://learn.unity.com/course/create-with-code
いくつものパートに分かれているようだ
チュートリアルのWebサイトを見渡すと、
Select your Unity version
というドロップダウンリストがある。
インストールしている Unity のバージョンに合わせる。
わたしは 2022年11月現在、 先行版の 2022.1 ではなく、 LTS の 2021.3 をインストールしているから、 2021.3 にする
2021.3 は 2021年3月 に見えるから 2021c にでもすればいいのに、LTS は 3 だから 2021.3 だ、という表記は Unityの作法として決まっている。
参考: 📖 3.Identify Unity versions
私は神ではないので仕方ない。人のやることを受け入れることにする。諦め、妥協し、不本意なことに従う
あとで分かったのだが この Select your Unity version
、 記事毎に設定するもので、記事が存在しないバージョン番号もあるようだ。
多分、古い記事の内容と同じで、変更がなかったのだと思うことにしよう。 ユーザーからすれば「記事が無い!」という気持ちだが、まあ、いいだろう
Step [O5o1o0] Getting Started
-
Getting Started
- Tutorial, Begginer, 35 Mins
さらにパートに分かれている
Step [O5o1o1o0] Course Introduction
-
Course Introduction
- Tutorial, Begginer, 10 Mins
動画が2本あり、やる気を高める動画と、このコースの動画を上手く使える人がしている勉強方法について の2本のようだ
Tips:
動画は英語だし、字幕も 英語かスペイン語で 日本語はないかもしれない。
じゃあ 日本語話者は どうすればいいかというと、
動画の外の下側に Show transcript
リンクがあり クリックすると 全文書き起こし のようなものが出てくるので
Web ブラウザーの機能で Web サイト全体に Google翻訳 をかけるといいだろう
例えば以下のように出る
00:00:12 たった一つなのに
ちょっとしたアドバイス
00:00:14 大事なことなのでここでシェアします
00:00:17 私たちがこのビデオ全体を作ったこと
それについてあなたに話すために。
00:00:20 ですから、これ以上苦労することなく、
00:00:22 ここに最も重要な3つがあります
あなたが知っておくべき言葉
あとで分かったことだが、日本語が選べる動画もあるし、選べない動画もあるようだ。まあ、いいだろう。
また、ブラウザ翻訳すると、動画の上の字幕が日本語になるケースもあるし、ならないケースもある
Tips:
そんなことできないかも知れないが、教えておく
もし 英語のリスニング(聞き取り)をしながら、動画と、日本語訳の間を目で往復するのが 間に合わないときは、
動画を再生した直後に 一時停止し、
日本語訳を先に全部読んでしまってから(変な直訳で意味分からないが) 落ち着いて 動画を見るとよい
Tips:
動画は、ページに埋め込まれているとサイズが小さくて Unity Editor の文字が見えないので、全画面表示にして見るとよい
Step [O5o1o2o0] Install Unity Software
-
Install Unity Software
- Tutorial, Begginer, 25 Mins
インストールしておけ、というものが説明されている
VS 2022 を使っているのに Microsoft Visual Studio Community 2019
なんか入れたくないが、
私は神ではないので仕方ない。人のやることを受け入れることにする。諦め、妥協し、不本意なことに従う
ほとんど 先にやってしまっていたことが書いてある。先に進む
Tips:
あとで分かったことだが、外部スクリプトを開くエディターは選ぶことができる
Step [O5o2o_1o0] Unit 1 - Player Control
あとで分かったことだが、 Unit 1 の目次を見て 少なそうだな、と思ったら 目次を開けると中に パートが沢山ある
Player Control
は、すぐにゲーム開発に取り掛かるのではなく、 Unity Editor の基本操作を覚えていく感じ
Step [O5o2o0] Unit 1 - Introduction
-
Unit 1 - Introduction
- Tutorial, Begginer, 5 Mins
確かに動画を1本見るだけで 5分もあれば終わる
Step [O5o2o1o0] Lesson 1.1 - Start your 3D Engines
-
Lesson 1.1 - Start your 3D Engines
- Tutorial, Begginer, 1 Hour 20 Mins
ここから実技に入るのだろう
著作権で縛られていて商用不可の材料が .zip ファイルで置いてあるのでダウンロードする
Prototype 1 - Starter Files.zip
ファイルがダウンロードされた
Tips:
Unity Project の名前が Prototype 1
なのだが、イケてないと思う。
Driving Car
みたいな名前なら あとで思い出せると思うのだが、
レッスンをしばらくサボって 続きをやるかな、と思ってプロジェクト・リストに Prototype 1
という Unity Project が並んでいても
「なんだったかな、これ……?」と思う
じゃあ名前を変えればいいのかもしれないが、変えたら変えたで 後で分からなくなるのも嫌だ。
私は神ではないので仕方ない。人のやることを受け入れることにする。諦め、妥協し、不本意なことに従う
Step [O5o2o1o1o0] 1.Make a course folder and new project
動画ではデスクトップにフォルダーを置いていたが、
わたしは フォルダーの場所を 📂 "C:\Users\{ユーザー名}\UnityProjects\Create with Code"
とした。
Step [O5o2o1o2o0] 2.Import assets and open Prototype 1
さっきダウンロードした Prototype 1 - Starter Files.zip
ファイルをどこへでもいいので解凍する。
Prototype-1_Starter-Files.unitypackage
というファイルが出てくる。
これは ユニティーパッケージ と呼ぶ
ユニティーパッケージを Unity Editor へインポートする方法は 動画で説明があるので、そうする
動画の中で同じことを2回やっているが、
同じことは2回できないという説明なのに 2回できてしまい、よく分からないので無視した
Step [O5o2o1o3o0] 3.Add your vehicle to the scene
とにかく 赤い車を置いた
Step [O5o2o1o4o0] 4.Add an obstacle and reposition it
箱を置いたり、X,Y,Z 座標をリセットしたり、ゲームオブジェクトの名前を変えたりした
Step [O5o2o1o5o0] 5.Locate your camera and run the game
カメラを選択する。プレイする
Step [O5o2o1o6o0] 6.Move the camera behind the vehicle
- ギズモを使ってみる
- 車の後ろにカメラを持っていく
- マウスの左ボタンを押下しながら [Ctrl] キーをクリックすると何かできるそうだが、なんのことだか分からなかった
Step [O5o2o1o7o0] 7.Customize the interface layout
- Unity Editor の、いろんなレイアウトを試す
-
My Layout
を作ってほしい
Step [O5o3o0] Lesson 1.2 - Pedal to the Metal
-
Lesson 1.2 - Pedal to the Metal
- Tutorial, Begginer, 1 Hour 10 Mins -
まず1本の動画を見る。スクリプトの話しをする、という前振りだ
- これから PlayerControl というものを C#言語で作りますよ、という前振り
Step [O5o3o1o0] 1.Create and apply your first script
- C#スクリプト・ファイルを新規作成して、 それを Vehicle(赤い車)にアタッチするところまで
Step [O5o3o2o0] 2.Add a comment in the Update() method
- Unity の補助画面として Visual Studio を開いて C# スクリプトをここに書く……、というところまで
- Tips として、 ソリューション・エクスプローラーといったサイドビューを全て閉じ、画面全体をテキストエディターだけにするのが見やすいというテクニックを教えてくれる
Tips
📖 Openin unity script in visual studio does not work
[Edit] - [Preferences] - [External tools] - [External Script Editor]
👆 エディターを選べるらしい
Visual Studio Community 2022
を選んだ
Unity Editor で C# スクリプトファイルをダブルクリックすると、Visual Studio Community 2022 が出てきた
VSCode も選べるが、 Visual Studio の方が インテリジェンス機能が利くので良かった
Step [O5o3o3o0] 3.Give the vehicle a forward motion
- トラックがすごいスピードで地平線まで走っていく
Step [O5o3o4o0] 4.Use a Vector3 to move forward
- プログラムが数字で書かれているより、単語で書かれている方が見やすいよな、という話し
- z の正の数は 必ず前方なのだろうか。自分から見た座標か?
- z の単位は meter
Step [O5o3o5o0] 5.Customize the vehicle’s speed
- トラックのスピードをゆっくりにする
- Frame (いわゆる FPS)を知る
Step [O5o3o6o0] 6.Add RigidBody components to objects
- トラックと障害物が突き抜けないように、物理的な設定をする
- Mass の単位は killo-gram
Step [O5o3o7o0] 7.Duplicate and position the obstacles
- 箱を増やす
Step [O5o3o8o0] 8.Lesson Recap
- レッスン1.2のまとめ
Step [O5o4o0] Lesson 1.3 - High Speed Chase
-
Lesson 1.3 - High Speed Chase
- Tutorial, Begginer, 50 Mins -
これからすることの説明動画を観る
Step [O5o4o1o0] 1.Add a speed variable for your vehicle
- Unity Editor のインスペクターを使って、ゲーム画面を見ながら変数の値を変更する方法を知る
Step [O5o4o2o0] 2.Create a new script for the camera
- トラックとカメラのポジションを紐づける方法を知る
Step [O5o4o3o0] 3.Add an offset to the camera position
- 近すぎるトラックとカメラのポジションを少し離す方法を知る
Step [O5o4o4o0] 4.Make the offset into a Vector3 variable
- コードの書き方を少し綺麗にする
Step [O5o4o5o0] 5.Smooth the Camera with LateUpdate
- 画面のカクツキの解消
Step [O5o4o6o0] 6.Edit the playmode tint color
- 再生中に、編集中と思って間違って編集するのを防ぐ方法
Step [O5o4o7o0] 7.Lesson Recap
- まとめ動画を見る
Step [O5o5o0] Lesson 1.4 - Step into the Driver's Seat
-
Lesson 1.4 - Step into the Driver's Seat
- Tutorial, Begginer, 50 Mins -
これからやることの動画を見る
Step [O5o5o1o0] 1.Allow the vehicle to move left/right
- 左右への移動
Step [O5o5o2o0] 2.Base left/right movement on input
-
Turn Speed
を 1 にするのを聞き逃さないでほしい -
a
,d
キーや、 左、右キーを使って トラックを左右に移動できるようになる
Step [O5o5o3o0] 3.Take control of the vehicle speed
-
w
,s
キーや、上、下キーを使って トラックを前後に移動できるようにする
Step [O5o5o4o0] 4.Make vehicle rotate instead of slide
-
Global
、Local
ボタンの説明を聞いてやってみたが、Local
にしてもGlobal
と同じ動きだった。よく分からない - トラックの首振り(Rotate)メソッドの説明
-
Speed
を 10、Turn Speed
を 25 に変更
Step [O5o5o5o0] 5.Clean your code and hierarchy
- ヒエラルキー・ウィンドウを整理する
- コードを整理する
Step [O5o5o6o0] 6.Lesson Recap
- 今までの振り返り動画を見る
Step [O5o6o0] Challenge 1 - Plane Programming
-
Challenge 1 - Plane Programming
- Tutorial, Begginer, 30 Mins -
諦めるな、という感じの動画を見る
Step [O5o6o1o0] 1.Challenge 1 Overview
- このチャレンジの全体像の説明動画を見る
- バグがあるプロジェクトを修正するという内容
- その答えは、そのチャレンジのページの下の方にあるから、分からなくなったときに見ろということ
- それでも分からない場合の調べ方の紹介(Stack Overflow を見るとか、実際にプログラマーがやるような内容)
-
Prototype 1
に、Challenge 1
カスタムパッケージをインポートしてみたものの、そのあと何をするのか?- とりあえず
Instructions
フォルダーに入っている動画を見たところで、このステップを完了にする -
Scenes
という名前のフォルダーを作ってくれていないだけで、Challenge 1
というシーンが入っていたのでそれを開けてプレイする- 確かにバグがありそうだ。これを直すのがチャレンジらしい
- とりあえず
Step [O5o6o2o0] 2.Warning
- 説明が書いてある。バグを直せということと、分からなかったら下を読めということ
- 下にはヒントが書いてあるだけで答えは書いていないので、下を読まなくても、自分のやり方で、先々、勝手に直していいと思う
- あとでヒントを読むと、自分のやり方が想定されていない方法だと分かったので直した
Step [O5o6o3o0] 3.The plane is going backward
- 確かに 後ろに進むように書いてあるので、前に進むように書き直した
Step [O5o6o4o0] 4.The plane is going too fast
- 飛行機が速く飛んでいるので、遅く飛ぶようにスピードを遅めにした(Speedを0.5にした)が、ヒントを見ると、わたしの方法は想定された解答ではないようだ
Step [O5o6o5o0] 5.The plane is tilting automatically
- 飛行機が機首を上げたり、下げたりするのを勝手にやっているから、ユーザーが上、下キーを押したときだけ機首を上げ、下げするように
直せという課題だが、なぜ 機首が勝手に上がったり下がったりしてるのか分からない- プログラムに、機首を上げたり、下げたりしろと書いてあるのではないようだ
- 発想の問題かと思う。一番シンプルだと思う方法で直した(飛行機のメッシュのチェックボックスを外した)が、ヒントを見ると、わたしの方法は想定された解答ではないようだ
Step [O5o6o6o0] 6.The camera is in front of the plane
- カメラが なんにもない方向を向いているので、飛行機の方を向くといいと思う
- この課題はもっと早いステップでやった方が、バグ探しが楽なんじゃないか?
Step [O5o6o7o0] 7.The camera is not following the plane
- 飛行機は飛んでいくので、カメラが 飛行機と並走するように置くといいと思う
Step [O5o6o8o0] 8.Bonus: The plane’s propeller does not spin
- 飛行機のプロペラが回っていないことを確認する
- プロペラだけ部品が分かれているので、ヒエラルキー・ウィンドウから プロペラをダブルクリックすると 再生中でもシーン・ビューで一瞬拡大できる
- インスペクターで設定できるのか、スクリプトを書くのか、どちらか分からない
- プロペラを1フレームに1回り 回すには 思ってるより大きな数字になることに気づくと なんとかできた
Step [O5o7o0] Lab 1 - Project Design Document
-
Lab 1 - Project Design Document
- Tutorial, Begginer, 1 Hour 30 Mins
やる気を出す動画を観る
Step [O5o7o1o0] 1.Understand what a Personal Project is
将来のレッスンでやることも含んだ、計画書の書き方の動画を観る
Step [O5o7o2o0] 2.Review Design Doc examples
- 計画書の記入例の動画を観る
- Google Document 形式、Word 形式、 PDF 形式で 同じ計画書の テンプレートをダウンロードできる
Step [O5o7o3o0] 3.Complete your Project Concept V1
- 計画書を観ながら、新しいプロジェクトを計画する例の動画を観る
Step [O5o7o4o0] 4.Complete your Project Timeline
- タイムラインを書こう、という話しの動画を観る
- 追加したい機能は
Backlog
に書く
Step [O5o7o5o0] 5.Complete your MVP sketch
- オフィスソフトを用いたアイデアスケッチの作り方動画を観る
Step [O5o7o6o0] 6.Recap
- まとめ動画を観る
Step [O5o8o0] Quiz 1
-
Quiz 1
- Quiz, Begginer, 15 Mins
クイズが10問ある。ラジオボタンを選択していく
Step [O5o9o0] Bonus Features 1 - Share your Work
-
Bonus Features 1 - Share your Work
- Tutorial, Begginer, 1 Hour
Step [O5o9o1o0] 1.Overview
動画を観る。
難しいことをやらせるつもりで、このステップはスキップしてよいとの説明がある
Step [O5o9o2o0] 2.Easy: Obstacle pyramids
動画を観る。
障害物を積んでみろ、ということらしい。
あとで分かったことだが、ヒントは記事のページの下の方にある。とりあえず自分で調べてやる
確かに、ブロックを積む方法が分からない。宙に浮く
👆 [Ctrl]
キーを押しながら 箱を動かしたりしてみるが、箱の表面に スナップするようなことはなく 突き抜けたりする
📖 Unityショートカット : エディタ上でオブジェクトを密着させて配置する
👆 [Shift] + [Ctrl]
キーを押しながら 箱を動かしたりしてみるが、スナップしている感じはしない。食い込む
ただ、この操作が思っていることに一番近いから使う
- Create Emptry で
Pile
と名前を付けて 箱を4つ入れ、 Pile を[Ctrl] + [D]
で複製するなど 効率の良い作業方法を勝手にする
途中で飽きるので 完了 にする
Step [O5o9o3o0] 3.Medium: Oncoming vehicles
動画を観る。
対向車を走らせてみろ、ということらしい。
あとで分かったことだが、ヒントは記事のページの下の方にある。とりあえず自分で調べてやる
とりあえず 白いバスを置いてみるが、反対を向かせる方法が分からん。Y軸を固定して、回転すればいいのか。できた
走らせるには、スクリプトを新規作成して ゲームオブジェクトにアタッチして、
スクリプトの内容は Z軸の正の方向に進んでもらうようにすればいいと思う
BusController.cs
みたいなファイル名でいいか?
📺 やってみた
途中で飽きるので 完了 にする
Step [O5o9o4o0] 4.Hard: Camera switcher
動画を観る。
キーボードのキーを押すと 運転席視点と、車の後ろからの視点を 切り替えろ、ということらしい。
あとで分かったことだが、ヒントは記事のページの下の方にある。とりあえず自分で調べてやる
とりあえず [Edit] - [Project Settings...] - [Input Manager]
を見てみる
Jump
に Space
キーが割り当てられているので、とりあえず これを使ってみる
FollowPlayer.cs
というスクリプトは、車の後ろからの始点 を意味するので、
これとは別に PerspectiveOfDriversSeat.cs
というスクリプトを作ればいいのか?
Jump
キーを受け取るスクリプトは どのゲームオブジェクトだ?
👆 2008年頃のフォーラムらしく、リンク切れしていて リンク先の URLが業者に乗っ取られている
Unity Hub から 現在のフォーラムへ移動
👆 検索の性能が悪く、欲しい記事が見つからない
チュートリアルの記事に コメントがあるので 読んでみるが ベスト・プラクティス を感じない
Hierarchy
ビューの Main Camera
に C# スクリプトを2つアタッチすることはできるようだ。
FollowPlayer.cs
と PerspectiveOfDriversSeat.cs
の2つのスクリプトを持たせた。
このスクリプトの違いは、 offset だけ
private Vector3 offset = new Vector3(0.5f, 2, 1.5f);
👆 この x, y, z の数字は シーン画面、ゲーム画面を見ながら手調整していく
ゲーム中に Space キーを押すと、その2つのスクリプトのうち、片方のスクリプトだけが有効になるように
交互に切り替わってくれればいいわけだが
CameraSwitcher
という C# スクリプト・ファイルを作るか
そして Main Camera
ゲームオブジェクトへアタッチする
スペースキーを押したかどうかを、どうやって取得するか?
👇 例えば、これでどうか?
// Update is called once per frame
void Update()
{
var isPressSpaceKey = Input.GetKeyDown(KeyCode.Space);
}
Main Camera
にアタッチされているスクリプトの 活性/不活性 を切り替えたいが、
Main Camera
にどうアクセスし、
Main Camera
にアタッチされているスクリプトの 活性/不活性 にどうやってアクセスする?
インターネットで適当にググることにする
👇 こうすると、それっぽくなるが、思ってる感じとは違う。
思ってるのと違っていれば手調整する、の繰り返し
using System;
using UnityEngine;
public class CameraSwitcher : MonoBehaviour
{
private int cameraView;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
var isPressSpaceKey = Input.GetKeyDown(KeyCode.Space);
if (isPressSpaceKey)
{
// 0 と 1 を ひっくり返す
cameraView = 1 - cameraView;
var followPlayer = this.GetComponent<FollowPlayer>();
var perspectiveOfDriverSeat = this.GetComponent<PerspectiveOfDriversSeat>();
switch (cameraView)
{
case 0:
followPlayer.enabled = false;
perspectiveOfDriverSeat.enabled = true;
break;
case 1:
followPlayer.enabled = true;
perspectiveOfDriverSeat.enabled = false;
break;
default:
throw new Exception($"Unexpected cameraView:{cameraView}");
}
}
}
}
📺 やってみた
Step [O5o9o5o0] 5.Expert: Local multiplayer
動画を観る。
画面を2分割して、左画面と 右画面で 別のカメラにして、車の操作も 1P と 2P で分けろ、ということらしい。
あとで分かったことだが、ヒントは記事のページの下の方にある。とりあえず自分で調べてやる
ヒントによると、カメラには Viewport Rect
というプロパティがあるそうだ。確かにある
じゃあ とりあえず 2台目の カメラを 置いてみるか
Main Camera
を [Ctrl] + [D]
キーで複製する。 2P Camera
に名称変更
Vehicle
も [Ctrl] + [D]
キーで複製する。 2P Vehicle
に名称変更
2P Camera
の FollowPlayer
スクリプトの Player プロパティと、
PerspectiveOfDriversSeat
スクリプトの Player プロパティに Vehicle
が入っているので、
これを 2P Vehicle
に置き換える
Main Camera
の Viewport Rect
の X 0 Y 0 W 1 H 1
を、 X 0 Y 0 W 0.5 H 1
に置き換える
2P Camera
の Viewport Rect
の X 0 Y 0 W 1 H 1
を、 X 0.5 Y 0 W 0.5 H 1
に置き換える
カメラや 車の位置を シーン画面で調整する
PlayerController.cs
が 1P のキー設定になっている。
これを [Ctrl] + [D]
キーで複製して Player2Controller.cs
に名称変更する。
ファイルを開くと クラス名が PlayerController
なので、 Player2Controller
に変える
Player2Controller.cs
を 2P Vehicle
にアタッチする。
もともと付いていた PlayerController.cs
はリムーブする
horizontalInput = Input.GetAxis("Horizontal");
forwardInput = Input.GetAxis("Vertical");
👆 この "Horizontal" などの名称を変える必要があると思う。 Input Manager
を調べてみる
プレイヤー1と プレイヤー2で 名称が分かれているわけでも無さそうだ
📖 Unityでオフラインの対戦プレイや協力プレイを実現する方法
👆 自分で Horizontal2
のように名前を変えなければいけないみたいだ、最初から設定しておいてくれたらいいのに……
Joy Num
というのが プレイヤー番号に相当するのだろう
Negative Button
などの設定を1つ1つ変えていく
Gravity
とか Dead
とか何だか分からないが 1プレイヤーと 2プレイヤーで 同じになるように設定を変えていく
最初の設定から けっこう変えないといけない
📺 やってみた
Step [O5o9o6o0] Share your work
画像をアップロードするといいらしいが、よく分からない
スクリーンショットを撮ってアップロードする
Submission Gallery
というところに公開されるようだ
Step [O6o0] Unit 2 - Introduction
-
Unit 2 - Introduction
- Tutorial, Begginer, 5 Mins
案内役の人のテンションが上がっている動画を見る。
英語のちからがないので 直訳を読むが、 その言い回しで 何を伝えようとしているのか よく分からないが まあいいだろう
Step [O6o1o0] Lesson 2.1 - Player Positioning
-
Lesson 2.1 - Player Positioning
- Tutorial, Begginer, 1 Hour
動画を観る。 if文の話しに触れてくれる
Step [O6o1o1o0] 1.Create a new Project for Prototype 2
動画を観る
Unity Hub を使って Prototype 2
プロジェクトを新規作成し、
.unitypackage
をプロジェクトにインポートする
SampleScene
は削除する
Prototype 2
シーンを開く
Step [O6o1o2o0] 2.Add the Player, Animals, and Food
動画を観る
- キャラクターを配置する
- 牧場の娘のゲームオブジェクト名を
Player
に名称変更する
Step [O6o1o3o0] 3.Get the user’s horizontal input
動画を観る
-
Assets
フォルダーの下にScripts
フォルダーを作成する -
Assets/Scripts
フォルダーの下にPlayerController.cs
ファイルを作成する - 水平方向の入力を変数に受け取るだけ
以下略
Step [O6o1o4o0] 4.Move the player left-to-right
動画を観る。
内容の趣旨は プロトタイプ1 と被る
- キー入力を、プレイヤーの水平位置に連動させる
Step [O6o1o5o0] 5.Keep the player inbounds
動画を観る。
C# を初めて書く人に向けての動画なので、コードをコピペするだけでもいいが、一応観ていく
Step [O6o1o6o0] 6.Clean up your code and variables
動画を観る。
C# を初めて書く人に向けての動画なので、コードをコピペするだけでもいいが、一応観ていく
Step [O6o1o7o0] 7.Lesson Recap
まとめ動画を観るだけ
Step [O6o2o0] Lesson 2.2 - Food Flight
-
Lesson 2.2 - Food Flight
- Tutorial, Begginer, 1 Hour 10 Mins
動画を観るだけ
- Prefabs の説明
Step [O6o2o1o0] 1.Make the projectile fly forwards
動画を観るだけ
- 既知の技術の反復練習
Step [O6o2o2o0] 2.Make the projectile into a prefab
動画を観る
- Prefabs の使い方の実践
- プレファブを、C#スクリプトから参照できるようにする
Step [O6o2o3o0] 3.Test for spacebar press
動画を観る
- スペースバーを押下されたことを C#スクリプトで判定する if文コードブロックを書くところまで
Step [O6o2o4o0] 4.Launch projectile on spacebar press
動画を観る
- Instantiate の説明
- 1行書くだけ
📺 やってみた
Step [O6o2o5o0] 5.Make animals into prefabs
動画を観る
- 動物もプレファブにする
Step [O6o2o6o0] 6.Destroy projectiles offscreen
動画を観る
- 画面外に飛んでいったピザを削除する方法の説明(画面外に出ていった動物はまだ削除しない)
- Prefabs を Override するのが要点
- Hierarchy ビューのゲームオブジェクトにスクリプトをアタッチしても、プレファブには反映されない
- Inspecter ビューの右上の
Overrides
ドロップダウンリストをクリックして、その中のApply All
ボタンをクリックすると、プレファブに反映されると説明される
- Inspecter ビューの右上の
- Hierarchy ビューのゲームオブジェクトにスクリプトをアタッチしても、プレファブには反映されない
Step [O6o2o7o0] 7.Destroy animals offscreen
動画を観る
- 画面外に出ていった動物を削除する方法の説明
- if ~ else 文の説明
Step [O6o2o8o0] 8.Lesson Recap
動画を観る
Step [O6o3o0] Lesson 2.3 - Random Animal Stampede
-
Lesson 2.3 - Random Animal Stampede
- Tutorial, Begginer, 1 Hour
動画を観る
- Ramdomness
Step [O6o3o1o0] 1.Create a spawn manager
動画を観る
- Unity Editor で可変サイズの配列のプロパティを置く方法の説明
Step [O6o3o2o0] 2.Spawn an animal if S is pressed
動画を観る
- Sキーを押すと 動物が発射される方法の説明
Step [O6o3o3o0] 3.Spawn random animals from array
動画を観る
- 乱数の説明
Step [O6o3o4o0] 4.Randomize the spawn location
動画を観る
- 乱数の説明(動物を生成する線上の点)
Step [O6o3o5o0] 5.Change the perspective of the camera
動画を観る
- プロパティ1個分の説明
- パースを付ける方法、パースを付けない方法の説明
Step [O6o3o6o0] 6.Lesson Recap
動画を観るだけ
Step [O6o4o0] Lesson 2.4 - Collision Decisions
-
Lesson 2.4 - Collision Decisions
- Tutorial, Begginer, 50 Mins
動画を観る
- 関数を初めて自分で書くという話し
Step [O6o4o1o0] 1.Make a new method to spawn animals
動画を観る
- 関数を始めて自分で書くという話し
- リファクタリングするだけ
Step [O6o4o2o0] 2.Spawn the animals at timed intervals
動画を観る
-
InvokeRepeating()
を使う- タイマーを1行で書ける
📺 やってみた
Step [O6o4o3o0] 3.Add collider and trigger components
動画を観る
-
コライダー
の説明 -
RigidBody
とGravity
の説明 - Inspecter ビューの
Overrides
ドロップダウンリストのApply All
ボタンも必要なら使う
Step [O6o4o4o0] 4.Destroy objects on collision
動画を観る
-
OnTriggerEnter
メソッドのオーバーライドの説明 - きつねから 止まっているピザに当たりに来ても 衝突とは判定されない?
- 動いているピザが きつねに当たると 衝突と判定される?
Step [O6o4o5o0] 5.Trigger a “Game Over” message
動画を観る
-
Debug.Log()
の説明- Unity のステータスバーは暗くて文字が見えない(文字の色ではなく、ログが非表示になっている)
-
[Window] - [General] - [Console]
からコンソール・ウィンドウを表示できるが、デバッグ・ログは出ていない- コンソールの右上の [吹き出しに?が描かれたアイコン] をクリックすると ログが表示された。分かりづらい
- ステータスバーにも文字が表示されるようになった
- コンソールの右上の [吹き出しに?が描かれたアイコン] をクリックすると ログが表示された。分かりづらい
-
- Unity のステータスバーは暗くて文字が見えない(文字の色ではなく、ログが非表示になっている)
- シーンビューから ピザと動物を消す
- ソースコードの自動フォーマットの説明
Step [O6o4o6o0] 6.Lesson Recap
動画を観るだけ
Step [O6o5o0] Challenge 2 - Play Fetch
📅 2022-12-03
-
Challenge 2 - Play Fetch
- Tutorial, Begginer, 1 Hour -
バグのあるプログラムを直していこう、というもの
Step [O6o5o1o0] 1.Overview
動画を観る
-
Challenge 2 - Starter Files.zip
をダウンロードして解凍する。Prototype-2_Starter-Files.unitypackage
が入っている -
Prototype 2
プロジェクトに、Prototype-2_Starter-Files.unitypackage
パッケージをインポートする
Project ビュー:
📂 Assets
└── 📂 Challenge 2
├── 📂 Instructions
│ └── 📺 Challenge 2 - Outcome # 完成形の動画
└── 📄 Challenge 2 # シーン
👆 インポートされる
Challenge 2
シーンをクリックする
Challenge 2 - Outcome
動画をクリックして動画を観る
Step [O6o5o2o0] 2.Warning
このチャレンジの説明
- 以下のステップを続けて読んでいく
Step [O6o5o3o0] 3.Dogs are spawning at the top of the screen
画面の上で 犬が生成されているので、これをボールに変えること
Step [O6o5o4o0] 4.The player is spawning green balls instead of dogs
スペースキーを押すと 農夫が緑色のボールをスポーンしている。
代わりに 犬を生成するように変えること
Step [O6o5o5o0] 5.The balls are destroyed if anywhere near the dog
犬の近くでないのに、ボールが破棄されている。
代わりに、犬にぶつかったときにボールが破棄されているように見えてほしい
Step [O6o5o6o0] 6.Nothing is being destroyed off screen
生成されたボールと犬が破棄されていないので、
ボールは画面下に出たとき破棄してほしいし、犬は画面左の外に出たとき破棄してほしい
Step [O6o5o7o0] 7.Only one type of ball is being spawned
ボールが1種類しか落ちてこないおんで、
ボールが3種類落ちてくるようにしてほしい
Step [O6o5o8o0] 8.Bonus: The spawn interval is always the same
ボールが等間隔の時間で落ちてきているので、
3~5秒の間隔でランダムに落ちてきてほしい
Step [O6o5o9o0] 9.Bonus: The player can “spam” the spacebar key
犬を連射できるので、
連射の間隔を一定時間 開けてほしい
👇 こうやった
PlayerControllerX.cs:
using UnityEngine;
public class PlayerControllerX : MonoBehaviour
{
public GameObject dogPrefab;
/// <summary>
/// 溜め時間
/// </summary>
private float chargeSecs = 1.0f;
/// <summary>
/// 経過時間
/// </summary>
private float elapsedSecs = float.MaxValue;
// Update is called once per frame
void Update()
{
elapsedSecs += Time.deltaTime;
// On spacebar press, send dog
if (Input.GetKeyDown(KeyCode.Space) && elapsedSecs > chargeSecs)
{
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
elapsedSecs = 0.0f;
}
}
}
Step [O6o6o0] Lab 2 - New Project with Primitives
📅 2022-12-03 sat 16:21
-
Lab 2 - New Project with Primitives
- Tutorial, Begginer, 1 Hour
プリミティブ
は、球体、立方体、平面 のような基本図形のこと
できあいのものをインポートせず、新規作成のプロジェクトから、作っていくという趣旨
動画を観る
Step [O6o6o1o0] 1.Create a new Project and rename your scene
動画を観る
-
Personal Project
を作る
Step [O6o6o2o0] 2.Create a background plane
動画を観る
- 背景、または床を置こう という話し
- Plane オブジェクトの Inspector ビューの Transform コンポーネントの
Reset
ボタンを押そう、という話し
Step [O6o6o3o0] 3.Create primitive Player with a new material
動画を観る
- 球体を シーン ビューに置く。名前は
Player
Project ビュー:
📂 Assets
👉 └── 📂 Materials # 新規作成
👉 └── 📄 Blue # 新規作成
- 青いマテリアルを作って、シーン ビューに置いてある球体にドラッグ&ドロップする
Step [O6o6o4o0] 4.Position camera based on project type
動画を観る
- カメラのポジションを決めよう、という話し
Step [O6o6o5o0] 5.Enemies, obstacles, projectiles & materials
動画を観る
- 敵、障害物 等の配置
- 着色
Step [O6o6o6o0] 6.Export a Unity Package backup file
動画を観る
- バックアップの取り方の説明
-
*.unitypackage
ファイルを作れる
-
📂 UnityProjects # 練習用フォルダー
👉 └── 📂 Backups # 新規作成
Step [O6o6o7o0] 7.Lesson Recap
動画を観るだけ
Step [O6o7o0] Quiz 2
-
Quiz 2
- Quiz, Begginer, 15 Mins
概要は文章が長くて堅苦しいし、読み飛ばしていいかも。
Step [O6o8o0] Bonus Features 2 - Share your Work
-
Bonus Features 2 - Share your Work
- Tutorial, Begginer, 1 Hour
Step [O6o8o1o0] 1.Overview
4つの難易度別の努力目標が与えられる
完成図の動画を観る
- 以下のステップを続けて読んでいく
Step [O6o8o2o0] 2.Easy: Vertical player movement
動画を観る
- プレイヤーを上下に動かせるようにする
Step [O6o8o3o0] 3.Medium: Aggressive animals
動画を観る
-
動物を左右から出すようにする
-
左右から出てきた動物に当たると、コンソールにゲームオーバーと表示する
-
プレイヤーに
BoxCollider
を付けると、ピザを発射した瞬間にプレイヤーが消えてしまう。また、動物が、動物に当たって消えてしまう-
レイヤー
という概念が必要-
Player
の Inspector の上の方のLayer
ドロップダウンリストのAdd Layer
をクリック- 例えば
User Layer 10
にPlayer
と入力 -
User Layer 11
にAnimal
と入力 -
User Layer 12
にProjectile
(発射物)と入力
- 例えば
-
Player
ゲームオブジェクトのLayer
ドロップダウンリストをPlayer
レイヤーに変更 - 各動物ゲームオブジェクトの
Layer
ドロップダウンリストをAnimal
レイヤーに変更 - ピザの
Layer
ドロップダウンリストをProjectile
レイヤーに変更 -
[Edit] - [Project Settings] - [Physics] -[Layer Collision Matrix]
-
Player
とAnimal
のチェックがオンである -
Player
とProjectile
のチェックをオフにする -
Animal
とAnimal
のチェックをオフにする
-
-
- ピザを参考に、プレイヤー、動物にも
RigidBody
を追加。Use Gravity
のチェックは外す
-
DetectCollisions.cs:
using UnityEngine;
/// <summary>
/// 衝突の検出
/// </summary>
public class DetectCollisions : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
/// <summary>
/// 自分: 動物
/// </summary>
/// <param name="other">農夫、動物</param>
private void OnTriggerEnter(Collider other)
{
if (gameObject.name == "Player")
{
Debug.Log("Damage! Game Over!");
}
// このスクリプトの所有者を破棄
Destroy(gameObject);
// このスクリプトの所有者と衝突した方を破棄
Destroy(other.gameObject);
}
}
PlayerController.cs:
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float horizontalInput;
public float verticalInput;
public float speed = 10.0f;
public float xRange = 10;
/// <summary>
/// 発射するもの
/// </summary>
public GameObject projectilePrefab;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
// Keep the player in bounds
if (transform.position.x < -xRange)
{
transform.position = new Vector3(-xRange, transform.position.y, transform.position.z);
}
if (transform.position.x > xRange)
{
transform.position = new Vector3(xRange, transform.position.y, transform.position.z);
}
horizontalInput = Input.GetAxis("Horizontal");
transform.Translate(Vector3.right * horizontalInput * Time.deltaTime * speed);
verticalInput = Input.GetAxis("Vertical");
transform.Translate(Vector3.forward * verticalInput * Time.deltaTime * speed);
// Launch a projectile from the player
if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(projectilePrefab, transform.position, projectilePrefab.transform.rotation);
}
}
}
Step [O6o8o4o0] 4.Hard: Game user interface
動画を観る
やりたいことは次の通り
プレイヤーに Lives
というプロパティーを持たせ、 3 から開始し、 0 になると ログに Game Over
と出す。
動物とプレイヤーが衝突すると Lives が 1 減る。
Score
というプロパティーがあり、 0 から開始し、 ピザと動物が衝突すると 1 増える。
Lives
と Score
は コンソールに表示する
プレイヤーに Lives
や Score
を持たせると、プレイヤーを破棄したときに Lives
と Score
も画面から消えてしまう。
とりあえず GameManager
ゲームオブジェクトを新規作成して、 GameManager
C#スクリプトをアタッチすることにする
using UnityEngine;
public class GameManager : MonoBehaviour
{
public int lives = 3;
public int score = 0;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Lives
と Score
が変化するタイミング、 Game Over
と表示するタイミングを以下にリストする
- 動物とプレイヤーが衝突したとき
- ピザと動物が衝突したとき
-
Score
が 0 になったタイミング
👇 とりあえず Lives
を 1 減らすメソッドと、 Lives
が 0 になったときに Game Over
を表示するコードを GameManager.cs
に追加する。
ついでに Score
を 1 増やすメソッドも追加する
/// <summary>
/// ライフを1減らす
/// </summary>
public void DecreaseLive()
{
if (0 < lives)
{
lives--;
Debug.Log($"Lives:{lives}");
if (lives == 0)
{
Debug.Log("Game Over");
}
}
}
/// <summary>
/// スコアを1増やす
/// </summary>
public void IncreaseLive()
{
score++;
Debug.Log($"Score:{score}");
}
👇 DetectCollisions.cs
の OnTriggerEnter
を書きかえる
/// <summary>
///
/// </summary>
/// <param name="other"></param>
private void OnTriggerEnter(Collider other)
{
// レイヤー名を取得
var myLayerName = LayerMask.LayerToName(gameObject.layer);
var opponentLayerName = LayerMask.LayerToName(other.gameObject.layer);
// Debug.Log($"myLayerName:{myLayerName} opponentLayerName:{opponentLayerName}");
// プレイヤーが、動物に衝突したとき
if (myLayerName == "Player" && opponentLayerName == "Animal")
{
var gameManagerScript = GameObject.Find("GameManager").GetComponent<GameManager>();
// ライフを減らす
gameManagerScript.DecreaseLive();
if (gameManagerScript.lives < 1)
{
// プレイヤーを破棄
Destroy(gameObject);
}
}
// 発射物が、動物に衝突したとき
if (myLayerName == "Projectile" && opponentLayerName == "Animal")
{
var gameManagerScript = GameObject.Find("GameManager").GetComponent<GameManager>();
// スコアを増やす
gameManagerScript.IncreaseLive();
}
// このスクリプトの所有者を破棄(プレイヤーを除く)
if (myLayerName != "Player")
{
Destroy(gameObject);
}
// 衝突した相手の方を破棄(プレイヤーを除く)
if (opponentLayerName != "Player")
{
Destroy(other.gameObject);
}
}
Step [O6o8o5o0] 5.Expert: Animal hunger bar
動画を観る
- 大きな改造になるので、改造に取り掛かる前に Export Package で バックアップを残した方がよい
やりたいことは次の通り
各動物の上に [空腹バー] を表示する。
[空腹バー] は最初空っぽで、ピザを当てるごとに増えていく。 [空腹バー] が満たされると動物は破棄される。
動物の種類ごとに、ピザを何回当てればいいか異なる
思ったのは次の通り
GUI を作るのは スキルレベル が高すぎる。平面図形を使った簡単なものでいいか。
黒い平面と、緑色の平面を2枚重ねればいいのでは。
緑色の平面と、黒い平面の左側を揃えて、緑色の平面の横幅が 0~黒い平面の横幅 に伸びていくと考える
Scene ビュー:
📄 HungerBar # GameObject
├── 📄 Plane_Green # GameObject with Material
└── 📄 Plane_Black # GameObject with Material
この HungerBar
ゲームオブジェクトを 動物の真上に くっつけるにはどうすればいいか?
とりあえず、 HunberBar
C#スクリプトを作って、 HunberBar
ゲームオブジェクトにアタッチする
次に、動物に 空腹 カウントを持たせることにする。
動物は [空腹バー] を持っているのだから、空腹バーに 空腹カウントを持たせるのがよさそう。
現在値の value
、 最大値の max
があればいいだろうか。
空腹バーのためのコードを追加
次に、ピザが動物に当たったときに、 満腹度を 1 増やしたい
次に、緑色の平面の横幅を変更したい。
どうやって 緑色の平面 を取得するのか?
HungerBar
ゲームオブジェクト の子要素の Plane_Green
ゲームオブジェクトを取るには?
ヒエラルキー・ビューのゲームオブジェクトを指すフルパスのようなものは無いらしい
動物から、 [空腹バー] への紐づきが無いことに気づく。
Animal
C#スクリプトを作成し、 各動物にアタッチする
コードは以下の通り
Animal.cs:
using UnityEngine;
public class Animal : MonoBehaviour
{
/// <summary>
/// 空腹バー
/// </summary>
public GameObject hungerBarPrefab;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
SpawnManager.cs / SpawnRandomAnimal method:
public GameObject hungerBarPrefab;
private float spawnRangeZ = 10;
private float spawnPosX = 30;
void SpawnRandomAnimal()
{
// 進行方向
// -1: to right
// 0: to down
// 1: to left
var angleType = Random.Range(-1, 2);
// Randomly generate animal index and spawn position
Vector3 spawnPos;
if (angleType == 0)
{
spawnPos = new Vector3(Random.Range(-spawnRangeX, spawnRangeX), 0, spawnPosZ);
}
else if (angleType == 1)
{
spawnPos = new Vector3(spawnPosX, 0, Random.Range(-spawnRangeZ, spawnRangeZ));
}
else
{
spawnPos = new Vector3(-spawnPosX, 0, Random.Range(-spawnRangeZ, spawnRangeZ));
}
// 動物
int animalIndex = Random.Range(0, animalPrefabs.Length);
var animal = Instantiate(animalPrefabs[animalIndex], spawnPos, animalPrefabs[animalIndex].transform.rotation);
animal.transform.Rotate(Vector3.up, (angleType * 90.0f + 360.0f) % 360.0f);// 向きを変える
var animalScript = animal.GetComponent<Animal>();
// 空腹バー
var hungerBar = Instantiate(hungerBarPrefab, spawnPos, new Quaternion(0.0f, 0.0f, 0.0f, 0.0f));
var hungerBarScript = hungerBar.GetComponent<HungerBar>();
// 動物の種類に応じて、空腹バーの最大値を変更する
if (animal.name == "Animal_Fox_01(Clone)")
{
hungerBarScript.max = 1;
}
else if (animal.name == "Animal_Doe_01(Clone)")
{
hungerBarScript.max = 2;
}
else if (animal.name == "Animal_Moose_01(Clone)")
{
hungerBarScript.max = 3;
}
// 動物と空腹バーを相互紐づけ
hungerBarScript.precededPrefab = animal;
animalScript.hungerBarPrefab = hungerBar;
}
DetectCollisions.cs / OnTrigger method:
private void OnTriggerEnter(Collider other)
{
bool isDestroySelf = false;
bool isDestroyOpponent = false;
// レイヤー名を取得
var myLayerName = LayerMask.LayerToName(gameObject.layer);
var opponentLayerName = LayerMask.LayerToName(other.gameObject.layer);
// Debug.Log($"myLayerName:{myLayerName} opponentLayerName:{opponentLayerName}");
// プレイヤーが、動物に衝突したとき
if (myLayerName == "Player" && opponentLayerName == "Animal")
{
var gameManagerScript = GameObject.Find("GameManager").GetComponent<GameManager>();
// ライフを減らす
gameManagerScript.DecreaseLive();
if (gameManagerScript.lives < 1)
{
// プレイヤーを破棄
Debug.Log($"Destroy player. Life none.");
isDestroySelf = true;
}
}
// 発射物が、動物に衝突したとき
if (myLayerName == "Projectile" && opponentLayerName == "Animal")
{
// スコアを増やす
var gameManagerScript = GameObject.Find("GameManager").GetComponent<GameManager>();
gameManagerScript.IncreaseLive();
// 動物から、空腹バーを取得
var animalScript = other.gameObject.GetComponent<Animal>();
var hungerBar = animalScript.hungerBarPrefab;
var hungerBarScript = hungerBar.GetComponent<HungerBar>();
// 満腹度を増やす
hungerBarScript.IncreaseValue();
// 満腹になっていれば、その動物オブジェクトと、空腹バーの両方を破棄
if (hungerBarScript.IsFull())
{
Debug.Log($"Destroy animal. value:{hungerBarScript.value} max:{hungerBarScript.max}");
isDestroyOpponent = true;
Destroy(hungerBar);
}
// 発射物を破棄
Debug.Log($"Destroy food. Because it hit an animal.");
isDestroySelf = true;
}
// このスクリプトの所有者を破棄
if (isDestroySelf)
{
Destroy(gameObject);
}
// 衝突した相手の方を破棄
if (isDestroyOpponent)
{
Destroy(other.gameObject);
}
}
GameManager.cs:
using UnityEngine;
public class GameManager : MonoBehaviour
{
public int lives = 3;
public int score = 0;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
/// <summary>
/// ライフを1減らす
/// </summary>
public void DecreaseLive()
{
if (0 < lives)
{
lives--;
Debug.Log($"Lives:{lives}");
if (lives == 0)
{
Debug.Log("Game Over");
}
}
}
/// <summary>
/// スコアを1増やす
/// </summary>
public void IncreaseLive()
{
score++;
Debug.Log($"Score:{score}");
}
}
HungerBar.cs:
using UnityEngine;
/// <summary>
/// 空腹バー
///
/// - 満腹度
/// </summary>
public class HungerBar : MonoBehaviour
{
/// <summary>
/// 先行プレファブ
///
/// - 張り付き先のゲームオブジェクト
/// </summary>
public GameObject precededPrefab;
/// <summary>
/// 現在値
/// </summary>
public int value = 0;
/// <summary>
/// 最大値
/// </summary>
public int max = 1;
// Start is called before the first frame update
void Start()
{
// 緑色の平面の横幅を変更する
this.Repaint();
}
// Update is called once per frame
void Update()
{
// 先行プレファブと、位置を同じくします
if (precededPrefab != null)
{
gameObject.transform.position = precededPrefab.transform.position;
}
}
/// <summary>
/// 満タンか?
/// </summary>
/// <returns></returns>
public bool IsFull()
{
return max <= value;
}
/// <summary>
/// 1 増やす
/// </summary>
public void IncreaseValue()
{
if (value < max)
{
value++;
Debug.Log($"Nice taste! value:{value} max:{max}");
}
// 緑色の平面の横幅を変更する
this.Repaint();
}
/// <summary>
/// 緑色の平面の横幅を変更する
/// </summary>
private void Repaint()
{
if (precededPrefab != null)
{
var rate = (float)value / (float)max;
var greenPlain = gameObject.transform.GetChild(0);
greenPlain.transform.localScale = new Vector3(rate, greenPlain.transform.localScale.y, greenPlain.transform.localScale.z);
// Debug.Log($"Repaint. greenPlain.name:{greenPlain.name} greenPlain.transform.localScale:{greenPlain.transform.localScale} rate:{rate} value:{value} max:{max}");
}
//else
//{
// Debug.Log("[Error] Repaint failed. Because precededPrefab is null.");
//}
}
}
見栄えが悪いところはあるが、大変なので先に進むことにする
Step [O6o8o6o0] 6.Hints and solution walkthrough
ヒントが書いてある
Step [O6o8o7o0] Share your work
📅 2022-12-04 sun 18:30
作品動画をアップロードすることができる
📺 やってみた
Step [O6o9o0] Unit 3 - Introduction
-
Unit 3 - Introduction
- Tutorial, Begginer, 5 Min
Step [O6o9o1o0] 1.Unit 3 - Introduction
動画を観るだけ
- おじさんがジョークを言うようになってきた
- BGM、効果音、パーティクルの前振り
Step [O6o9o2o0] Lesson 3.1 - Jump Force
📅 2022-12-04 sun 18:42
-
Lesson 3.1 - Jump Force
- Tutorial, Begginer, 1 Hour 30 Mins
Step [O6o9o2o1o0] Overview Video
動画を観るだけ
- 放物線を描くには
Translate()
では困難なので、Unity の物理演算AddForce()
を使おう、という話し
Step [O6o9o2o2o0] 1.Open prototype & change background
動画を観る
- 新しいプロジェクト
Prototype 3
を作って、Prototype-3_Starter-Files.unitypackage
をインポートする -
SpriteRenderer
の説明
Step [O6o9o2o3o0] 2.Choose and set up a player character
動画を観る
-
Player
ゲームオブジェクトの準備
Step [O6o9o2o4o0] 3.Make player jump at start
動画を観る
-
GetComponent<T>()
の使い方 -
RigidBody
のAddForce()
の使い方
Step [O6o9o2o5o0] 4.Make player jump if spacebar pressed
動画を観る
- スペース・バーを押下してジャンプする
- ジャンプの上昇をすぐにする
ForceMode.Impulse
定数
Step [O6o9o2o6o0] 5.Tweak the jump force and gravity
動画を観る
-
Physics.gravity
フィールドの説明 -
*=
演算子の説明
Step [O6o9o2o7o0] 6.Prevent player from double-jumping
動画を観る
-
bool
型の説明 -
&&
演算子の説明 -
OnCollisionEnter
メソッドの説明
Step [O6o9o2o8o0] 7.Make an obstacle and move it left
動画を観る
- 画面を固定して、障害物や、背景の方を高速に移動させる説明
Step [O6o9o2o9o0] 8.Create a spawn manager
動画を観る
-
SpawnManager
の作成
Step [O6o9o2o10o0] 9.Spawn obstacles at intervals
動画を観る
- 障害物の生成をリピート
- 衝突時に物体が傾く軸方向のフリーズの説明
Step [O6o9o2o11o0] 10.Lesson Recap
📅 2022-12-04 sun 22:03
動画を観るだけ
📺 やってみた
Step [O6o9o3o0] Lesson 3.2 - Make the World Whiz By
-
Lesson 3.2 - Make the World Whiz By
- Tutorial, Begginer, 1 Hour 10 Mins
Step [O6o9o3o1o0] Overview Video
動画を観るだけ
- このレッスンでやる内容のあらすじ
Step [O6o9o3o2o0] 1.Create a script to repeat background
動画を観る
- 背景がスクロールしているように見える仕組みの説明
-
RepeatBackground
C#スクリプトをBackground
オブジェクト(背景)にアタッチ
Step [O6o9o3o3o0] 2.Reset position of background
動画を観る
- 背景がリピートするスクリプトを書く
Step [O6o9o3o4o0] 3.Fix background repeat with collider
📅 2022-12-06 sun 19:42
動画を観る
- 背景の横幅を正確に計算する
Step [O6o9o3o5o0] 4.Add a new game over trigger
動画を観る
-
Tag
の作り方、付け方 - 地面と、障害物を区別する
CompareTag()
Step [O6o9o3o6o0] 5.Stop MoveLeft on gameOver
動画を観る
- スクリプトから、別のゲームオブジェクトにアタッチされているスクリプトの取得方法の説明
Step [O6o9o3o7o0] 6.Stop obstacle spawning on gameOver
動画を観る
- 同様
Step [O6o9o3o8o0] 7.Destroy obstacles that exit bounds
動画を観る
- 通り過ぎて行った障害物を削除する
📺 やってみた
Step [O6o9o3o9o0] 8.Lesson Recap
📅 2022-12-06 sun 20:56
動画を観るだけ
Step [O6o9o4o0] Lesson 3.3 - Don't Just Stand There
📅 2022-12-07 sun 19:11
-
Lesson 3.3 - Don't Just Stand There
- Tutorial, Begginer, 1 Hour
Step [O6o9o4o1o0] Overview Video
動画を見るだけ
-
AnimationController
の前振り
Step [O6o9o4o2o0] 1.Explore the player’s animations
動画を見る
-
Animatoion Controller
の説明 - いろいろダブルクリックして覗き見るだけ
-
Player
ゲームオブジェクトのAnimator
コンポーネントのController
欄をダブルクリックする
-
Step [O6o9o4o3o0] 2.Make the player start off at a run
動画を見る
- キャラクターが走るようになる
- テキストボックスに、数値を入れる
📺 やってみた
Step [O6o9o4o4o0] 3.Set up a jump animation
動画を見る
-
PlayerController
C#スクリプトから、Player
ゲームオブジェクトの持つAnimator
コンポーネントへアクセスする
Step [O6o9o4o5o0] 4.Adjust the jump animation
動画を見る
- 空中を走るのを直す
Step [O6o9o4o6o0] 5.Set up a falling animation
動画を見る
- スクリプトを書いて、倒れ込む演技へ、状態遷移
Step [O6o9o4o7o0] 6.Keep player from unconscious jumping
動画を見る
- 倒れ込んだあとにまだジャンプできる不具合を修正する
Step [O6o9o4o8o0] 7.Lesson Recap
📅 2022-12-07 sun 21:48
動画を見るだけ
Step [O6o9o5o0] Lesson 3.4 - Particles and Sound Effects
📅 2022-12-08 sun 19:21
-
Lesson 3.4 - Particles and Sound Effects
- Tutorial, Begginer, 1 Hour
Step [O6o9o5o1o0] Overview Video
動画を見るだけ
-
Particle
や、SoundListener
の説明
Step [O6o9o5o2o0] 1.Customize an explosion particle
動画を見る
-
Player
ゲームオブジェクトへ、 パーティクルをアタッチする方法
Step [O6o9o5o3o0] 2.Play the particle on collision
動画を見る
- パーティクルの再生方法
- (プロジェクト ビューではなく)ヒエラルキー ビューの方のパーティクルを、
PlayerController
C#スクリプトへアタッチする
- (プロジェクト ビューではなく)ヒエラルキー ビューの方のパーティクルを、
Step [O6o9o5o4o0] 3.Add a dirt splatter particle
動画を見る
- 足元のパーティクル
- ジャンプ中に障害物に当たると、足元のパーティクルは消えないようだ?
Step [O6o9o5o5o0] 4.Add music to the camera object
動画を見る
- カメラは音楽を聴くための耳も兼ねている
-
AudioSource
の説明
Step [O6o9o5o6o0] 5.Declare variables for Audio Clips
動画を見る
- 効果音を
PlayerController
C#スクリプトへアタッチする
Step [O6o9o5o7o0] 6.Play Audio Clips on jump and crash
動画を見る
- 効果音を鳴らす
📺 やってみた
Step [O6o9o5o8o0] 7.Lesson Recap
📅 2022-12-08 sun 22:05
動画を見るだけ
Step [O6o9o6o0] Challenge 3 - Balloons, Bombs, & Booleans
📅 2022-12-10 sun 11:42
-
Challenge 3 - Balloons, Bombs, & Booleans
- Tutorial, Begginer, 1 Hour -
エラーを直すというもの
-
このチャレンジ3は、最初の動かない不具合を除けば、チャレンジ2より簡単
Step [O6o9o6o1o0] 1.Overview
動画を見る
-
Challenge 3 starter files
ユニティーパッケージをPrototype 3
へインポートする
👇 2022年12月10日現在、このソースには NullReferenceException
という例外がある不具合があるようで、以下のように修正する必要がある
PlayerControllerX.cs:
void Start()
{
// ...
playerRb = GetComponent<Rigidbody>(); // 追加
// ...
}
Step [O6o9o6o2o0] 2.Warning
この章の説明を読むだけ
Step [O6o9o6o3o0] 3.The player can’t control the balloon
- 「プレイヤーがスペースバーを押すと、風船が浮き上がるようにしてほしい」とのことだが、スペースバーを押すと浮き上がる。
ヒントを見てみると、NullReferenceException
を直せ、というチャレンジだったようだ。もう直した
Step [O6o9o6o4o0] 4.The background only moves when the game is over
- ゲームオーバーのとき背景が動くようになっている。これを、ゲーム開始時に背景が動き、ゲームオーバーのとき背景が止まるようにしてほしい
- 条件判定の真偽が逆なのだろうと当たりを付けて、すぐ直す
Step [O6o9o6o5o0] 5.No objects are being spawned
- お金や爆弾といったゲームオブジェクトが画面上に生成されてこないので、数秒ごとに生成されてくるようにしてほしい
- ゲームオブジェクトを生成するのは
SpawnManager
C#スクリプトだろうと当たりを付けて、すぐ直す
- ゲームオブジェクトを生成するのは
Step [O6o9o6o6o0] 6.Fireworks appear to the side of the balloon
- 「風船の近くに火花が現れているので、風船のところで火花が現れてほしい」ということだが、ゲーム画面を見ても 何が悪くて どう直したらいいのか説明からは分からない
- 爆発と 火花は 別のパーティクルのようだ
- シーン ビューで、遠景にすると 遠くで火花が出ていることが分かった
- ポジションの数値を直すだけでいいのか?
Step [O6o9o6o7o0] 7.The background is not repeating properly
- 背景のスクロールのリピートのつながりがおかしいから、つながりの切れ目が見えないように直してほしい
- C#スクリプト全体を にらめっこしてると 問題個所が分かる
Step [O6o9o6o8o0] 8.Bonus: The balloon can float way too high
- 風船が高く浮きすぎているから、高く浮きすぎないようにしてほしい
- 風船が高く浮きすぎるのは、与える力が大きすぎるか、風船が軽すぎるか、それ以外かの理由だろうか?
- 風船の軽さは、
Player
ゲームオブジェクトの持つRigidBody
コンポーネントのmass
で質量をキログラム単位で指定すればいいと思うが、風船は重いものではないだろう - 与える力は、
Player
ゲームオブジェクトの持つPlayerControllerX
C#スクリプトのfloatForce
を指定すればいいと思う- じゃあ、バイナリーサーチでちょうどいい感じの数を探そうかと思ったが、風船が軽すぎるのか
floatForce
は 1 違うだけでだいぶ違う。少しずつ ずらして加減を調整する
- じゃあ、バイナリーサーチでちょうどいい感じの数を探そうかと思ったが、風船が軽すぎるのか
- 風船の軽さは、
- 風船が高く浮きすぎるのは、与える力が大きすぎるか、風船が軽すぎるか、それ以外かの理由だろうか?
Step [O6o9o6o9o0] 9.Bonus: The balloon can drop below the ground
📅 2022-12-10 sun 14:24
- 風船が画面下の外へ落ちて行ってしまう。これを、画面下で跳ね返るようにしてほしい。跳ね返るとき効果音も付けてほしい
- C#スクリプトを書けばいいのかもしれないが、チュートリアルのチャレンジ問題にしては手間が混み過ぎる。発想の問題。ヒントを見る
-
PlayerController
C#スクリプトのOnCollisionEnter()
メソッドを思い出す -
Ground
ゲームオブジェクトに、Ground
タグを付ける。Box Collider
コンポーネントも付ける
-
- C#スクリプトを書けばいいのかもしれないが、チュートリアルのチャレンジ問題にしては手間が混み過ぎる。発想の問題。ヒントを見る
参考:
if (other.gameObject.CompareTag("Ground"))
{
// 接地
// Debug.Log("Is ground!");
playerRb.AddForce(Vector3.up * floatForceOnGround);
playerAudio.PlayOneShot(boingSound, 1.0f);
}
📺 やってみた
Step [O6o9o7o0] Lab 3 - Player Control
📅 2022-12-10 sun 14:54
-
Lab 3 - Player Control
- Tutorial, Begginer, 1 Hour -
ほとんど復習
Step [O6o9o7o1o0] Overview Video
動画を見るだけ
Step [O6o9o7o2o0] 1.Create PlayerController and plan your code
動画を見る
- 基本操作の復習といった内容
-
Unity Hub
からPersonal Project
プロジェクトを開く -
Player
ゲームオブジェクトへPlayerController
C#スクリプトをアタッチする
-
Step [O6o9o7o3o0] 2.Basic movement from user input
動画を見る
- 説明がどんどん省略され始めてきている
- 十字キーを押したら、玉が転がるところの説明
-
PlayerController
C#スクリプトの書き方の復習
-
Step [O6o9o7o4o0] 3.Constrain the Player’s movement
動画を見る
- プレイヤーが転がらないように
Player
ゲームオブジェクトが持つRigidbody
コンポーネントの[Constraints] - [Freeze Rotation]
で制約を付ける - 玉が画面外に転がりでないように、左右に壁を置くというもの
-
Purple
材質を追加、壁を紫色にする
-
- 玉が画面外に転がりでないように、上下に
PlayerController
C#スクリプトで制限するというもの
Step [O6o9o7o5o0] 4.Code Cleanup and Export Backup
動画を見る
-
Environment
ゲームオブジェクトを作って、その下へWall
ゲームオブジェクトを入れる、といった片づけ -
Update()
メソッドの中の処理を、MovePlayer()
メソッドやConstrainPlayerPosition()
メソッドに分割するなどの、片づけ
Step [O6o9o7o6o0] 5.Lesson Recap
📅 2022-12-10 sun 17:39
動画を見るだけ
Step [O6o9o8o0] Quiz 3
-
Quiz 3
- Quiz, Begginer, 15 Mins
概要は読まなくていいかも
Step [O6o9o9o0] Bonus Features 3 - Share your Work
📅 2022-12-10 sun 18:01
-
Bonus Features 3 - Share your Work
- Tutorial, Begginer, 1 Hour
難しい課題に挑めるやつだ
Step [O6o9o9o1o0] 1.Overview
完成図の動画を観る
Step [O6o9o9o2o0] 2.Easy: Randomize obstacles
動画を観る
- 柵だけでなく、積み上げた箱や、ドラム缶も生成しよう、というもの
- 変数を配列に変える。インデックスの選択には乱数を使う
Step [O6o9o9o3o0] 3.Medium: Double jump
動画を観る
- 2段ジャンプを実装しよう、というもの
- 2段ジャンプ中かどうかのフラグを付けたらいいのだろうか? フラグ名は
isFirstJump
にしてみる
要点:
if (Input.GetKeyDown(KeyCode.Space) && (isOnGround || isFirstJump) && !gameOver)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
{
// ジャンプ
isFirstJump = !isFirstJump;
// ^^^^^^^^^^^^
}
Step [O6o9o9o4o0] 4.Hard: Dash ability and score
動画を観る
- プレイヤーが特定のキーを押下している間、ダッシュするよう実装してほしい
- 例えば
D
キーとか - フラグを使うか? フラグ名は
isDash
とかにするか? - プレイヤーではなく、障害物と背景のスピードを変えなければいけないのが難しい
-
MoveLeft
C#スクリプトの方に、PlayerController
C#スクリプトを参照するように変数を作ればいいのか? と思ったらgameOver
フィールドを見るために既に有った -
PlayerController
C#スクリプトにspeed
フィールドを追加するか?
-
- 例えば
- また、スコアを実装してほしい。ダッシュ中はスコアが2倍になる。ゲームオーバーでスコアのカウントアップを止める
- スコアは単純な実装にする
MoveLeft.cs:
var speed = playerControllerScript.speed;
if (playerControllerScript.gameOver == false)
{
transform.Translate(Vector3.left * Time.deltaTime * speed);
}
PlayerController.cs:
if (Input.GetKeyDown(KeyCode.D) && isOnGround && !gameOver)
{
isDash = !isDash;
if (isDash)
{
// ダッシュ
Debug.Log("Dash!");
speed = speedHigh;
playerAnim.SetFloat("Speed_f", 2.0f);
}
else
{
// ダッシュを止める
Debug.Log("Walk!");
speed = speedNormal;
playerAnim.SetFloat("Speed_f", 1.0f);
}
}
if (isDash)
{
score += 2;
}
else
{
score++;
}
📺 やってみた
Step [O6o9o9o5o0] 5.Expert: Game start animation
動画を観る
- ゲーム開始直後から走っているが、これを、最初は背景が止まっていて、画面の外から歩いてきて、そして走る、というゲーム開始時の演出を付けてほしい
-
SpawnManager
C#スクリプトのStart()
メソッドで行っている、InvokeRepeating()
による繰り返し処理を遅らせた方がいいのか?
-
- ヒントを見る
-
lerping
というのは、動作A, B の間を補完することを言うらしい
-
- 読者のコメントを見る
- 愚直にやっているようだ。簡単にできないか?
- とりあえず、イントロを 3秒 と固定して、プログラムを書いてみる
-
MoveLeft
C#スクリプトとSpawnManager
C#スクリプトを無効化したまま初めて、 3秒経過してから enable にする、といったことはできるか?-
GameManager
C#スクリプトを新規作成した方が楽そう - タイマーを作ったことはあっただろうか?
-
-
👇 チャレンジ2で、経過時間をカウントしていたことを思い出す
/// <summary>
/// 経過時間
/// </summary>
private float elapsedSecs = float.MaxValue;
3 秒間かけて 画面外から 所定の位置へ歩いてくる、というのは どうやって作る?
TimeLine というものがあるらしいが使い方が分からない
Vector3.Lerp()
というメソッドもあるらしいが、よくわからない
- ひとまず、プレイヤーの初期位置を 画面左端の外側になるよう、
Ground
ゲームオブジェクトの左端に置く。 position x=-10 とする。重力で端から落ちないように気を付ける -
GameManager
C#スクリプトで、3秒経過したら、 position x=0 とする - これだと、3秒後に瞬間移動するわけなので、その途中を補完するように見せたい
- 足元の土煙(パーティクル)は、
enabled
ではなく、playOnAwake
チェックボックスのチェックを外して、あとでPlay()
で開始するようにする- 接地状態だと
Play()
してしまうので、アニメーション・ステートを確認する
- 接地状態だと
👇 以下で、だいたい うまくいった
GameManager.cs:
using UnityEngine;
public class GameManager : MonoBehaviour
{
/// <summary>
/// ゲーム開始時の演出時間(秒)
/// </summary>
public float introductionSecs = 2.0f;
/// <summary>
/// 経過時間(秒)
/// </summary>
private float elapsedSecs;
private GameObject player;
public ParticleSystem playerDirtSplatter; // 足元の土煙
private GameObject background;
private GameObject spawnManager;
private Animator playerAnim;
private bool isGameStart;
private Vector3 preStartPos;
private Vector3 startPos = new Vector3(0.0f, 0.0f, 0.0f);
// Start is called before the first frame update
void Start()
{
player = GameObject.Find("Player");
background = GameObject.Find("Background");
spawnManager = GameObject.Find("SpawnManager");
playerAnim = player.GetComponent<Animator>();
preStartPos = player.transform.position;
}
// Update is called once per frame
void Update()
{
elapsedSecs += Time.deltaTime;
if (!isGameStart)
{
// 中間補完
player.transform.position = Vector3.Lerp(preStartPos, startPos, elapsedSecs / introductionSecs);
// End
if (elapsedSecs > introductionSecs)
{
// 演技
playerAnim.SetFloat("Speed_f", 1.0f); // 走るポーズ
playerDirtSplatter.Play(); // 足元の土煙
background.GetComponent<MoveLeft>().enabled = true;
spawnManager.GetComponent<SpawnManager>().enabled = true;
isGameStart = true;
}
}
}
}
PlayerController.cs:
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
// ...
if (playerAnim.GetCurrentAnimatorStateInfo(0).IsName("Run_Static"))
{
dirtParticle.Play(); // 土煙
}
}// ...
}
Step [O6o9o9o6o0] 6.Hints and solution walkthrough
📅 2022-12-10 sun 23:35
読むだけ
Step [O6o10o0] Unit 4 - Introduction
📅 2022-12-10 sun 23:40
-
Unit 4 - Introduction
- Tutorial, Begginer, 5 Min
- このコース全体で、 Unit 4 が1番難しいとのこと
- 難しいというのは、ベクトル計算を使うことを言ってるのか? ベクトル計算得意なら、むしろ簡単
- ボーナス フューチャーの章がベリーハード
- 難しいというのは、ベクトル計算を使うことを言ってるのか? ベクトル計算得意なら、むしろ簡単
Step [O6o10o1o0] Lesson 4.1 - Watch Where You’re Going
📅 2022-12-11 sun 10:33
-
Lesson 4.1 - Watch Where You’re Going
- Tutorial, Begginer, 1 Hour
Step [O6o10o1o1o0] Overview Video
動画観るだけ
- カメラ操作の話しか?
-
Focal Point
- 島が回転するのではなく、カメラが島の中心を軸にして島の外周を回る
あとで分かったことだが、カメラの回転というのは、カメラが首を振るのではなく、焦点を中心に周囲を回ることらしい
Step [O6o10o1o2o0] 1.Create project and open scene
動画観る
-
新しいプロジェクト
Prototype 4
を作って、Prototype-4_Starter-Files.unitypackage
をインポートする -
ゲームプレイすると、パーティクルが動いている。画面は暗いし、カメラは動かない。
Step [O6o10o1o3o0] 2.Set up the player and add a texture
動画観る
- 球体を置いて、プレイヤーとする
Step [O6o10o1o4o0] 3.Create a focal point for the camera
動画観る
- 島の中心を焦点として、カメラが島の周りを回るようにする方法
-
Focal Point
ゲームオブジェクトを作って、その下へMain Camera
を移動する -
RotateCamera
C#スクリプトを作って (Main Camera
の方ではなく)Focal Point
ゲームオブジェクトの方へアタッチ
-
Step [O6o10o1o5o0] 4.Rotate the focal point by user input
動画観る
- 左キー、右キーに応じて、カメラを軸回転できるようにする
Step [O6o10o1o6o0] 5.Add forward force to the player
動画観る
- 上キー、下キーに応じて、プレイヤーを操作できるようにする
-
PlayerController
C#スクリプトを作る
-
Step [O6o10o1o7o0] 6.Move in direction of focal point
動画観る
- プレイヤーを、前後に移動するのではなく、フォーカルポイントが向いている方向と、移動する方向を揃える、といった振る舞いに変更する
Step [O6o10o1o8o0] 7.Lesson Recap
動画を観るだけ
📅 2022-12-11 sun 13:02
Step [O6o10o2o0] Lesson 4.2 - Follow the Player
📅 2022-12-11 sun 16:08
-
Lesson 4.2 - Follow the Player
- Tutorial, Begginer, 1 Hour
Step [O6o10o2o1o0] Overview Video
動画を観るだけ
- 敵を作るという前振り
- ベクトル計算の紹介
Step [O6o10o2o2o0] 1.Add an enemy and a physics material
動画を観る
- 敵を作る。敵は、プレイヤー(球)を弾き返すだけの物理的な設定がある
-
Physics Materials
フォルダーを作る-
Bouncy
物理素材を作る- アタッチする
-
Step [O6o10o2o3o0] 2.Create enemy script to follow player
動画を観る
- プレイヤーを追いかける振る舞いを C#スクリプトで書き、敵にアタッチする
-
Enemy
C#スクリプト作成、Enemy
ゲームオブジェクトへアタッチ - ベクトル計算を使う
-
normalized
を使う
-
📺 やってみた
Step [O6o10o2o4o0] 3.Create a lookDirection variable
動画を観る
- コードが読みにくくなったので、読みやすくしようという話し
-
lookDirection
変数を作る
Step [O6o10o2o5o0] 4.Create a Spawn Manager for the enemy
動画を観る
- 敵を生成する
SpawnManager
を作る準備 -
Prefabs
フォルダーを作る-
Enemy
ゲームオブジェクトをPrefabs
フォルダーへドラッグ&ドロップ- Hiererchy ビューの
Enemy
ゲームオブジェクトは削除
- Hiererchy ビューの
-
-
Spawn Manager
ゲームオブジェクト作成、SpawnManager
C#スクリプト作成
Step [O6o10o2o6o0] 5.Randomly generate spawn position
動画を観る
- 敵を常に同じ位置に生成している。これを、ランダムな位置に生成するよう変えたい
Step [O6o10o2o7o0] 6.Make a method return a spawn point
動画を観る
- コードを整える
Step [O6o10o2o8o0] 7.Lesson Recap
動画を観るだけ
📅 2022-12-11 sun 18:00
Step [O6o10o3o0] Lesson 4.3 - PowerUp and CountDown
-
Lesson 4.3 - PowerUp and CountDown
- Tutorial, Begginer, 1 Hour -
パワーアイテムの話しのようだ
Step [O6o10o3o1o0] Overview Video
動画を観るだけ
- コルーチンの前振り
Step [O6o10o3o2o0] 1.Choose and prepare a powerup
動画を観る
- Hierarchy ビューの
[Course Library] - [Picups]
フォルダーのGem_01
プレファブを Scene ビューにドラッグ&ドロップする- Hierarchy ビューの
Gem_01
をPowerup
にリネームする
- Hierarchy ビューの
-
Powerup
タグ作成 - Scene ビューの
Powerup
ゲームオブジェクトを、 Project ビューのPrefabs
フォルダーへドラッグ&ドロップする
Step [O6o10o3o3o0] 2.Destroy powerup on collision
動画を観る
- プレイヤーがパワーアップに衝突したら、パワーアップを消す
-
PlayerController
C#スクリプトのOnTriggerEnter()
メソッド作成 -
hasPowerup
フラグ作成
-
Step [O6o10o3o4o0] 3.Test for enemy and powerup
動画を観る
- パワーアップ状態で敵に当たってみて衝突判定をテストする
-
Enemy
ゲームオブジェクトにEnemy
タグを付ける -
PlayerController
C#スクリプトにOnCollisionEnter()
メソッド追加
-
OnTriggerEnter は、 Box Collider の当たり判定に接触したとき?
OnCollisitionEnter は、 図形に衝突したときか?
Step [O6o10o3o5o0] 4.Apply extra knockback with powerup
動画を観る
- パワーアップしているときに敵に接触すると、敵が飛んでいく(ノックバック)ようにしたい
- ベクトル計算で、方向は算出できる。それを力として大きくして、加えるだけ
Step [O6o10o3o6o0] 5.Create Countdown Routine for powerup
動画を観る
- パワーアップは永遠に続く。そこで、パワーアップが時間経過で切れる仕組みを作る
- コルーチンの書き方を覚える
Step [O6o10o3o7o0] 6.Add a powerup indicator
動画を観る
- パワーアップ状態が切れたことがユーザーには分からない。そこで、パワーアップ状態が切れたことを分かるようにする
- active フラグの説明
-
+ new Vector3(...)
という書き方
📺 やってみた
Step [O6o10o3o8o0] 7.Lesson Recap
動画を観るだけ
📅 2022-12-11 sun 20:50
Step [O6o10o4o0] Lesson 4.3 - Lesson 4.4 - For-Loops For Waves
📅 2022-12-14 wed 18:40
-
Lesson 4.4 - For-Loops For Waves
- Tutorial, Begginer, 5o Mins -
敵を複数生成しよう、という話し
Step [O6o10o4o1o0] Overview Video
動画を観るだけ
-
Forループ
の前振り
Step [O6o10o4o2o0] 1.Write a for-loop to spawn 3 enemies
動画を観る
-
Forループ
の説明
Step [O6o10o4o3o0] 2.Give the for-loop a parameter
動画を観る
-
関数の引数
の説明
Step [O6o10o4o4o0] 3.Destroy enemies if they fall off
動画を観る
- 落ちた敵を破壊する
-
FindObjectsOfType<T>
メソッドの説明
Step [O6o10o4o5o0] 4.Increase enemyCount with waves
動画を観る
- 徐々に敵の数を増やす
Step [O6o10o4o6o0] 5.Spawn Powerups with new waves
動画を観る
- パワーアップアイテムも出す
📺 やってみた
Step [O6o10o4o7o0] 6.Lesson Recap
動画を観るだけ
📅 2022-12-14 wed 20:04
Step [O6o10o5o0] Challenge 4 - Soccer Scripting
-
Challenge 4 - Soccer Scripting
- Tutorial, Begginer, 1 Hour
概要読むだけ
- 不具合があるプロジェクトを直すという話し
Step [O6o10o5o1o0] 1.Overview
動画を観るだけ
-
Challenge 4 starter files
を準備する- Lesson 4 の material が外れるなどの不具合が起こったが直した
Step [O6o10o5o2o0] 2.Warning
この章の説明を読むだけ
- 以下のステップを続けて読んでいく
Step [O6o10o5o3o0] 3.Hitting an enemy sends it back towards you
📅 2022-12-15 wed 20:07
-
敵を攻撃すると、敵がわたしに向かって送り返されてくる。これは不具合なので、敵をわたしから遠ざけるようにしてほしい という課題
- ベクトルの正負が逆なのでは?
-
しかしプレイすると
NullReferenceException
が出て動かない
EnemyX.cs:
private GameObject playerGoal;
👆 このフィールドがヌルなのでは? 入れてみる
void Start()
{
// ...
playerGoal = GameObject.Find("Player Goal");
}
👆 NullReferenceException
はこれで直った
PlyaerControllerX.cs:
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.CompareTag("Enemy")) { // ...
// Vector3 awayFromPlayer = transform.position - other.gameObject.transform.position;
Vector3 awayFromPlayer = other.gameObject.transform.position - transform.position;
// ...
}
}
👆 これで直った
Step [O6o10o5o4o0] A new wave spawns when the player gets a powerup
- プレイヤーがパワーアップを取ると、敵の波が生成される。これは不具合なので、敵を全て破壊したときに、敵の波を生成してほしい という課題
- パワーアップ・アイテムと衝突したときに、敵を生成する関数を呼び出しているのではないか?もしそうなら、それを削除すればどうか?
- そのようなコードは見当たらない
- じゃあ、パワーアップ・アイテムが全部破壊されると 敵を生成するように書いているのでは?
- パワーアップ・アイテムと衝突したときに、敵を生成する関数を呼び出しているのではないか?もしそうなら、それを削除すればどうか?
SpawnManager.cs:
void Update()
{
enemyCount = FindObjectsOfType<Enemy>().Length;
if (enemyCount == 0)
{
waveNumber++;
SpawnEnemyWave(waveNumber);
Instantiate(powerupPrefab, GenerateSpawnPosition(), powerupPrefab.transform.rotation);
}
}
👆 一見すると、敵の数を数えているように見える
敵には Enemy
タグが、 アイテムには Powerup
タグが付いている。これも正しいように見える
SpawnManagerX.cs:
void Update()
{
enemyCount = GameObject.FindGameObjectsWithTag("Powerup").Length;
if (enemyCount == 0)
{
SpawnEnemyWave(waveCount);
}
}
👆 見ているスクリプトが違ったので見直すと タグが間違っているので修正する。これで直った
Step [O6o10o5o5o0] 5.The powerup never goes away
- パワーアップ期間が切れない。これは不具合なので、一定時間経過すると消えるように直してほしい
- コルーチンが動いていれば消えるはず。どうなっているか確認する
-
IEnumerator PowerupCooldown()
の呼出し箇所が 0 箇所だ
-
- コルーチンが動いていれば消えるはず。どうなっているか確認する
PlayerControllerX.cs:
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Powerup"))
{ // ...
// 追加
StartCoroutine(PowerupCooldown());
}
}
👆 過去のコードを参考に追加する。これで直った
Step [O6o10o5o6o0] 6.2 enemies are spawned in every wave
- どの波でも敵が2つ増える。これを、1回目の波では1、2回目の波では2、3回目の波では3,というようにしてほしい という課題
-
SpawnEnemyWave()
の呼出し箇所を調べてみる。waveCount
分、増えるようだ-
waveCount
の使用箇所を調べてみる
-
-
SpawnManagerX:
void SpawnEnemyWave(int enemiesToSpawn)
{// ...
// Spawn number of enemy balls based on wave number
for (int i = 0; i < 2; i++)
{
Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
} // ...
}
👆 途中、上記のような箇所を見つけた。 ハードコーディングの 2
を waveCount
に変えてみる。多分直った
Step [O6o10o5o7o0] 7.The enemy balls are not moving anywhere
- 敵は動かない。これは不具合なので、プレイヤー側のゴールを目指して動いてほしい
- 敵から見てプレイヤー側のゴールの向きを、それを力の向きと捉えて、その力の向きを小さくして、毎フレーム、敵に与えればいいのでは
EnemyX:
void Update()
{
// Set enemy direction towards player goal and move there
Vector3 lookDirection = (playerGoal.transform.position - transform.position).normalized;
enemyRb.AddForce(lookDirection * speed * Time.deltaTime);
}
👆 それっぽいコードはもう書いてある。だったら、speed が0なのでは? ビンゴ。 Enemy
プレファブの持つ EnemyX
C#スクリプトの Speed
フィールドに 30
ぐらい入れる。直った
Step [O6o10o5o8o0] 8.Bonus: The player needs a turbo boost
- スペースバーを押している間中、プレイヤーは速くなりたい。そしてブーストしている間、パーティクル効果を付けてほしい
-
PlayerControllerX
C#スクリプトのUpdate
メソッドの中で スペース・キーの押下判定をして、Speed
の2倍ぐらい 力を余分に加えればいいか? - パーティクルは、シーンビューで
Player
ゲームオブジェクトの子として加えて、setActive()
でオン/オフを切り替えればいいか?
-
PlayerControllerX.cs:
void Update()
{ // ...
// Turbo boost
if (Input.GetKey(KeyCode.Space))
{
Debug.Log("Boost!");
var turbo = 3;
playerRb.AddForce(focalPoint.transform.forward * turbo * speed * Time.deltaTime);
}
// ...
}
👆 これで向いている方向に力が加わっていると思うが、実感はない。Input.GetKeyDown()
は押下にしか反応しないので、 Input.GetKey()
を使えば押しっぱなしを検知できる
-
Smoke_Particle
という素材が入っていたので、Player
ゲームオブジェクトの子として置く。Player
の子にすると、回転してしまう。焦点カメラ
の子にする-
Play On Awake
のチェックは外しておく-
Prototype 3
の土煙を参考にする
-
-
public ParticleSystem dirtParticle;
dirtParticle.Play(); // 土煙
dirtParticle.Stop();
👆 上記のコードをうまく使えばいいはず
-
Play()
メソッドを使っても、パーティクルの動画再生が始まらない-
Project
ビューにあるパーティクルではなく、Scene
ビューにあるパーティクルをPlayerControllerX
C#スクリプトにアタッチすると、再生された
-
PlayerControllerX.cs:
// Turbo boost
public ParticleSystem smokeParticle;
public float spamSmokeSecs = 3.0f;
public float spamSmokeSecsCountdown;
void Update()
{ // ...
// Turbo boost
if (Input.GetKey(KeyCode.Space))
{
Debug.Log("Boost!");
var turbo = 3;
playerRb.AddForce(focalPoint.transform.forward * turbo * speed * Time.deltaTime);
if (spamSmokeSecsCountdown < 0.5f)
{
smokeParticle.Play();
spamSmokeSecsCountdown = spamSmokeSecs;
}
}
// Turbo boost
spamSmokeSecsCountdown -= Time.deltaTime;
// ...
}
👆 これで OK
📅 2022-12-15 thu 22:04
Step [O6o10o5o9o0] 9.Bonus: The enemies never get more difficult
-
敵の速度は増えません。そこで、新しい波ごとに増えるようにして、ゲームを難しくしてください
- 敵の数が増えるだけでも難しいが……
-
敵の速度は
Enemy
C#スクリプトのSpeed
変数に設定されている。さっき自分で設定したやつだ-
SpawnManagerX
C#スクリプトのSpawnEnemyWave
メソッドで、敵の速度を設定すればいいような気がする
-
SpawnManagerX.cs:
void SpawnEnemyWave(int enemiesToSpawn)
{ // ...
for (int i = 0; i < waveCount; i++)
{
var enemyGo = Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
var enemyScript = enemyGo.GetComponent<EnemyX>();
enemyScript.speed *= waveCount;
}
// ...
}
👆 簡単にやるなら、こう?
📅 2022-12-15 thu 22:29
Step [O6o10o6o0] Lab 4 - Basic Gameplay
-
Lab 4 - Basic Gameplay
- Tutorial, Begginer, 1 Hour 30 Mins
📅 2022-12-17 sat 13:20
概要読むだけ
- 復習なので退屈な章。次のクイズの章のためにやる感じか
Step [O6o10o6o1o0] Overview Video
動画を観るだけ
Step [O6o10o6o2o0] 1.Give objects basic movement
動画を観る
-
現在、球だけを上下左右キーで動かすことができ、それ以外の図形は動かない状態だ。そこで、敵オブジェクトを動かす方法の基本を説明する
-
非プレイヤーオブジェクトを Hierarchy ビューでまとめて選択し、
Rigidbody
コンポーネントをアタッチする -
MoveDown
C#スクリプトを作成- 非プレイヤーオブジェクトを Hierarchy ビューでまとめて選択し、
MoveDown
C#スクリプトを まとめてアタッチする
- 非プレイヤーオブジェクトを Hierarchy ビューでまとめて選択し、
MoveDown.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveDown : MonoBehaviour
{
public float speed = 5.0f;
private Rigidbody objectRb;
// Start is called before the first frame update
void Start()
{
objectRb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
objectRb.AddForce(Vector3.forward * -speed);
}
}
Step [O6o10o6o3o0] 2.Destroy objects off-screen
動画を観る
-
現在、画面外に出たオブジェクトはずっと残っている。これを、画面外に出たオブジェクトを破壊するようにしたい
-
z 座標が -10 より下がったら破壊する、という発想
MoveDown.cs
private float zDestroy = -10.0f;
void Update()
{ // ...
if (transform.position.z < zDestroy)
{
Destroy(gameObject);
}
}
Step [O6o10o6o4o0] 3.Handle object collisions
動画を観る
-
Powerup
ゲームオブジェクトのCapsule Collider
のIs Trigger
チェックボックスにチェックを付け忘れていたので、チェックしておく(ぶつからず、通過するようになる) -
Phisycs Materials
フォルダー作成-
Bouncy
物理素材作成-
Bounciness
を1
に変更 -
Bounce Combine
をMultiply
に変更
-
-
Bouncy
物理素材を、Player
ゲームオブジェクトのSphere Collider
コンポーネントへアタッチ(Bouncy
物理素材を、Player
ゲームオブジェクトへドラッグ&ドロップすればよい)
-
-
Enemy
タグ作成 -
Powerup
タグ作成 -
Player, Enemy, Powerup ゲームオブジェクトへ、それぞれ Player, Enemy Powerup タグを設定
-
PlayerController
C#スクリプトへ、OnCollisionEnter()
メソッド作成 -
PlayerController
C#スクリプトへ、OnTriggerEnter()
メソッド作成
PlayerController.cs:
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
Debug.Log("Player has collided with enemy.");
}
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Powerup"))
{
Destroy(other.gameObject);
}
}
Step [O6o10o6o5o0] 4.Make objects into prefabs
動画を観る
-
ゲームプレイ中にインスタンス化するには、プレファブにしておく必要があるという説明
-
Project ビューに、
Prefabs
フォルダー作成-
Enemy 1
やPowerup
ゲームオブジェクトをPrefabs
フォルダーへドラッグ&ドロップ - Scene ビューの
Enemy 1
やPowerup
ゲームオブジェクトは削除
-
Step [O6o10o6o6o0] 5.Make SpawnManager spawn Prefabs
動画を観る
11分もある長い動画
-
SpawnManager
ゲームオブジェクト作成 -
SpawnManager
C#スクリプト作成。SpawnManager
ゲームオブジェクトへアタッチ
SpawnManager.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnManager : MonoBehaviour
{
public GameObject[] enemies;
public GameObject powerup;
private float zEnemySpawn = 12.0f;
private float xSpawnRange = 16.0f;
private float zPowerupRange = 5.0f;
private float ySpawn = 0.75f;
private float powerupSpawnTime = 5.0f;
private float enemySpawnTime = 1.0f;
private float startDelay = 1.0f;
// Start is called before the first frame update
void Start()
{
InvokeRepeating("SpawnRandomEnemy", startDelay, enemySpawnTime);
InvokeRepeating("SpawnPowerup", startDelay, powerupSpawnTime);
}
// Update is called once per frame
void Update()
{
}
void SpawnRandomEnemy()
{
float randomX = Random.Range(-xSpawnRange, xSpawnRange);
int randomIndex = Random.Range(0, enemies.Length);
Vector3 spawnPos = new Vector3(randomX, ySpawn, zEnemySpawn);
Instantiate(enemies[randomIndex], spawnPos, enemies[randomIndex].gameObject.transform.rotation);
}
void SpawnPowerup()
{
float randomX = Random.Range(-xSpawnRange, xSpawnRange);
float randomZ = Random.Range(-zPowerupRange, zPowerupRange);
Vector3 spawnPos = new Vector3(randomX, ySpawn, randomZ);
Instantiate(powerup, spawnPos, powerup.gameObject.transform.rotation);
}
}
Step [O6o10o7o0] 6.Recap
動画を観るだけ
📅 2022-12-17 sat 16:57
📺 やってみた
Step [O6o10o8o0] Quiz 4
-
Quiz 4
- Quiz, Begginer, 15 Mins
概要は読まなくてもいいや
📅 2022-12-17 sat 17:22
Step [O6o10o9o0] Bonus Features 4 - Share your Work
-
Bonus Features 4 - Share your Work
- Tutorial, Begginer, 1 Hour
概要読むだけ
- 簡単な問題から、難しい問題まで出てくるやつ
Step [O6o10o9o1o0] 1.Overview
動画を観る
- 完成例の動画
Step [O6o10o9o2o0] 2.Easy: Harder enemy
📅 2022-12-18 sun 10:46
動画を観る
-
敵の種類を増やして、ランダムに生成してほしい という話し
- サンプル動画からは 意図がよく分からないが……
-
Materials
フォルダーを作って、 Material を作るか -
SpawnManager
C#スクリプトのenemyPrefab
フィールドを配列にすればどうか?- インデックスは乱数にする
SpawnManager.cs:
public GameObject[] enemyPrefabs;
void SpawnEnemyWave(int enemiesToSpawn)
{
for (int i = 0; i < enemiesToSpawn; i++)
{
int randomIndex = Random.Range(0, enemyPrefabs.Length);
Debug.Log($"randomIndex:{randomIndex}");
GameObject enemyPrefab = enemyPrefabs[randomIndex];
Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
}
}
- 敵毎に強さを設定するのは
Rigidbody
コンポーネントのMass
フィールドをいじる(1 mass = 1 Killo-gram)-
Scale
をいじっても 大きさを変更できる
-
Step [O6o10o9o3o0] 3.Medium: Homing rockets
動画を観る
-
ホーミング・ロケットを発射できるパワーアップアイテムを追加してほしい という話し
- 要件:非パワーアップ時は ワンウェイ、パワーアップ時は全ての敵に向けて発射してほしい
-
SpawnManager
C#スクリプトのpowerupPrefab
フィールドを配列にすればどうか?- 通常と、ホーミングの違いを見分けるには?
SpawnManager.cs:
public GameObject[] powerupPrefabs;
void SpawnPowerup()
{
int randomIndex = Random.Range(0, powerupPrefabs.Length);
GameObject powerupPrefab = powerupPrefabs[randomIndex];
Instantiate(powerupPrefab, GenerateSpawnPosition(), powerupPrefab.transform.rotation);
}
PlayerController.cs:
public int powerupType;
void Update()
{ // ...
if (hasPowerup && powerupType == 2 && Input.GetKey(KeyCode.Space))
{
Debug.Log("TODO ここで球を発射したい");
}
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Powerup"))
{
if (other.name.StartsWith("Powerup 2")) // 実際は "Powerup 2(Clone)" になっている
{
Debug.Log("パワーアップ2型");
powerupType = 2;
}
else
{
Debug.Log("パワーアップ1型");
powerupType = 1;
} // ...
}
}
👆 パワーアイテムは、名前で区別できるだろう
- 球の発射は、前にピザを飛ばしたチュートリアルを参考にする
- 球の図形は、カプセルを寝かせれば作れるか。名前は
Bullet
にする -
Rigidbody
のMass
を大きくすれば、相手は吹っ飛ぶだろう - 水平に飛んでいってほしいので、
Use Gravity
は外す - 水平回転以外の回転を止めたいので
Freeze
でx
とz
をフリーズ
- 球の図形は、カプセルを寝かせれば作れるか。名前は
- 発射口というゲームオブジェクトを作ってしまうのが好手らしい
-
Player
から見て Z=1 の位置にCube
図形を置く。名前はLauncher
とかにしておく
-
-
LauncherController
C#スクリプトを作って、Launcher
ゲームオブジェクトへアタッチ
LauncherController.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 発射口のコントローラー
/// </summary>
public class LauncherController : MonoBehaviour
{
public GameObject bulletPrefab;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (
// hasPowerup && powerupType == 2 &&
Input.GetKey(KeyCode.Space))
{
// Debug.Log("TODO ここで球を発射したい");
SpawnBullet();
}
}
void SpawnBullet()
{
Instantiate(bulletPrefab, transform.position, transform.rotation);
}
}
👆 これだと、ジャムって噴水みたいに暴発する。スパムを止める必要がある
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 発射口のコントローラー
/// </summary>
public class LauncherController : MonoBehaviour
{
public GameObject bulletPrefab;
public float spamCountdownSecs;
public float spamSecs = 0.5f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
spamCountdownSecs -= Time.deltaTime;
if (
// hasPowerup && powerupType == 2 &&
Input.GetKey(KeyCode.Space) && spamCountdownSecs < 0.0f)
{
// Debug.Log("TODO ここで球を発射したい");
SpawnBullet();
spamCountdownSecs = spamSecs;
}
}
void SpawnBullet()
{
Instantiate(bulletPrefab, transform.position, transform.rotation);
}
}
👆 スパムは止まる
-
HomingBullet
C#スクリプトを作り、Bullet
ゲームオブジェクトへアタッチ-
HomingBullet
C#スクリプトにspeed
,targetPrefab
フィールド作成
-
HomingBullet.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HomingBullet : MonoBehaviour
{
public float speed = 100.0f;
private Rigidbody myRb;
public GameObject targetPrefab;
// Start is called before the first frame update
void Start()
{
myRb = GetComponent<Rigidbody>();
}
// Update is called once per frame
void Update()
{
if (targetPrefab == null)
{
return;
}
Vector3 lookDirection = (targetPrefab.transform.position - transform.position).normalized;
myRb.AddForce(lookDirection * speed);
// 盤から落ちてたら破壊
if (transform.position.y < -10)
{
Destroy(gameObject);
}
}
}
- シーン上のすべての敵のポジションを知りたい
enemyCount = GameObject.FindGameObjectsWithTag("Powerup").Length;
👆 前のチュートリアルのこれが使えるのでは?
LauncherController.cs:
void SpawnBullet()
{
// シーンの敵のポジションを知りたい
GameObject[] enemiesGo = GameObject.FindGameObjectsWithTag("Enemy");
foreach(var enemyGo in enemiesGo)
{
GameObject homingBulletGo = Instantiate(homingBulletPrefab, transform.position, transform.rotation);
HomingBullet homingBulletScript = homingBulletGo.GetComponent<HomingBullet>();
homingBulletScript.targetPrefab = enemyGo;
Vector3 lookDirection = (enemyGo.transform.position - homingBulletGo.transform.position).normalized;
homingBulletGo.GetComponent<Rigidbody>().AddForce(lookDirection * Time.deltaTime * homingBulletScript.speed);
}
}
👆 基本的な考え方はこう
📺 やってみた
📅 2022-12-18 sun 14:33
Step [O6o10o9o4o0] 4.Hard: Smash attack
動画を観る
-
ジャンプして着地の衝撃で敵を遠ざけてほしい。近くの敵の方が衝撃が大きいはず という課題
-
ジャンプをどう実装するか?
AddForce()
でなんとかなるのか? -
Unity Learn Webサイトのコメントを参考にする
- 難しいので部品を分ける
-
SmashAttack
というゲームオブジェクト作成 -
SmashAttack
C#スクリプトを作り、SmashAttack
ゲームオブジェクトへアタッチ
-
- 難しいので部品を分ける
SmashAttack.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmashAttack : MonoBehaviour
{
public GameObject playerPrefab;
public float smashMultiplier = 10f;
public float forceRadius = 100f;
public float jumpForce = 500f;
public float waitForSeconds = 3.0f;
public float spamCountdownSecs;
public float spamSecs = 0.5f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
spamCountdownSecs -= Time.deltaTime;
if (Input.GetKeyDown(KeyCode.S) && spamCountdownSecs < 0.0f)
{
StartCoroutine(Smash());
spamCountdownSecs = spamSecs;
}
}
/// <summary>
/// コルーチン
/// </summary>
/// <returns></returns>
IEnumerator Smash()
{
// すぐジャンプ
playerPrefab.GetComponent<Rigidbody>().AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
// 1.5秒待機
yield return new WaitForSeconds(waitForSeconds);
// シーン上のすべての敵に対して
foreach (var enemy in FindObjectsOfType<Enemy>())
{
// プレイヤーから見た敵の位置
Vector3 awayFromEnemy = enemy.transform.position - playerPrefab.transform.position;
if (awayFromEnemy.magnitude < forceRadius)
{
// 敵に力を加える
enemy.GetComponent<Rigidbody>().AddForce((forceRadius - awayFromEnemy.magnitude) * smashMultiplier * awayFromEnemy, ForceMode.Impulse);
}
}
}
}
👆 重さと 力のパラメーターを丁度よく調整するのが うまくいかない
📺 やってみた
Step [O6o10o9o5o0] 5.Expert: Boss battle
📅 2022-12-18 sun 15:22
-
一定数の波のあと、発射物を発射する敵など、ボスのような敵をプログラムしてほしい という話し
- このゲームは 操作性の悪さから 波を1つクリアするのも難しいので この課題は難しい
-
とりあえず、
Enemy 3
ゲームオブジェクトを追加する。特長は でかい ということにする- 第2派のときに enemyPrefabs[2] が必ず出てくるようにプログラムしてみる
📺 やってみた
📅 2022-12-18 sun 15:45
Step [O6o10o9o6o0] 6.Hints and solution walkthrough
ヒントが書いてあるだけ
Step [O6o11o0] Unit 5 - Introduction
📅 2022-12-18 sun 15:59
-
Unit 5 - Introduction
- Tutorial, Begginer, 5 Min
動画を観るだけ
Step [O6o11o1o0] Lesson 5.1 - Clicky Mouse
Lesson 5.1 - Clicky Mouse
- Tutorial, Begginer, 1 Hour
概要は読まなくていいや
Step [O6o11o1o1o0] Overview Video
動画を観るだけ
- マウスクリックの前振り
Step [O6o11o1o2o0] 1.Create project and switch to 2D view
動画を観る
-
Prototype 5
プロジェクトをいつも通り作る -
2D
ボタンをクリックして、 2D ビューにする
Step [O6o11o1o3o0] 2.Create good and bad targets
動画を観る
-
Good 3つ、 Bad 1つ の射撃の目標のプレファブを作る
-
Rigidbody
,Box Collider
をアタッチ
-
-
Target
C#スクリプトを作る。射撃の目標ゲームオブジェクトへアタッチ -
Prefabs
フォルダーを作って 射撃の目標を移動。 Hiererchy ビューからは削除
Step [O6o11o1o4o0] 3.Toss objects randomly in the air
動画を観る
- 射撃の目標を 空中に放り投げるという話し
- トルク とは、ねじること
-
AddTorque()
メソッドの説明
-
Step [O6o11o1o5o0] 4.Replace messy code with new methods
動画を観る
- コードを読みやすくするという話し
- ヘルパーメソッドを作る
Step [O6o11o1o6o0] 5.Create object list in Game Manager
動画を観る
-
Game Manager
ゲームオブジェクト作成-
GameManager
C#スクリプトを作成する。アイコンは特別に、歯車になる。設定ファイルとしてよく使うので -
Game Manager
ゲームオブジェクトへGameManager
C#スクリプトをアタッチ
-
-
List<>
の説明
Step [O6o11o1o7o0] 6.Create a coroutine to spawn objects
動画を観る
- 射撃の目標の生成のタイミング
- コルーチンを使う
-
while
ループの説明
Step [O6o11o1o8o0] 7.Destroy target with click and sensor
動画を観る
-
OnMouseDown()
の説明-
Collider Box
のIs Trigger
がチェックされていると効く?
-
-
OnTriggerEnter()
の説明- シーンの底に
Sensor
ゲームオブジェクトが最初から置かれてあって、そこに衝突したら破壊する
- シーンの底に
-
ySpawn
を -2 へ変更
Step [O6o11o1o9o0] 8.Lesson Recap
動画を観るだけ
📅 2022-12-18 sun 18:17
Step [O6o11o2o0] Lesson 5.2 - Keeping Score
📅 2022-12-18 sun 18:24
-
Lesson 5.2 - Keeping Score
- Tutorial, Begginer, 1 Hour 10 Mins
概要読むだけ
- スコアを表示するのだろうか?
Step [O6o11o2o1o0] Overview Video
動画を観るだけ
Step [O6o11o2o2o0] 1.Add Score text position it on screen
動画を観る
-
TextMeshPro
の説明 -
Hierarchy ビューから、
[Create] - [UI] - [TextMeshPro - Text]
をクリック- 初めて TextMeshPro を使うなら、
Inport TMP Essentials
ボタンをクリック-
Canvas
というゲームオブジェクトが自動で作られる。その下にTextMeshPro -Text
が置かれる
-
- 初めて TextMeshPro を使うなら、
-
Anchor
の使い方
Step [O6o11o2o3o0] 2.Edit the Score Text’s properties
動画を観る
- 見栄えの良いテキストになるようにプロパティを設定する話し
-
UGUI
は ユーグイと読む
Step [O6o11o2o4o0] 3.Initialize score text and variable
動画を観る
- テキスト表示
-
using
文の説明using TMPro;
-
.text
フィールド
GameManager.cs:
public TextMeshProUGUI scoreText;
void Start()
{ // ...
score = 0;
scoreText.text = "Score: " + score;
}
Step [O6o11o2o5o0] 4.Create a new UpdateScore method
動画を観る
- スコア表示を更新されるようにする
Step [O6o11o2o6o0] 5.Add score when targets are destroyed
動画を観る
- 射撃の目標を破壊したときにスコアを更新したいという話し
Target.cs:
private GameManager gameManager;
void Start()
{ // ...
gameManager = GameObject.Find("Game Manager").GetComponent<GameManager>();
}
private void OnMouseDown()
{ // ...
gameManager.UpdateScore(5);
}
Step [O6o11o2o7o0] 6.Assign a point value to each target
動画を観る
- 射撃の目標ごとに、スコアを変えたいという話し
Step [O6o11o2o8o0] 7.Add a Particle explosion
動画を観る
- 射撃の目標は、クリックしたら爆発してほしい、という話し
Target.cs:
public ParticleSystem explosionParticle;
private void OnMouseDown()
{ // ...
Instantiate(explosionParticle, transform.position, explosionParticle.transform.rotation);
//...
}
Step [O6o11o2o9o0] 8.Lesson Recap
📅 2022-12-18 sun 21:22
動画を観るだけ
📺 やってみた
Step [O6o11o3o0] Lesson 5.3 - Game Over
📅 2022-12-18 sun 21:28
-
Lesson 5.3 - Game Over
- Tutorial, Begginer, 1 Hour 10 Mins
概要読むだけ
Step [O6o11o3o1o0] Overview Video
📅 2022-12-19 sun 18:47
動画を観るだけ
-
EventListener
の前振り
Step [O6o11o3o2o0] 1.Create a Game Over text object
動画を観る
- テキストの配置の基本操作の説明
Step [O6o11o3o3o0] 2.Make GameOver text appear
動画を観る
- テキストの表示/非表示についての話し
-
gameObject.SetActive(true)
使用
Step [O6o11o3o4o0] 3.Create GameOver function
動画を観る
- 良いオブジェクトが、画面下のラインに当たった時に Game Over を表示するようにしてほしい、という話し
-
Bad
タグ作成
Step [O6o11o3o5o0] 4.Stop spawning and score on GameOver
動画を観る
- オブジェクトの生成と スコアの更新を止める
-
isGameActive
フラグ
Step [O6o11o3o6o0] 5.Add a Restart button
動画を観る
- ボタン作成の話し
-
Button
ではなく、Button - TextMeshPro
の方を使う
Step [O6o11o3o7o0] 6.Make the restart button work
動画を観る
- リスタートボタンを働かせるという話し
- `using UnityEngine.SceneManagement;
-
SceneManager.LoadScene(SceneManager.GetActiveScene().name)
使用-
Restart Button
ゲームオブジェクトの Inspector ビュー のOn Click
イベントの使い方
-
-
Step [O6o11o3o8o0] 7.Show restart button on game over
動画を観る
- ゲームがアクティブな間は リスタートボタンをオフにしてほしいという話し
-
using UnityEngine.UI
使用
Step [O6o11o3o9o0] 8.Lesson Recap
動画を観るだけ
📅 2022-12-19 mon 20:50
📺 やってみた
Step [O6o11o4o0] Lesson 5.4 - What’s the Difficulty?
📅 2022-12-20 sun 20:02
-
Lesson 5.4 - What’s the Difficulty?
- Tutorial, Begginer, 1 Hour
概要読むだけ
Step [O6o11o4o1o0] Overview Video
動画を観るだけ
Step [O6o11o4o2o0] 1.Create Title text and menu buttons
動画を観る
- タイトル、3つのボタンの置き方の説明
Step [O6o11o4o3o0] 2.Add a DifficultyButton script
動画を観る
- 難易度ボタンを働かせる準備
-
DifficultyButton
C#スクリプト作成、3つのボタンへアタッチ
Step [O6o11o4o4o0] 3.Call SetDifficulty on button click
動画を観る
- ボタンに働きを持たせる前振り
-
button.onClick.AddListener(メソッド名)
使用 - デバッグ方法の説明
Step [O6o11o4o5o0] 4.Make your buttons start the game
動画を観る
- ボタン押下でゲーム開始する話し
Step [O6o11o4o6o0] 5.Deactivate Title Screen on StartGame
動画を観る
- タイトルを非表示にする話し
Step [O6o11o4o7o0] 6.Use a parameter to change difficulty
動画を観る
- ゲームの難しさを変える話し
-
Maximize On Play
ボタン(Play Maximized
ボタン)の説明
📺 やってみた
Step [O6o11o4o8o0] 7.Lesson Recap
動画を観るだけ
📅 2022-12-20 mon 22:14
Step [O6o11o5o0] Challenge 5 - Whack-a-Food
📅 2022-12-21 mon 18:58
-
Challenge 5 - Whack-a-Food
- Tutorial, Begginer, 1 Hour
概要は読まなくてもいいかも
- バグを直そう、という課題
Step [O6o11o5o1o0] 1.Overview
動画を観る
-
Challenge 5
の準備をする
Step [O6o11o5o2o0] 2.Warning
読むだけ
Step [O6o11o5o3o0] 3.The difficulty buttons look messy
- ボタンのテキストがずれているので、水平方向、垂直方向ともにボタンのセンターに揃えてほしい という話し
- テキストの寄せボタンをクリックして解決
Step [O6o11o5o4o0] 4.The food is being destroyed too soon
-
現状、マウスが近づいたら食品が破棄されてしまう。これを、マウスでクリックしたときに破棄するようにしてほしい という話し
-
MonoBehaviour
のメソッドを見てみるか-
TargetX
C#スクリプトにOnMouseEnter()
メソッドがあるので、OnMouseDown()
メソッドにリネームする
-
Step [O6o11o5o5o0] 5.The Score is being replaced by the word “score”
- 現状、
score
としか表示されてない。 これを、Score:
に直し、その後ろに点数を表示してほしい という話し
GameManagerX.cs:
public void UpdateScore(int scoreToAdd)
{
score += scoreToAdd;
// scoreText.text = "score";
scoreText.text = "Score: " + score;
}
👆 これで十分そう
Step [O6o11o5o6o0] 6.When you lose, there’s no way to Restart
- リスタートボタンを付けてほしいという話し
GameManagerX.cs:
public void GameOver()
{
gameOverText.gameObject.SetActive(true);
// restartButton.gameObject.SetActive(false);
restartButton.gameObject.SetActive(true);
isGameActive = false;
}
👆 これで十分そう
Step [O6o11o5o7o0] 7.The difficulty buttons don’t change the difficulty
- 難易度を変えるボタンがいつもハードなので、イージーならゲームスピードが遅く、ハードなら速くなるようにしてほしい という話し
DifficultyButton.cs:
void SetDifficulty()
{
Debug.Log(button.gameObject.name + " was clicked");
// gameManagerX.StartGame();
gameManagerX.StartGame(difficulty);
}
GameManagerX.cs:
// public void StartGame()
public void StartGame(int difficulty)
{
// spawnRate /= 5;
spawnRate /= difficulty;
// ...
}
👆 これで十分そう
Step [O6o11o5o8o0] 8.Bonus: The game can go on forever
-
現状、ゲームが永遠に続いているので、タイマーを 59 から初めて、 0 になったらゲームオーバーになるようにしてほしい という話し
-
なんの用意もされていないので、一から作れということらしい
- ヒントを見ると
Unity Count down timer C#
でググれとある-
Update()
メソッドの中でTime.deltaTime
を減算していけばいいということらしい-
Mathf.Round()
メソッドで小数点を四捨五入できるらしい
-
-
- ヒントを見ると
GameManagerX.cs:
public TextMeshProUGUI timerText;
private float timeLeftSecs = 60;
private void Update()
{
if (isGameActive)
{
timeLeftSecs -= Time.deltaTime;
if (timeLeftSecs < 0)
{
GameOver();
}
else
{
timerText.text = "Timer: " + Mathf.Round(timeLeftSecs);
}
}
}
👆 これで十分そう
📺 やってみた
📅 2022-12-21 mon 20:07
Step [O6o11o6o0] Lab 5 - Swap out your Assets
-
Lab 5 - Swap out your Assets
- Tutorial, Begginer, 1 Hour 30 Mins
📅 2022-12-24 sun 11:22
概要は読まなくてもいいかも
- 退屈なプリミティブな図形を、豪華なアセットに置き換えよう、という話し
Step [O6o11o6o1o0] Overview Video
動画を観るだけ
Step [O6o11o6o2o0] 1.Import and browse the asset library
動画を観る
-
アセット・ライブラリのインポートの話し
-
Create with Code - Course Library.zip
をダウンロードする -
コースライブラリーをインポートする
Step [O6o11o6o3o0] 2.Replace player with new asset
動画を観る
- プリミティブなジオメトリーを、 アセットへ置き換えるという話し
- Hirarchy ビューで、
Player
ゲームオブジェクトを Project ビューのPrefabs
フォルダーへドラッグ&ドロップし、 プレファブ化する- Project ビューの
Player
プレファブをダブルクリックする-
Player
プレファブの子要素として コースライブラリーのフォルダーから、動物のプレファブ をドラッグ&ドロップする- 球に付いていた メッシュや、コライダーの Active のチェックを外す
- 動物に コライダーを付ける
-
- Project ビューの
- Hirarchy ビューで、
Step [O6o11o6o4o0] 3.Browse the Asset store
動画を観る
- Unity Asset Store の紹介
- Pricing で
Free Asets
をチェックする(無料) - Publisher で
Synty Studios
を検索(チュートリアルのオススメ) -
Low Poly
にすると、電池の消費が少ないなど、ゲーム用に向く -
[Add to My Assets]
ボタンをクリック-
[Open in Unity]
ボタンをクリック-
Package Manager
画面が出てくる。色んな商品が並んでいるので、 Webサイトで選んだ商品を探す -
[Download]
ボタンをクリック -
[Import]
ボタンをクリック
-
-
- Pricing で
フォルダーを作って、その下に置くといい
📂 Assets
└── 📂 Asset Store
└── 📂 (ダウンロードしたアセット)
Step [O6o11o6o5o0] 4.Replace all non-player primitives
動画を観る
📺 やってみた
Step [O6o11o6o6o0] 5.Replace the background texture
動画を観る
- テクスチャーの質感を上げる説明
Step [O6o11o6o7o0] 6.Recap
動画を観る
📅 2022-12-24 sun 14:17
Step [O6o11o7o0] Quiz 5
-
Quiz 5
- Quiz, Begginer, 15 Mins
📅 2022-12-24 sun 14:38
Step [O6o11o8o0] Bonus Features 5 - Share your Work
-
Bonus Features 5 - Share your Work
- Tutorial, Begginer, 1 Hour
概要読むだけ
Step [O6o11o8o1o0] 1.Overview
動画を観るだけ
Step [O6o11o8o2o0] 2.Easy: Lives UI
動画を観る
-
失敗を3つまでしてもゲームオーバーにならない、という
Lives:
というカウンターを画面に付けてほしい、という話し -
とりあえず
Score:
を複製して、そのあとのことは そのあと考える -
private int lives = 3;
変数でも増やしてみよ
Target.cs:
private void OnTriggerEnter(Collider other)
{
Destroy(gameObject);
if (!gameObject.CompareTag("Bad"))
{
gameManager.GameOver();
}
}
👆 Target.cs
の方に ゲームオーバーの決定権があるの つらい
せめて gameManager.DecreaseLive()
みたいなメソッドを通したい
GameManager.cs:
void Start()
{
livesText.text = "Lives: " + lives;
}
public void DecreaseLife()
{
if (isGameActive)
{
lives--;
livesText.text = "Lives: " + lives;
if (lives<1)
{
GameOver();
}
}
}
👆 用意する
Target.cs:
// gameManager.GameOver();
gameManager.DecreaseLife();
👆 これでよさげ
Step [O6o11o8o3o0] 3.Medium: Music volume
-
音量を下げるボリュームを付けてほしい、という課題
-
とりあえず スライダー・バーを置いてみる。使い方は そのあと考える
-
とりあえず BGM を付ける、しかし BGM なんか どこにある?
- プロトタイプ3 からインポートする。このとき、 📂
Sound
フォルダーだけチェックする - カメラに AudioSource をアタッチして、そこへ サウンドファイルをドラッグ&ドロップする
- スライダーバーと、オーディオソースの紐づけ方が分からん
- スライダーバーは、 Inspector ビューを見ると
OnValueChanged
イベントを持っているようだ
- スライダーバーは、 Inspector ビューを見ると
- プロトタイプ3 からインポートする。このとき、 📂
- とりあえず、
Audio Manager
ゲームオブジェクトと、AudioManager
C#スクリプトを作るか
AudioManager.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AudioManager : MonoBehaviour
{
private AudioSource audioSource;
private Slider volumeSlider;
// Start is called before the first frame update
void Start()
{
audioSource = GameObject.Find("Main Camera").GetComponent<AudioSource>();
volumeSlider = GameObject.Find("Volume Slider").GetComponent<Slider>();
}
// Update is called once per frame
void Update()
{
}
public void UpdateVolume()
{
audioSource.volume = volumeSlider.value;
}
}
Step [O6o11o8o4o0] 4.Hard: Pause menu
動画を観る
-
ボタンを押すと 一時停止と再開を切り替えられるような、ポーズボタンを付けてほしい、という課題
-
物理的に飛んでいる物体を、どうやってポーズするのか?
- ヒントを見ると、
Time.timeScale
を使うらしい
- ヒントを見ると、
GameManager.cs:
private bool isPause;
void Update()
{
// 一時停止/再開 切替
if (isGameActive && Input.GetKeyDown(KeyCode.Space))
{
isPause = !isPause;
if (isPause)
{
Time.timeScale = 0;
} else
{
Time.timeScale = 1;
}
}
}
👆 機能だけなら これでいけるが、 画面への Pause
表示と、 BGM の一時停止が残ってる。 ポーズ中にブロックが崩せるのもよくない
GameManager.cs:
void Update()
{
// 一時停止/再開 切替
if ((isPause || isGameActive) && Input.GetKeyDown(KeyCode.Space))
{
isPause = !isPause;
isGameActive = !isPause;
if (isPause)
{
Time.timeScale = 0;
} else
{
Time.timeScale = 1;
}
}
}
👆 雑に解決すると、こう
AudioManager.cs:
public void Pause()
{
audioSource.Pause();
}
public void Play()
{
audioSource.Play();
}
GameManager.cs:
public TextMeshProUGUI pauseText;
private GameObject directionalLight;
private AudioManager audioManagerScript;
void Start()
{ // ...
directionalLight = GameObject.Find("Directional Light");
}
void Update()
{
if ((isPause || isGameActive) && Input.GetKeyDown(KeyCode.Space))
{ // ...
if (isPause)
{ // ...
directionalLight.SetActive(false);
pauseText.gameObject.SetActive(true);
audioManagerScript.Pause();
} else
{ // ...
directionalLight.SetActive(true);
pauseText.gameObject.SetActive(false);
audioManagerScript.Play();
}
}
}
👆 ポーズ時に画面を暗くする。ポーズテキストを出す。音を一時停止させる。それを解除させる
-
Pause
の文字は、Game Over Text
ゲームオブジェクトを複製して いじって作る- Inspector ビューの
public TextMeshProUGUI pauseText
フィールドへ、Pause Text
ゲーム・オブジェクトを アクティブにして ドラッグ&ドロップするのと、 非アクティブにして ドラッグ&ドロップするのとで アタッチされるのが ゲームオブジェクトなのか、テキストなのかが違うので確認すること
- Inspector ビューの
Step [O6o11o8o5o0] 5.Expert: Click-and-swipe
-
マウスクリックに代えて、マウスドラッグで 対象を破壊できるように変えてほしいという課題
-
ペンみたいな軌跡をどうやって作れるのか分からん。 答えを見て進むことにする
- Unity Learn のコメント欄を見る
-
Good 1
~Good 3
ゲームオブジェクトへ、Good
タグを付ける
-
- Unity Learn のコメント欄を見る
// Author: VladStoyanoff
// Arranged by: Muzudho
// CursorTrail script, attached to Main Camera (creates the trail):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CursorTrail : MonoBehaviour
{
public Color trailColor = new Color(1, 0, 0.38f);
public float distanceFromCamera = 5;
public float startWidth = 0.1f;
public float endWidth = 0f;
public float trailTime = 0.24f;
Transform trailTransform;
Camera thisCamera;
GameObject trailObj;
// Start is called before the first frame update
void Start()
{
thisCamera = GetComponent<Camera>();
// 新規作成
trailObj = new GameObject("Mouse Trail");
trailTransform = trailObj.transform;
TrailRenderer trail = trailObj.AddComponent<TrailRenderer>();
trail.time = -1f;
MoveTrailToCursor(Input.mousePosition);
trail.time = trailTime;
trail.startWidth = startWidth;
trail.endWidth = endWidth;
trail.numCapVertices = 2;
trail.sharedMaterial = new Material(Shader.Find("Unlit/Color"));
trail.sharedMaterial.color = trailColor;
}
// Update is called once per frame
void Update()
{
MoveTrailToCursor(Input.mousePosition);
}
void MoveTrailToCursor(Vector3 screenPosition)
{
// スクリーン座標を、ワールド座標へ変換
trailTransform.position = thisCamera.ScreenToWorldPoint(new Vector3(screenPosition.x, screenPosition.y, distanceFromCamera));
}
public void SetVisibility(bool isVisibility)
{
trailObj.SetActive(isVisibility);
}
}
Targets.cs:
// Author: VladStoyanoff
// Arranged by: Muzudho
// Changes in Targets.cs script on the OnMouseDown() function:
private void OnMouseOver()
{
if (gameManager.isGameActive && Input.GetMouseButton(0))
{
if (gameObject.CompareTag("Good"))
{
Destroy(gameObject);
gameManager.UpdateScore(pointValue);
Instantiate(explosionParticle, transform.position, explosionParticle.transform.rotation);
}
else if (gameObject.CompareTag("Bad"))
{
Destroy(gameObject);
gameManager.DecreaseLife();
Instantiate(explosionParticle, transform.position, explosionParticle.transform.rotation);
}
}
}
GameManager.cs:
// Author: VladStoyanoff
// Arranged by: Muzudho
// Changes in the GameManager.cs script regarding the GameOver() and StartGame() functions:
private CursorTrail cursorTrailScript;
void Start()
{ // ...
cursorTrailScript = GameObject.Find("Main Camera").GetComponent<CursorTrail>();
}
void Update()
{ // ...
if (Input.GetMouseButton(0))
{
cursorTrailScript.SetVisibility(true);
}
else
{
cursorTrailScript.SetVisibility(false);
}
}
public void StartGame(int difficulty)
{ // ...
cursorTrailScript.enabled = true;
}
public void GameOver()
{ // ...
cursorTrailScript.enabled = false;
}
📺 やってみた
Step [O6o11o8o6o0] 6.Hints and solution walkthrough
ヒントが載っている
📅 2022-12-24 sun 18:05
Step [O6o12o0] Next Steps - Introduction
-
Next Steps - Introduction
- Tutorial, Begginer, 5 Mins
概要読むだけ
Step [O6o12o1o0] 1.Next Steps - Introduction
動画を観るだけ
Step [O6o12o2o0] Lesson 6.1 - Project Optimization
-
Lesson 6.1 - Project Optimization
- Tutorial, Begginer, 30 Mins
概要読むだけ
- プロジェクトの改善をするらしい
Step [O6o12o2o1o0] 1.Variable attributes
動画を観る
-
Prototype 1
の復習 -
[SerializeField]
アトリビュートの説明 - アクセス修飾子の説明
Step [O6o12o2o2o0] 2.Unity Event Functions
動画を観る
-
Prototype 1
の復習 -
Secondary Camera
の作成 -
Update()
やStart()
以外の関数の話し-
FixedUpdate()
- 物理的な計算をするものへ -
LateUpdate()
- カメラへ Awake()
-
Step [O6o12o2o3o0] 3.Object Pooling
動画を観る
-
Prototype 2
の復習 - この説明をそのまま実行すると、破壊してしまう。バックアップを取っておくこと
- 上書きせず、差分を調べて 自力でソース読んで マージすること
- インスタンスの生成と破棄より効率的な、プーリングの説明
なんどか修復してやってみたが 壊れた。この節はスキップする
DestroyOutOfBounds.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyOutOfBounds : MonoBehaviour
{
private float topBound = 30;
private float lowerBound = -10;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (transform.position.z > topBound)
{
// Instead of destroying the projectile when it leaves the screen
//Destroy(gameObject);
// Just deactivate it
gameObject.SetActive(false);
}
else if (transform.position.z < lowerBound)
{
Debug.Log("Game Over!");
Destroy(gameObject);
}
}
}
DetectCollisions.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DetectCollisions : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
// Instead of destroying the projectile when it collides with an animal
//Destroy(other.gameObject);
// Just deactivate the food and destroy the animal
other.gameObject.SetActive(false);
Destroy(gameObject);
}
}
ObjectPooler.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPooler : MonoBehaviour
{
public static ObjectPooler SharedInstance;
public List<GameObject> pooledObjects;
public GameObject objectToPool;
public int amountToPool;
void Awake()
{
SharedInstance = this;
}
// Start is called before the first frame update
void Start()
{
// Loop through list of pooled objects,deactivating them and adding them to the list
pooledObjects = new List<GameObject>();
for (int i = 0; i < amountToPool; i++)
{
GameObject obj = (GameObject)Instantiate(objectToPool);
obj.SetActive(false);
pooledObjects.Add(obj);
obj.transform.SetParent(this.transform); // set as children of Spawn Manager
}
}
public GameObject GetPooledObject()
{
// For as many objects as are in the pooledObjects list
for (int i = 0; i < pooledObjects.Count; i++)
{
// if the pooled objects is NOT active, return that object
if (!pooledObjects[i].activeInHierarchy)
{
return pooledObjects[i];
}
}
// otherwise, return null
return null;
}
}
PlayerController.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private float horizontalInput;
private float speed = 20.0f;
private float xRange = 20;
public GameObject projectilePrefab;
// Update is called once per frame
void Update()
{
// Check for left and right bounds
if (transform.position.x < -xRange)
{
transform.position = new Vector3(-xRange, transform.position.y, transform.position.z);
}
if (transform.position.x > xRange)
{
transform.position = new Vector3(xRange, transform.position.y, transform.position.z);
}
// Player movement left to right
horizontalInput = Input.GetAxis("Horizontal");
transform.Translate(Vector3.right * Time.deltaTime * speed * horizontalInput);
if (Input.GetKeyDown(KeyCode.Space))
{
// No longer necessary to Instantiate prefabs
// Instantiate(projectilePrefab, transform.position, projectilePrefab.transform.rotation);
// Get an object object from the pool
GameObject pooledProjectile = ObjectPooler.SharedInstance.GetPooledObject();
if (pooledProjectile != null)
{
pooledProjectile.SetActive(true); // activate it
pooledProjectile.transform.position = transform.position; // position it at player
}
}
}
}
Step [O6o12o2o4o0] 4.Lesson Recap
オブジェクト・プーリングはスキップ
📅 2022-12-24 sun 20:29
Step [O6o12o3o0] Lesson 6.2 - Research and Troubleshooting
-
Lesson 6.2 - Research and Troubleshooting
- Tutorial, Begginer, 1 Hour
Step [O6o12o3o1o0] 1.Make the vehicle use forces
動画を観る
-
スピードメーターを付けよう、という話し
-
加速と減速
-
transform.Translate()
をやめて、playerRb.AddForce()
に変える -
Speed
をやめて、HorsePower
を付ける
-
-
空間の
Global
とLocal
- Googling
Unity add force in local space
-
AddForce()
の代わりにAddRelativeForce()
を使う
-
- Googling
-
Prototype 1
プロジェクトのバックアップを取っておく
Step [O6o12o3o2o0] 2.Prevent car from flipping over
動画を観る(15:50 もある、長い)
- 平行移動から 物理的な移動に変えたので 車がよくひっくり返るようになってしまった。これを ひっくり返らないようにしてほしいという話し
- 車の形に見えるが、車輪が完全な円をしていて、回らなければ つっかえるので 車体はひっくり返る。
Wheel Colliders
の説明 -
Rigidbody.centerOfMass
(重心)を下げる、という説明-
Center of Mass
ゲームオブジェクトを作る
-
- 車の形に見えるが、車輪が完全な円をしていて、回らなければ つっかえるので 車体はひっくり返る。
📺 やってみた
余計 転がるようになったが、レッスンの先に進む
📅 2022-12-24 sun 22:39
Step [O6o12o3o3o0] 3.Add a speedometer display
動画を観る(12:54 もある、長い)
- スピード・メーターは、テキストで実装するようだ
- マグニチュード(キロメートル毎時) から マイル毎時 に変換している?
Step [O6o12o3o4o0] 4.Add an RPM display
動画を観る
- 毎分回転数って何だ。タイヤが1分間に何回回ってるか知りたいらしい
-
剰余の説明
Modulus
,Remainder
Step [O6o12o3o5o0] 5.Prevent driving in mid-air
動画を観る
- 空中で加速できるので、できないようにしてほしい、という話し
- 車輪4つを、1つ1つ接地判定する必要がある
-
foreach
文の説明-
wheel.isGrounded
使用
-
-
Step [O6o12o3o6o0] 6.Lesson Recap
読むだけ
📅 2022-12-24 sun 16:48
Step [O6o12o4o0] Lesson 6.3 - Sharing your Projects
-
Lesson 6.3 - Sharing your Projects
- Tutorial, Begginer, 30 Mins
ビルドして、 WebGL 用にエクスポートする話しらしい
Step [O6o12o4o1o0] 1.Install export Modules
-
Export Module
というものを追加する話し
Step [O6o12o4o2o0] 2.Build your game for Mac or Windows
- 終了方法の分からないゲームだと、終了方法が分からないから注意
📺 やってみた
Step [O6o12o4o3o0] 3.Build your game for WebGL
- 以下のようなエラーが出て動かない
Failed to download file Build/Prototype1_webgl.data.gz. Loading web pages via a file:// URL without a web server is not supported by this browser. Please use a local development web server to host Unity content, or use the Unity Build and Run option.
📖 【Unity】WebGLビルドしてブラウザで表示する時にハマった件
[Edit] - [Project Settings] - [Player] - [Publish Settings] - [Decompression Fallback]
チェックボックスにチェックを入れる
Visual Studio Code の live server
エクステンションで Webサーバーとして起動する
📺 やってみた
ゲームのアップロード先には、以下のようなサイトがあるらしい
📖 Unity Play
📖 itch.io
Step [O6o12o4o4o0] 4.Lesson Recap
読むだけ
📅 2022-12-24 sun 17:41
Step [O7o0] Django で Unity を動かすには
📂 static
├── 📂 warabenture_vol1o0
│ └── 📂 Builds
│ └── 📂 AirHockey
👉 │ ├── 📂 Build
👉 │ ├── 📂 StreamingAssets
👉 │ └── 📂 TemplateData
📂 templates
└── 📂 warabenture_vol1o0
└── 📂 Builds
└── 📂 AirHockey
👉 └── 📄 index.html
👆 index.html を templates フォルダーの下へ、 それ以外を static フォルダーの下へ
このとき、 Build という名前のフォルダーが git 操作で無視されることがあった。無視されていないか、要確認
index.html:
<!-- 冒頭に追加 -->
{% load static %}
<!-- 削除
<link rel="shortcut icon" href="TemplateData/favicon.ico" />
<link rel="stylesheet" href="TemplateData/style.css" />
↓ 追加(パスは編集すること)
-->
<link rel="shortcut icon" href="{% static 'warabenture_vol1o0/Builds/AirHockey/TemplateData/favicon.ico' %}" />
<!-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -->
<link rel="stylesheet" href="{% static 'warabenture_vol1o0/Builds/AirHockey/TemplateData/style.css' %}" />
<!-- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -->
<script>
// ↓ パスを編集すること
// var buildUrl = "Build";
var buildUrl = "{% static 'warabenture_vol1o0/Builds/AirHockey/Build' %}";
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
var loaderUrl = buildUrl + "/AirHockey.loader.js";
var config = {
dataUrl: buildUrl + "/AirHockey.data.unityweb",
frameworkUrl: buildUrl + "/AirHockey.framework.js.unityweb",
codeUrl: buildUrl + "/AirHockey.wasm.unityweb",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "Air Hockey",
productVersion: "0.1",
showBanner: unityShowBanner,
};
</script>
Step [O8o0] DOTS Best Practices
-
DOTS Best Practices
- Course, Advanced, 1 Hour 55 Mins
いったん パス
Step [O9o0] Unity Essentials
📅2023-01-10 tue
👆 ページのレイアウトが ビギナーコースと違っていて 使い方が分からん
Step [O9o1o0] Get started with Unity
-
Get started with Unity
- Mission, Foundational
ビギナーコースより エッセンシャルズを先にやればよかったのか
Step [O9o1o1o0] Welcome to Unity Essentials
-
Get started with Unity
- Tutorial, Foundational, 0 Mins
先人の話しを聞け、みたいなことをするらしい
Step [O9o1o1o1o0] 1.Overview
動画観るだけ
トランスクリプトが無い。翻訳できね~
Step [O9o1o1o2o0] 2.What's next
これから Unity をインストールしよう、という前振り
Step [O9o2o0] Get the setup wizard
-
Get the setup wizard
- Tutorial, Foundational, 30 Mins
インストールはもうしてるけどなあ。成績上げたいので読んでいく
Step [O9o2o1o0] 1.Overview
前振り文章
Step [O9o2o2o0] 2.Before you begin
Unityが使える環境の説明文章
Step [O9o2o3o0] 3.Download the setup wizard
ダウンロードの案内の説明文章
Step [O9o2o4o0] 4.Next steps
次のステップの説明文章
Step [O9o3o0] Unity Plans: What's right for me?
-
Unity Plans: What's right for me?
- Tutorial, Foundational, 25 Mins
なんか 計画だろうか
Step [O9o3o1o0] 1.Overview
個人か、企業かで サブスクリプション(料金)プランが違うという前振り文章
Step [O9o3o2o0] 2.What are Unity Plans?
動画観るだけ
この動画には英語のトランスクリプトが付いてる
サブスクリプション・プランの違いの説明
Step [O9o3o3o0] 3.Unity Plans in detail
サブスクリプション・プランの違いの説明の詳細な文章
Step [O9o3o4o0] 4.Unity Education Plans
教育者、学生向けの説明文章
Step [O9o3o5o0] 5.Next steps
次に Unity Hub をインストールする流れらしい
Step [O9o4o0] Install Unity and the Hub
-
Install Unity and the Hub
- Tutorial, Foundational, 45 Mins
📅2023-01-10 tue 19:30
Step [O9o4o1o0] 1.Overview
インストールの前振り文章
Step [O9o4o2o0] 2.Install Unity 2019.4 LTS
Unity Hub をインストールして開き、
Unity Hub を使って Unity をインストールしよう、という説明文章
Step [O9o4o3o0] 3.What is a Unity ID?
Unity ID の説明
Step [O9o4o4o0] 4.Create your Unity ID
Unity ID の作り方の説明
Step [O9o4o5o0] 5.Select a Microgame
Unityの最初の体験として、 LEGO マイクロゲームをインストールしよう、という話し
しかし Unity Hub に Select Microgame
というメニューは見当たらない。記事が古いのか?
ググると見つかるが
インストールが進まないが、できたつもりで先に進む
Step [O9o4o6o0] 6.Launch Unity Editor
Microgame をインストールしたあとの話し。
インストールしてないが、先に進む
Step [O9o4o7o0] 7.Install Unity without the wizard
インストール・ウィザードを使わずにインストールする話し
Step [O9o4o8o0] 8.Next steps
Unity Hub と、 Unity Editor と、 Unity ID の準備ができたという話し
Step [O9o5o0] Explore the Unity Editor
-
Explore the Unity Editor
- Tutorial, Foundational, 45 Mins
📅2023-01-10 tue 19:53
Unity Editor と パッケージ・マネージャーの説明をするらしい
トランスクリプトも .zip ファイルで提供しているようだ
Step [O9o5o1o0] 1.Overview
Microgame の説明の前に、 Unity Editor の説明をするという前振り
Step [O9o5o2o0] 2.Before you begin
始める前に、今開いているチュートリアルを閉じろとのことだが、そんな画面は開いていない
先に進む
Step [O9o5o3o0] 3.Unity Editor: First impressions
動画がある
最初に Unity を触った時の感想みたいな内容
Step [O9o5o4o0] 4.Introduction to the Unity Editor
Unity Editor の構成の紹介
5つの要素
- Scene ビューと、 Game ビュー
- Hierarchy ウィンドウ
- GameObject が並んでいる
- Project ウィンドウ
- Asset が並んでいる
- Inspector ウィンドウ
- GameObject の詳細情報
- コンポーネントが並んでいる
- GameObject の詳細情報
- ツールバー
Step [O9o5o5o0] 5.Review the Editor layout options
Unity Editor の前述の5つの要素の配置レイアウトは変えれるという話し
Step [O9o5o6o0] 6.Using scenes in your project
Unity Editor のプロジェクトは、複数のシーンで構成されるという話し
シーン1つ分は、体験1つ分と考えるとよいとのこと。
Unity プロジェクトの要件は、シーンを1つ以上含んでいるということだけ
Step [O9o5o7o0] 7.Practice navigating the scene
Scene ビューのウィンドウ内でのナビゲーションの説明
- Pan
- 手のひらツールでシーン・ビューをドラッグ
- Zoom
-
Alt
キーを押したまま、右クリックでドラッグ
-
- Orbit
-
Alt
キーを押したまま、左クリックでドラッグ
-
- Focus(Frame Select)
- ゲーム・オブジェクトが選択されているときに、シーン・ビューで
F
キー押下
- ゲーム・オブジェクトが選択されているときに、シーン・ビューで
フライスルー・モードは、一人称視点でシーン・ビューをナビゲートする方法
- Flythrough mode
- クリックして、右マウスボタンを押し続ける
-
WASD
キーが left/right/forward/backward に対応 -
Q
とE
キーがビューの up/down に対応 - 選択して Shift を押し続けると動くのが速い
Step [O9o5o8o0] 8.Unity Editor tips and tricks
動画観るだけ
Step [O9o5o9o0] 9.Summary
まとめ文章読むだけ
📅2023-01-10 tue 20:38
Step [O9o6o0] Explore a Microgame
-
Explore a Microgame
- Tutorial, Foundational, 30 Mins
マイクロゲームはインストールしてないが……
コード無しで ゲーム体験をするらしい
Step [O9o6o1o0] 1.Overview
文章
Step [O9o6o2o0] 2.Open a new Microgame
Unity Hub の NEW
ボタンから 4つの Microgame を選べる??
確かに 選べそうだ
テンプレートと呼ぶらしい。ダウンロードしてみる
Step [O9o6o3o0] 3.Re-open the tutorial window
チュートリアル・ウィンドウの開き方の説明だが、よく分からない
インストールが出てきたらチュートリアルが出てきた。
先に進めないゲームを、先に進めるように改造していくチュートリアルだ。
チュートリアルを進めていくと、エレベーターを作る所で 何をすればいいのか分からなくなり 嫌になったので やめた
📅2023-01-10 tue 21:45
Step [O9o6o4o0] 4.Complete the in-Editor tutorials
文章。
完了してないけど先に進む
Step [O9o6o5o0] 5.Explore the submissions
マイクロゲームの提出の仕方の説明
Step [O9o6o6o0] 6.Submit your Microgame in our Gallery
チュートリアルを完了すると、マイクロゲームを提出する方法を習得できるらしいが、
LEGOのチュートリアルが嫌になったので ここで終わる
Step [OA10o0] Creative Core: UI
📅2023-01-11 wed 18:56
-
Creative Core: UI
- Project, Beginner, 3 Hours 45 Mins
コースから外れてしまったので、適当に選んで始めてみる
と思ったが、タイトルを見ると もうやったビギナーコースと重複してるかもしれない。パスする
ほかのも見てみるが ビギナーコースと重複してそう
Step [OA11o0] DOTS Best Practices
-
DOTS Best Practices
- Course, Advanced, 1 Hour 55 Mins
とりあえず もう一回見てみる
どうも内容が 高速化、最適化のもののようだ。興味無いのでパス