Unityの寺子屋 4日目

学習内容

アニメとSEの設定

◇アニメとSEの設定

復習
アニメはctrl+6で開くことが出来るアニメーションウィンドウから設定できる。
アニメーションウィンドウ中央のCreatから新しいアニメを作る。
2Dではアニメに使う画像などをプロパティにドラッグ&ドロップすることで、簡単に作成可能。

複数のアニメを状況に応じて切り替えたい場合はアニメーターコントローラーから設定できる。
ある条件下でのみ再生したいアニメがある場合、遷移条件を設定する必要がる。
遷移条件の設定はトランジション(アニメ間にある矢印)に対して行うが、こういった特定条件下でのみ再生したいアニメの場合にはどこから遷移させて良いのかわからない場合がある。その場合は、AnyStateからトランジションを引けばよい。
AnyStateは現在のステートは指定せず、切り替え用のトランジションが必要な場合に使用する。

DOTweenを使ったアニメ

Sequenceクラス:アニメーションの統合を行えるクラス。
Append():直前の動作に続けて設定したアニメを再生するメソッド
シーケンスクラスのインスタンスを作って、そこからAppend()を呼び出しますが、引数に追加したいアニメ(Tweenなど)を書き込むと直前の動作に続けて書き込んだアニメが再生されます。
具体的なコードなどは以下のサイトを参考にしてください。

Qiita – DOTweenをふわっとまとめてみた
https://qiita.com/kagigi/items/bdf4d42835add07b0077

ToAlpha(getter,setter,終了値、期間):DOTweenクラスの関数。第一第二引数にはラムダ式というものを使って、不透明度を取得・設定するための匿名関数を指定するとのこと。正直何言ってるのかわからなかったです….
ラムダ式というものは関数を設定するためのC#の文法とのこと。ようは関数を定義しているらしいです。
どうやって定義しているかというと、

引数 => 関数内の処理

という形で記述されていました。
一応ざっくり説明をしてくれてはいるものの、しっかりとどういうものか知っておいたほうがよさそうですね。

後はSEを追加しました。
また、本当は追加ステージの作成と、タイトル、ステージ選択画面まで作って一応完成ですが、そちらについては「UnityではじめるC#」(リンクはアマゾン)で一度学習した内容なので今回は割愛しました。
そんな感じで完成したゲームがこちら。



ついにUnityの寺子屋終了です!


内容的にかぶっているところなど、割愛した部分もありますが、 一応1カ月で3冊の入門書を終わらせることが出来ました。
ここからすぐ自作ゲームを作ることは難しいかもしれませんが、スタートラインにはたてたのではないでしょうか。
とりあえず、作りたいものにチャレンジしてみて、その過程でいろいろなスキルを身についけていきたいと思います。

そういえば、今まで、この本を含めて3冊のUnity入門書でC#も少しは勉強できてはいるものの、その内容はC#の超基本的な部分のみですので、C#のいわゆる常識的なところ(基本的な文法や使い方、用語など)はちゃんとしたC#専用の入門書、学習書を使って勉強したほうがよさそうです。
有名どころだと独習C#などがあるようだったので、本屋で内容を見てみたところ、結構難しそう+つまらなそう(モチベが上がらなさそう)でした。
おそらく、今はゲームを作りたい欲が強く、そういった部分に気持ちが向かないのだと思います。
ゲームを作っていくうちに、C#の文法などがわからなくて困る場面が出てくると思うので、その時にそういった本で勉強するのがモチベーションを維持しやすいのかなと思いました。
せっかく一カ月あった休みを使って勉強したので、このまま何も残せず終わりたくないですし、自分のこれからの人生のためにも続けていきたいと思うので、モチベーション管理はしっかりしたいと思います。

次回以降はゲーム作成中に勉強した技術や、作成中のゲームなどの制作過程を書いたり、作成するにあたり取り組んでいる本などを今までのような形式で書いていこうと思います。

それでは、今日はこの辺で。


Unityの寺子屋 3日目

学習内容

  1. chap4:放置ゲームをクッキークリッカー系に変える
  2. chap5:横スクロールアクションゲームの作成
    • Rigidbody2Dのプロパティ
    • PhysicsMaterial2D
    • ゲームクリアの処理

1.chap4:放置ゲームをクッキークリッカー系に変える

OnApplicationPause関数:UnityEngineクラスの関数で、引数はbool型。アプリがバックグラウンド以降or復帰した時に呼び出される。
OnApplicationQuitというアプリが完全終了した際に呼び出される関数もあると野のこと(下記参考サイト参照)

以下参考サイト

chap4の内容はクッキークリッカー系に直すだけでした。
基本的なシステムは放置ゲームのものを流用すればできるようになっていたので、初めて出てきた関数だけメモがてら残しています。

2.chap5:横スクロールアクションの作成

chap5からは横スクロールアクションを作成していきます。
正直この章目当てで買ったくらい横スクロールアクションのゲームが作りたいと思っています。メトロイドが好きなので、メトロイドヴァニアなんかをそのうち作れたらいいなぁと思っております。

◇Rigidbody2Dのプロパティ

プロパティ説明
Body Typeその物体のタイプを、Dynamic、Kinematic、Staticから選択する。
Materialマテリアルを設定する。
Simulated物理演算と衝突判定のon/offを切り替える
Use Auto Massonにするとコライダーの形状から質量を自動的に検出する。
Mass質量のこと。(Use Auto Mass)をオフにしているときはここに密度を指定する。重い物体は動かす際にも止める際にも大きな力が必要になる。
Linear Drag移動の減衰値
Angular Drag回転動作の減衰値
Gravity Scale重力の影響度合。0にすると無重力状態を表現できる。
Collision Detectionほかのオブジェクトとの衝突検知の方法
Sleeping Modeプロセッサー負荷を抑えるためのオブジェクトのスリープ方法。
①Never Sleep、②Start Awake、③Start Asleepの三つがある。
①は常時動ける状態なので、負荷がたまりやすい。衝突すればスリープが解除されるため、たいていは初期設定の②で問題ない。
Interpolateスムージングの設定。処理の重さなどが原因で動きがぎこちなくなる時に利用する
Constraintsリジットボディーのモーション制限(移動/回転)。positionのx、yどちらかをonにすると縦or横にしか動かなくなる。rotationのzをonにすると回転しなくなる。

LinerDragとAngulerDragを調節することで粘り気のある液体のなかを動くような表現に使える。

Rigidbody2Dコンポーネントを利用してキャラクターの動作などをさせる場合には、FiedUpdate関数内で操作すると決められている。
これはFixedUpdate関数はUpdate関数と違い、固定フレームレートで動くため、動作環境依存でフレームレートが変わり、遅延してしまったり、不安定になることがないためである。

復習

velocity:Rigidbodyの速度ベクトルのこと。
enum:列挙型。列挙型で変数の宣言を行うときは「タグ名 変数名;」とする。

◇PhysicsMaterial2D

3Dグラフィクスなどでは物体の表面の質感の設定を指す。今回設定するのは物理エンジン用のPhysicsMaterial2Dでは物体が接した時の滑り具合を設定する摩擦と、衝突した時の跳ね返り度合を調整する弾性を設定できる。

復習
・Linecast関数:Physics2Dクラスのラインキャスタ機能の一種で線分上に特定のレイヤーに属するColliderが存在する(ヒットする)場合はtrueを返す。
Physics2D.Linecast(始点、終点、レイヤーマスク、トリガーも対象にするか)

ここではブロックや敵との衝突判定をおこなうために、ラインキャスター関数を用いている。キャラクタープレイヤーの足元を三角状に掘り下げるような判定領域を作っている。敵キャラがブロックにぶつかって移動方向を変える際にも、敵がブロックと衝突したかどうかを検出するために使っている。

・既習のゲーム外の判定について
OnTriggerEnter2D関数でプレイヤーがトリガーのコライダーに接したことを判別している。関数の引数は接触した相手のCollider2D型を参照する。

◇ゲームクリアの処理

ゲームクリアの処理は基本的にはゲームオーバー時と変わらない。
しかし、ゲームオーバーではプレイヤーは消していたが、今回はクリア時にプレイヤーを消さないため、ゴールのオブジェクトに触れ続けると接触判定が繰り返し発生してしまう。
そのため、クリアの演出(UIの表示など)+ ゴールオブジェクトとプレイヤーの衝突判定が消えるようにしなければいけない。

なんやかんやで、chap5時点のゲームはこちら

念願の横スクロールアクションの基礎が勉強できました!
やっていることは今までと同じですが、敵を踏む処理や敵の移動の処理の方法などの基本を学べました。
最近では、「あのゲームのあの敵はこうやれば実装できるのかな?」とか「あの動きはどう処理してるんだろう。」といった考えや疑問がたくさん湧いてきて、それを考える時間がとても楽しいと感じています。
次はプレイヤーや敵にアニメとSEなどの音楽、追加ステージなどをつけて完成です。
画面をスクロールさせるにはマップを広くしたり、カメラにプレイヤーを追従させたりする必要があります。
その辺についても勉強できるのかな?
一応今まで自分が勉強してきたことでどうにかなりそうな気もするので、この本が終わったら挑戦してみたいです。

この本はchap7がアプリ販売についての考え方になっているので、ゲーム作成に関する内容は次のchap6が最後になります。
正直、書く内容が陳腐すぎるだろうなと思いながら書いておりますが、どうでしょうか..?
chap6の記事は少し内容も薄くなる(chap6の内容が今までやってきた本の内容が見についていればできてしまうレベルだと思われる)ので、さらに書くことがなさそうなのが心配ですw
そんな感じではありますが、最後まで頑張ろうと思います!

それではこの辺で。

Unityの寺子屋 2日目

学習内容

  • BGMと効果音を鳴らす
  • オブジェクトにアニメーションを付ける
  • DOTweenを使った演出
  • スコアデータの保存

◇BGMと効果音を鳴らす

ゲーム中のBGMは、ゲームが起動している間、ずっとなり続けてほしいので、ゲームの間常に存在しているオブジェクトから鳴らす。(例えばゲーム中の処理をする空のオブジェクトなど)
方法としては、オブジェクトにAudio Sourceコンポーネントをアタッチし、音源をAudio Clipにドラッグ&ドロップすればよい。

ゲーム中の動作に演出としてSEを付けたい場合にはスクリプトから制御する。
具体的には…
ゲームマネージャーなどの制御オブジェクトにアタッチしているスクリプト上で
AudioSource型の変数(仮にaSource)とpublic なAudio Clipクラスの変数(仮にSE)を宣言しておく。

Start関数内で、aSourceにAudio Sourceコンポーネントを取得させておく。

ヒエラルキービューに戻り、スクリプトをアタッチしているオブジェクトのインスペクタ―ビューからpublicで宣言しているSEに鳴らしたい音源をドラッグ&ドロップし、変数に音源を渡しておく

音声を鳴らしたい処理を行っている関数内でaSource.PlayOneShot(SE);と書くと、処理を行った際に変数に渡していた音声が鳴る。

◇オブジェクトにアニメーションを付ける

アニメーションはwindow→Animation→Animation(もしくはCtrl+6)から作成することが出来る。アニメーションを付けるとAnimaterウィンドウとAnimationウィンドウの2つが現れる。
前者は複数のアニメーションを切り替える仕組み。アニメーターウィンドウでは、複数のアニメーションがボックスとして表示されている。これらボックスはステートと呼ばれている。特定のボックス間には矢印が伸びているが、これはアニメの遷移(トランジション)を表している。

後者では具体的にどんなアニメーションをオブジェクトに付けるか編集することが出来る。アニメーションウィンドウでは位置を変えたり、スケールを調整したりと様々なことが出来るが、どのようなアニメが存在するのかはここでは割愛する。
このアニメーションでは素材さえあればパラパラ漫画のようなアニメを付けることも可能である。
また、スクリプトからアニメーションを制御することもできるため、特定の処理を行う場面でのみアニメーションさせることも可能である。

GetCurrentAnimatorStateInfo関数:レイヤー数(アニメーターウィンドウ内のレイヤー?)を引数にとり、現在のアニメーションステートを返す関数。返り値のステートはAnimatorStateInfo型。
引数のレイヤー数は0だとBaseLayerを参照するのだと思う。が、あっているのかな…?
有識者の方がいましたら、コメントお願いします。

上記関数が持つfullPathHashは現在のステート(レイヤー名.ステート名)をIDに変換してくれるプロパティ。IDはint型の数ケタの数字で、この値を条件文内で比較することでスクリプト上からアニメーションの遷移を制御できる。
AnimetorクラスのStringToHashは引数に渡したstring型の値をint型のIDに変換する関数で、fullPathHashで取得したステートのIDとStringToHashでIDに変換したアニメーションステートを比較して、目的のステートと一致しているのか判断する際に使われる。

使用例は以下参考サイトを参照。

Pop技術ログ – 【Unity】アニメーターによる状態遷移とソース側での制御【技術】
http://blog.livedoor.jp/f_paul/archives/27309591.html

Amnesia~あむねじあ~ – Animator.StringToHash  文字列からパラメーター ID を生成。
http://bestrafung.blog.fc2.com/blog-entry-22.html

◇DOTWEENを使った演出

オブジェクトを曲線を描いて動かしたり、ジャンプさせたりと少し特殊な動かし方をしたい場合に便利なDOTweenというAssetを導入しました。
今回は取得したアイテムが曲線を描いて動く演出を付けるために以下のようなスクリプトを書きました。

各種関数などの簡単な説明は上記のスクリプトにコメントとして残してあります。
DOTweenの関数はDOTweenの公式ドキュメントや、DOTweenについてまとめている方がいらっしゃるので、そちらを見ていただけたらと思います。
自分もいろいろ調べてみて、使い方などその都度書いていこうと思います。

以下参考サイト。

GitHub – anzfactory/HowTo DOTween.md
https://gist.github.com/anzfactory/da73149ba91626ba796d598578b163cc

◇スコアデータの保存

PlayerPrefs:データを保存する仕組み。各OSの特定の場所にデータを保存してくれる。読み書きはキーと呼ばれる値を識別するための名前と値となる数値や文字列をセットにする。
理解のためのに参考にしたサイトは以下を参照

Qitta – Unityで簡単なセーブとロードの方法
https://qiita.com/tilyakuda/items/e3ccfbf507acfb16404f

PlayerPrefsではint、float、stringの3つの型しか使えない。例えば時刻を保存したい時などはDateTime型の値になるので、このままでは保存できない。
しかし、変数名.ToBinary.ToStringとすると、ToBinaryで変数に格納された値を64bitのバイナリ値に直し、その後ToStringでバイナリ値を文字列に変換することで、型の違う値を保存することが出来る。
ちなみにSetIntの扱う整数は32bitの値なのでバイナリ値のままでは保存が出来ない。

少し完成まで時間がかかりましたが、作ったゲームはこちら。

放置ゲーム完成版

やっぱりひとつ前の本よりも内容は難しくなっていて、完成させるのが大変でした。
ただ、調べればすぐ理解できたり、あーあれかってわかるときもあるので、自分の成長を実感しております。
また、やっていることは同じようなことの繰り返しなので復習になっていいですね。

本当は19日に投稿するつもりだったのですが、忘れていたので今日になってしまいました。

今日はchap4+αの内容も投稿しようと思います。

それでは、この辺で。


Unityの寺子屋1日目

学習内容

  • chap2:放置ゲームの作成
  • chap2内でわからなかったところ(UIImageとScript)

UIImage

・インスペクタ―内のRaycastTarget:オフにするとオフにされたイメージはタッチ判定の対象外となる。

Script

・(~)Instantiate(-):インスタンティエイト関数は引数(-)に渡したオブジェクトのクローン(インスタンス)を生成する。関数の前の()内(~)にGameObjectなどの型を入れると、指定した型にキャスト型変換して、指定した型の変数を代入する。

・SetParent関数:セットペアレント関数は親のオブジェクトを設定する関数。
 変数に対してこの関数の処理を行うと、引数に渡したオブジェクトの子として変数が設定される。

EventTriggerについて – Qiita

https://qiita.com/takesuke/items/e3b314aa7fd9111bc17f

代表例はボタンコンポーネントについてるOnClick。
詳細は上記リンクQiitaに記載されているので、参考にしてください!

イベントトリガーコンポーネントを目的のオブジェクト(本内ではプレハブ)にアタッチして、関数を読みだすのですが…ここで問題発生。

イベントトリガーコンポーネントを アタッチした後、関数を読みだすために”使いたい関数(メソッド)の書かれたスクリプトをアタッチしたオブジェクト”をNoneの部分にドラッグ&ドロップし、NoFunctionから目的の関数を呼び出すのですが、オブジェクトの部分にスクリプトを直接当ててしまっていたので、関数が全然呼び出されませんでしたw

そこそこ時間を無駄にしてしまいました…
調べてみるとあまりそういったミスをしている方はいなかったのですが、初心者や初学者、勉強したての方はミスってしまうのではないかと思い、残しておこうと思いました。

・DateTime.UtcNow Property:コンピューター上の現在の日時を世界協定時刻 (UTC) で表した DateTime オブジェクトを取得する。
時刻の差を記録するためにDateTime型同士の引き算をすると、その結果はTimeSpan型になるため、~秒間隔でなにかをする際には、TimeSpan型で時刻差を扱うようにしたほうが良い。

・FromSeconds():指定した秒数を表す TimeSpan を返します。秒数は、ミリ秒単位の精度で指定する。つまり、引数にいれたdouble型の数字をミリ秒単位の精度で秒数に直して返す関数。

・SetSiblingIndex(): ヒエラルキービュー内などのゲームオブジェクトの順番を指定した順番に直すような関数?。この本では、レベルアップの演出で表示する雲のオブジェクトを、2つのオブジェクトの間に表示させるために使用していた。
詳細は下記を参照。

Kanのメモ帳 – Hierarchy内の順序をプログラムで変える

・enum型:連続する定数(列挙体)を定義するための型。曜日や月など特定の値しかとりえないものに対して使われる。
詳細は以下を参照。

++C++;//未確認飛行C – 列挙型

https://ufcpp.net/study/csharp/st_enum.html

なんとかchap2の内容を一通り終えることが出来ました。
今まで2つの本を通して、ゲームってこんな感じでできるんだ!という思いと、意外と理解できるし、もう少し勉強すればサックっと一つくらいゲーム作れるかも!とか思っていました。
こんな調子だったのでこの寺子屋をはじめる前も、サクッと終わらせてゲーム一個作ってみよ!なんてことを考えていましたが、考えが甘かったみたいです….

というのも今までやっていた2冊に比べると内容は格段にレベルアップしております。やっていることは「UnityではじめるC#」の延長なのですが、スクリプトも複雑になってきて、スクリプト一つ一つでやっていることを理解することはできても、自分でこれを作れるのか?という不安が出てきました。

ただ、サンプルとして用意されているゲームのジャンルがとても素晴らしい(汎用性が高い)ので、実際に自作ゲームを作る際にかなり参考になる(流用できるところがかなり多い)だろうと感じています。
あと、そもそも最初の一つ目に作ったゲームなんて、たいていの人がクソゲーしか作れないだろうと思いますし、自分が抜群にできるやつとも思っていないので、最初はほぼスクリプトやシステムが丸パクリみたいなものでも、いいと思うようにしました。
ただ、この数週間でずぶの素人から、ここまで良くこれたものだとも思いますので、そこは褒めてあげて、さらにレベルアップしていきたいと思います。
寺子屋は時間がかかりそうなので少しずつでも進めていこうと思います。
あんまり根を詰めても精神的に良くないですし。

それでは、寺子屋の1日目はこれで終了です。
次はchap3に取り組んでいきます。

あ、あと参考にしたリンクなどを載せるようにしてみました。
同じようなところでつまずいた方が奇跡的にこのブログにたどり着いたとき、参考になればと思いますw
もし、なにかこうしたほうがいいよみたいなアドバイスなどありましたら、コメントを下さるとありがたいです。

それでは、ありがとうございました。
では、この辺で。

UnityではじめるC#4日目

学習内容

  • 物理パズルの作成
  • PlayerPrefsの使い方

◇物理パズルの作成

やったこととしては、ゲームの要素となるボール、壁3種類(移動可能な壁、移動歩かな壁、ゲーム外検出壁)、ゴールをゲームオブジェクトとしてシーン上に配置して、Rigidbody2Dやコライダーなどのコンポーネントをアタッチ。
ゲームのリセット機能を付けたり、ボールやシーン上に配置する壁はPrefab化しておいて、新しいステージなどを作成する際やリセット時にオブジェクトを配置できるようにしたりしました。
また、ステージ選択画面を作ったりと、今までやってきたこと(Unity5の教科書も含めて)を総動員してゲームを形にしていきました。
なので、内容としては今までやってきたことの復習といった感じだったので、細かいことは割愛します。

◇PlayerPrefsの使い方

復習的な内容だったと話したばかりですが、どこまでクリアしたのかを記録できる機能をつけるために、PlayerPrefsの使い方を新しく学習したので、内容をまとめておこうと思います。

ステージセレクト時にいきなり先のステージに進むことが無いよう、クリアしたステージを確認し、直前のステージがクリアされていれば選択できるような機能を実装しました。ただ、そのためにはクリアしたステージの情報を記録する仕組みが必要です。
通常の変数はプログラムを終了すると情報が消えてしまうので、ファイルのように終了後も残すためには別の方法を使う必要がありますが、そのため仕組みとしてPlayerPrefsがUnityでは用意されています。
これを使うと、各OSの特定の場所にデータを保存してくれます。
使い方としてはPlayerPrefsクラスの関数を使って書き込みと読み出しを行うことが出来ます。
読み書きにはキーと呼ばれる値に識別するための名前と値となる数値や文字列をセットにします。具体的には以下のようにします。

PlayerPrefsクラスのメソッドには値を設定するSet○○○と、値を取得するGet○○○があって、それぞれfloat型用とint型用、string型用の三種類が用意されています。そのほかキーと値を削除するDeleteAll、DeleteKeyなどもあります。Set○○○で書き込んだ値はアプリの終了時にファイルに保存されますが、クラッシュすることもあるので、PlayerPrefsに用意されているSave関数を使えば確実に保存できます。
これらを使って、ゲームのクリア時にデータをセーブし、先のステージが解放されるような機能を実装しました。
ただ、いろいろ実験してみて理解を深めようとしてみたのですが、いまいち使い方が理解できていないので、もう少しリファレンス読んでみたり、ほかの技術ブログをのぞいてみたりしたいと思います。

・memo

Invoke関数:第一引数に指定した名前の関数を第2引数で指定した時間後に呼び出す関数。

そんなこんなで、完成したゲームがこちら。

これでUnityではじめるC#終了です!
3日程度で終了できましたが、学ぶことが多く、密度の濃い3日でした!
「脱出ゲーム」と「物理パズル」という2大定番ゲームの作り方を勉強できたのもかなり大きいです。
次はUnityの寺子屋を勉強しようと思います。
その傍らで、今月中を目標に自作アプリを作ってリリースしたいと思っているので、どんなアプリにするのか企画もしていきたいと思います。
それでは今日はこの辺で。

UnityではじめるC# 3日目

学習内容

chap5:脱出ゲームの作成

・タイトル画面の作成

UIの作成:ボタンなどUIの部品を配置する土台となるCanvasを作成し、UIを作りこむ。
Canvasはゲーム画面よりもはるかに大きいサイズで作成されるが、これでは単位の基準があてにならないので調整する。
調整はヒエラルキービューのRender ModeをScreenSpace-Cameraに変え、Render CameraにMain Cameraオブジェクトをドラッグ&ドロップ。
Canvas Scalarコンポーネントはキャンバス上のUIパーツのサイズを調整する。
UI Scale ModeをScale with Screen Sizeに変更した場合、Reference Resolutionに指定した改造お土(画面サイズ)を基準に調整する。
Screen Match Modeは実機の画面サイズとReference Resolutionの設定値が一致しない場合に用いる。
UIパーツはTransformコンポーネントの代わりにRectTransformコンポーネントを持っている。このコンポーネントでは、Anchorの種類によって、位置かサイズを自動調整できる。
UIパーツはボタンやテキストなど、必要なものは一通りそろっているので、それらを使って、UIをデザインしていく。
ボタンなどのUIパーツはイベントを持っており、そこにどのメソッドを呼び出すのかを指定することが出来る。
ボタンの場合にはOnClickイベントがある。クリックされたときにどんな関数が呼び出されるかなどを指定することが出来る。

変数を宣言する際に変数型の前にconstを付けると定数化することが出来る。
定数の名前は変数名との見分けがつくように、慣用的に大文字のアルファベットを使う。

ボタンに関数を割り当てる
ボタンのOnClickイベントに関数を割り当てるには、割り当てたい関数を含むコンポーネントがアタッチされたオブジェクトなどをNoneの部分にドラッグ&ドロップし、Functionの選択から割り当てたい関数を選ぶことで割り当てることが出来る。
そうすることで、ボタンがクリックされた際に、OnClickイベントに割り当てた関数が呼び出され、実行される。

あとはひたすらゲームオブジェクトをボタンとして設置して、関数割り当てて、条件を満たしていればアイテムが手に入って…と、繰り返し作業してゲームが完成しました!

完成したゲームはこちら。

そんなこんなで脱出ゲームも完成しました!
この本を始めてからまだ3日目(1日目と2日目の内容は1日で終わっているので実質2日)でここまで来ているのでかなりさくさく進めてる実感があります!
この本が終わった後は、自作の寺子屋などにチャレンジするつもりですが、その後は1つ自力でゲームを作ってgoogleのプレイストアにリリースしてみようと考えています。

とりあえず、次の物理パズルゲームの作成を頑張ります。

それではこの辺で!

UnityではじめるC# 2日目

今日の学習内容

  • chap4:Unityプログラミングの基本

◇イベント関数:Start、Update関数などのこと。ほかにはOnMouseClickやOnMouseDrag、OnColisionEnter、OnColisionExitなどがある。
Update関数などの定期イベントはフレーム事に呼び出される。fpsが60くらいだとすると、Update関数もそのぐらいの頻度で呼び出される。

定期イベントにはFixedUpdate、Update、LateUpdateの三種類がある。

  • LateUpdate関数:すべてのゲームオブジェクトの更新が完了した後でやりたい処理がある場合に用いる。一般的には全キャラクターの移動が完了したあとで、それに合わせてカメラを移動する処理などがある。
  • FixedUpdate関数 : 固定間隔で呼び出される 定期イベント。3Dゲームなどで1フレームの処理がパソコンで処理しきれないほど重い場合には、描画しきれないフレームが間引かれ、fpsが減ってしまうことがある。これによって不都合が生じる場合に用いられる。

◇画像の表示

2DゲームではTextureTypeがSprite(2D and UI)になっている必要がある。
Generate Mip Mapsは3Dゲームのテクスチャ向けの設定で、有効にしているとスマートフォン上で画像がぼやけることがあるので、2Dゲームの場合にはオフにする。

SpriteRendererコンポーネント:Spriteタイプの画像を表示するコンポーネント。Spriteに指定された画像がゲームオブジェクトの外観として表示される。

◇インスペクタ―上の「プロパティ」

インスペクター上のTransformコンポーネントでPositionなどのプロパティを調整することで、オブジェクトの正確な位置などを調節できる。
ここでいう「プロパティ」とはC#のプロパティとは異なるものであるが、Unityのクラスが持つプロパティやメンバー変数はたいていインスペクタ―上に表示されるので、同じものと考えてもあながち間違えではない。
スクリプトコンポーネントをオブジェクトにアタッチすると、スクリプト上でpublicで宣言されているメンバ変数はインスペクタビューから値を設定できるようになることからも、ほぼ同じものといえるだろう。

◇コンポーネントの取得

GetComponent関数:ゲームオブジェクトが持っているコンポーネントを取得する関数。下記の表のような種類が存在する。

メンバー働き
gameObject変数
このコンポーネントがアタッチされているゲームオブジェクト
transform変数ゲームオブジェクトにアタッチされたTransform
GetComponent関数ゲームオブジェクトから指定した型のコンポーネントを取得
GetComponentChildren関数子オブジェクトのコンポーネントを取得
GetComponentParent関数親オブジェクトのコンポーネントを取得
GetComponents関数ゲームオブジェクトから指定した型のコンポーネントをすべて取得する(同じコンポーネントが複数アタッチされている場合に使用)

◇Transformクラスの利用

Transformコンポーネント(C#から見るとTransformクラスのインスタンス)を取得し、Transformクラスのメンバー変数を使うことが良くあるが、Transformクラスは次の表のようなメンバー変数を持っている。

メンバー働き
localPotion変数ローカル空間(親オブジェクト基準)の位置
localRotation変数 ローカル空間(親オブジェクト基準)の回転
position変数ワールド空間の位置
rotation変数ワールド空間の回転
localScale変数親オブジェクトを基準にした相対的な拡大縮小率
LookAt関数対象をTransformの方向を向かせる?
TransformPoint関数ローカル空間からワールド空間へpositionを変換

ここでpositionはVector3型の変数であるが、Vector3はクラスではない。
Vector3は構造体と呼ばれ、classではなくstructで定義する。クラスに似ているが、intなどと同様に値として扱われる。変数から変数に代入された場合には、クラスであればインスタンスを参照する状態になるが、Vector3では別のものにメンバー変数がコピーされた状態になる。

◇Prefab→割愛

とりあえず4章を終わらせました。

4章は簡単なスクリプトを書いてみて、オブジェクトを動かしてみる感じでした。
内容的にもキホンのキの部分という感じなので、Unity5の教科書には載っていない部分だけピックアップして書き出してみています。
4章のようなオブジェクトをスクリプトコンポーネントで制御することは、すでにUnity5の教科書を通してやってきているので、スクリプトを読んで理解できたら再現はしない方針にしました。

chap5では脱出ゲームを作るようなので、こちらはしっかりスクリプトの意味を理解しつつ、実際に手を動かして取り組んでみようと思います。

ここまで読んでくださりありがとうございます。
それでは、この辺で。

UnityではしめるC# 1日目

どうも、みりんです。

今日からUnityではじめるC#に取り組んでいこうと思います。
すでに、Unity5の教科書に取り組み、一通りやり切ったのでこの本はサクサク進めていければと思っております。
進めている中で、大切だと感じだり、未知だったもの、復習もかねて残しておきたいことなどをここに書いているつもりです。
すでに一冊取り組んでいることもあり、記述内容が少しずつ絞られていく可能性があるので、内容が薄くなってしまったら申し訳ないですw

学習内容

  • chap1:Unityの基本操作→割愛
  • chap2:C#の基本
  • chap3:条件分岐と繰り返し処理

◇chap2:C#の基本

スクリプトの上の行→usingディレクティブ。Unityのクラスなどを使うために宣言。
スクリプト名のクラスの定義→後続の{}ブロックがスクリプト名のクラスの内容であることを意味している。
Start&Updateメソッド(関数)→2つの関数の役割については割愛。関数は必ずクラスの中に書く。
四則演算では、複数の演算子を使う場合、通常の四則演算と演算子の優先順位が異なるため注意が必要。
例えば以下の計算。

実行結果は「1+8×4は132」となる。*は+よりも計算の優先順位が高いため、8×4が計算され32となる。その後+の計算処理が行われるが、+は左の+から優先的に計算を行うため、前の文字列と1との間で文字列の連結が行われ、上記の実行結果となる。これは()を用いて計算の優先度を変えることで、防ぐことが出来る。
この辺りは、実際の数学と同じですね。

以下に演算子と優先順位を表としてまとめたものを載せておきます。
これは本のp34 表2-02と同じものです。本をお持ちの方はそちらを参照してみてください。

優先順位カテゴリ演算子
1基本式. () [] x++ x– new typeof checked unchecked
2単項式+ – ! ~ ++x –X (T)x
3乗法式* / %
4加法式+ –
5シフト<< >>
6関係式と型検査< > <= >= is as
7等値式== !=
8AND(論理)&
9XOR(論理)^
10OR(論理)|
11AND(条件)&&
12OR(条件)||
13条件?:
14代入= *= /= += -= <<= >>=&= ^= |=

C#の変数にはいくつかの型が存在する。代表的なのはint、float、double、string、boolなど。このように標準で用意されている型は組み込み型と呼ばれる。
型はクラスからつくることもできる。
変数の型と代入しようとしている値の型が異なる場合には代入することが出来ませんが、型変換(キャスト)と呼ばれる機能を使うことで、代入しようとしている値の型を変換して代入することが出来ます。キャストは下記のように記述します。

この場合、int型なので小数点以下は切り下げられてしまいます。この型変換はどんな型同士でもできるわけではなく、数値同士など関連性があるものだけで可能だそうです。

・クラス:変数や関数をグループ化して扱う「くくり」のようなもの。

Unityであればゲームオブジェクトそれぞれがクラスと関連付けられる。
例えば、プレイヤークラス、エネミークラスなど。こういった考えをオブジェクト指向と呼んでいます。
クラスを使って様々な実態のある物(Unityでいえばゲームオブジェクト)を作ります。例えばプレイヤークラスというものがあったら、実際にプレイヤーが操作する主人公となるキャラクターのことです。こういった、クラスを使って作成した実態(オブジェクト)はインスタンスと呼ばれます。
インスタンスはnew演算子を使って作ることが出来ます。
クラスを作るという事は、新しい型を作ることと同義なので、クラスを作るたびに新しい型が出来ていることになります。
あるクラスの中の関数や変数を利用したい場面があるかと思いますが、その時には.(ドット)演算子を使うことで、それらの関数、変数を呼び出して使うことが出来ます。

・クラスの継承

プレイヤークラス以外にも、NPCクラスなどの似通ったクラスを作る場合、それぞれに同じ機能が必要になる場合がありますが、そのような場合には継承を使います。継承を使うことで、元(親)となるクラスの変数や関数を引き継いだ新しいクラスを作ることが可能になります。共通する機能は親のクラスに記述し、新しく追加したい機能や個別に設定したい機能は子のクラスに記述することで、共通部分は記述せず、新しいクラスを定義することが出来ます。
Unityでは下記の1文が書かれていますが、これが継承です。

MonoBehaviourクラスを継承したLessonというクラスを作るという事を意味しています。Start関数やUpdate関数はMonoBehaviourクラスの機能で、これを継承しているため、新しく作ったスクリプト上で使用することが出来ています。
ただし、継承することのできる親クラスは1つまでなので、複数の親クラスから継承して新しいクラスを作ることはできないので注意です。

・インスタンスと変数の寿命

インスタンスはnewを使って作成し、変数に代入しますが、実際に変数にインスタンスが代入されているわけではありません。イメージとしては作成したインスタンスにアクセスできるチャンネル=変数と考えると良いかもしれません。インスタンスは変数によって参照されている(チャンネルが作られている)状態でないと、一定時間で自動的に消えてしまうので、消したくないインスタンスは常に変数から参照されている状態にしておく必要があります。

・変数のスコープ(寿命)

クラスのメンバー変数と関数内で宣言した変数にはスコープの違いが存在します。
メンバー変数はクラスのインスタンスが消滅するまで存在し続けますが、関数中の変数は所属している関数の処理が終わるまでしか存在し続けられません。
すべての変数がメンバー変数になってしまうと管理が大変になります。変数の寿命が決まっていれば、その変数が生きている間だけ管理すれば良く、異なるブロックであれば、同じ名前の変数を作ることもできるので、気軽に使い捨てることが出来ます。

◇chap3:条件分岐と繰り返し処理

・if文:割愛

・switch文:ifがtrueかfalseの2択なのに対し、switchでは条件を複数に分岐させることが可能。
switch文の変数や式の内容と、caseラベルの値が一致するかを比較し、一致した場合にはcase~break文までを実行する。
どのcaseとも一致しない場合は、default文の後の処理が実行される。
caseラベルには式や変数を使うことが出来ず、数値か文字列のみが使える。
そのため、等しいか否かしかチェックすることができない。
caseラベルを続けて記述すると、二つのうちどちらかのラベルと一致した場合に処理が実行される。

・条件演算子?:

?:を使うことで、演算子だけで条件分岐を作ることが出来る。
変数=条件式?trueの値:falseの値;
これを使うことでifよりも短い文で条件分岐を記述することが出来るが、わかりづらいので、無理に使う必要もないらしい。

・繰り返し文

for、while、do-while→割愛
continue文:繰り返し処理を1回スキップする。

・配列(変数):複数のデータを記録できる変数。普通の変数には値を1つしか代入することが出来ないが、配列には値を代入できる枠が複数あり、それぞれに別々の値を代入できる。イメージは棚やロッカー。
配列内の1つ1つの変数のことを要素、箱一つ一つに付けられている番号のことを添字と呼ぶ。
配列の宣言は以下のように行う。

これでarrayという要素数5個(箱の数が5個)の配列変数が宣言されていることになる。
配列はArrayという特殊なクラスのインスタンスで、宣言した配列変数はArray型インスタンスを参照している状態になっている。
そのため、下記のように1つのインスタンスを複数の配列変数で参照したり、宣言後の配列変数に別のインスタンスを参照させたりすることも可能。

配列変数も以下のように初期化させることが出来る。

複数の値を代入できるのは最初の宣言時のみで、宣言が済んだ配列変数に後から複数の値を記録することはできず、1つの要素ずつに代入していく必要がある。
要素に値を代入するには、変数名[添字]と書くことで、普通の変数と同じように使うことが出来る。ただし、添字は0からスタートすることに注意すること。

・クラス型の配列変数

クラス型の配列変数は次のように宣言する

クラス型の配列変数も{}を使うことで初期化することが出来る。
上記のスクリプトで

Person[] parr = new Person[5] → Person[] parr = {new Parson(), new Parson()}

と書き換えると要素数2の初期化された配列変数になる。
ただ、メンバ変数に後から代入するのが面倒なので、初期化時にそこまで済ませておきたい。

・コンストラクタ―

コンストラクタ―:クラスと同じ名前の特殊な関数でインスタンス作成時に初期値を設定する。関数の書き方と同じだが、呼び出す際にはnewを用いる。

上記のプログラム文にコンストラクタ―を追記すると下記の通り。

ただし、このままだとエラーが出てしまう。これは、クラス型の変数に=new Person()と代入していたが、このnew Person()も実はコンストラクタで、クラスの宣言時にデフォルトで用意されていたコンストラクタである。
これが引数を二つ持つ新しいコンストラクタを定義したことで使えなくなってしまうためである。
コンストラクタは作成する際に必ずクラス名で宣言しなければならないことを考えると、2つ以上のコンストラクタを作れないように見えるかもしれない。
しかし、コンストラクタは戻り値と引数の型が異なれば、同名のコンストラクタを作ることが可能であるので、新たに引数も返り値も持たないコンストラクタを宣言してやれば問題ない。
つまり、上記のスクリプトにpublic Person(){}を追記してやればよい。
これは関数の宣言時にも同じことができる。

コンストラクタを設定したことで、Start関数内の記述を下記のようにすることが出来る。

・多次元配列→割愛

・foreach文:配列変数と組み合わせやすいように改良されたfor文
下記のように使う。

foreachでは配列の要素が順番に変数に入るため、簡単に配列変数の全要素を処理することが出来る。上の場合、1,2,3,4,5とコンソールウィンドウに表示される。

・Array.Sort関数

Arrayクラスには配列変数の操作を助ける便利な関数を持っている。その中でも、Array.Sort関数は昇順に並べ替えることが出来る関数。引数に配列を渡すことで、中の要素を昇順に並べ替え、昇順になった配列を返してくれる。

・List<T>クラス

配列変数の要素数を変えることが出来るクラス。<T>の部分を型パラメータと呼び、Lsit<int>のように記録したい方を指定する。リストを操作するための下記のようなメンバ関数やプロパティが用意されている。

メンバー働き
Addメソッド末尾に要素を追加する。
Clearメソッドすべての要素を削除する。
Countプロパティ現在の要素の数を取得する。
Containsメソッドある要素がリスト内にあるか調べる。
Sortメソッドリストを並べ帰る(※静的メソッドでないので、変数名.Sort()の形で呼び出す。
Insertメソッド指定した位置に要素を挿入する。
Removeメソッド指定した位置の要素を削除する。

List<T>の使用例は以下の通り。

Add関数で要素を決定し、Countプロパティで要素数を調べている。
Add(4)の状態であれば、最終的にコンソールビューに4が表示され、Add(32)であれば、コンソールビューには32が表示される。

ということで、とりあえずchap3まで取り組みました。
一部、飛ばした部分もありましたが、C#の基本的なところは知らないことが多いので、とても勉強になりました。特にクラスやインスタンス、コンストラクタはあまり理解できていなかったところだったので、わかりやすく解説してあってよかったです。

プログラミングの基礎知識中心で退屈なところでしたし、未知の部分やクラスなどの考え方など、理解の難しい部分も多かった割にはサクサク進められたと思うので、この調子でこの先も進んでいきたいですね。

ここまで読んでくださり、ありがとうございました。
それでは、この辺で。

Unity5の教科書7日目

今日の学習内容

  • ライト(光源)の種類
  • Raycast関数の使い方
  • Tagを使ったオブジェクトの識別
  • 効果音を鳴らすタイミングと鳴らす音源の指定
  • レベルデザイン

◇ライト(光源)の種類

  • Directional Light:無限遠から平行に光を放つ。距離に依存して光の強さが変化しない。
  • Point Light:光源から全方位に光を放つ。距離に依存して光の強さが減衰する。
  • Spot Light:特定方向に光を放つ。光の強度が距離に依存して減衰。

◇Raycast関数の使い方

Physics.Raycast関数:ある地点からRay(光線)を飛ばして、飛ばしたRayの先にコライダーがあるのかを検出する関数。銃弾やレーザービームなどのあたり判定に使ったりする。

関数の詳細は以下の通り

Raycast (Vector3originVector3direction, float maxDistance= Mathf.Infinity, int layerMask= DefaultRaycastLayers,QueryTriggerInteractionqueryTriggerInteraction= QueryTriggerInteraction.UseGlobal);

<Rayがヒットしたコライダーの位置を検出するスクリプト>

引用:Unityスクリプトリファレンス RaycastHit.point
https://docs.unity3d.com/ja/2017.4/ScriptReference/RaycastHit-point.html

ここで使われているRaycastHit変数はコライダの衝突に基づいて情報を格納します。
どういうことかというと、Raycast関数で見えない線を飛ばし、その先にあるオブジェクトのコライダーにその線がぶつかったら、そのオブジェクトの情報が入ることになります。
10行目の引数hitの前にoutとありますが、これは「outに続く変数(ここではhit)に関数の中で取得した値を入れて返してくれ」という意味があるそうです。
つまり、上述の見えない線がぶつかったらhitにオブジェクトの情報を格納してくれということを意味していることになります。
Raycast関数の引数には線の原点と線を放つ方向を指定する必要がありますが、Ray変数を使うことで、この原点と方向を同時に指定することが出来ます。

◇Tagを使ったオブジェクトの識別

Unityではオブジェクトそれぞれに特定の名前(タグ)を付けることが出来、スクリプトからもそのタグを使ってオブジェクトの判断をできます。
ScreenPointToRayを使う際、メインカメラのタグがUnTaggedになっていることが原因でScreenPointToRayが機能しないといったエラーがありました。
こういった具合にタグ付けされているオブジェクトを参照したいのに、オブジェクトがタグ付けされておらず、エラーがでるなんてこともあるので、全オブジェクトが正しくタグ付けされているのかは注意しないといけないですね。

タグの作成はEdit→ProjectSetting→Tags and Layersを選択。Tagsを展開し。+をクリックでタグの作成ができる。その後、作成したタグをタグ付けしたいオブジェクトの インスペクタ―ビュー内から選択することで、タグ付けできる。

◇効果音を鳴らすタイミングと鳴らす音源の指定

オブジェクトから音を鳴らしたい場合にはAudio Sourceコンポーネントをアタッチし使用するが、Audio Sourceコンポーネントに登録できる音源は1つしかない。
状況に応じて音源を鳴らし分けたい場合には、スクリプトから音源を指定する必要がある。
public変数としてAudio Source型の変数を定義して、スクリプトのコンポーネントから任意の音源を取り出せるようにすると、鳴らしわけが可能。

memo
RandomクラスのRange関数
→Range(a, b)でa以上、b未満の整数をランダムに返す。ある範囲内のランダムな整数を使いたいときに便利。

◇レベルデザイン

ゲームオブジェクトの生成を行う際には、生成に関する様々なパラメータを使用することになる。これらのパラメータは値を変えることで、ゲームの難易度を変えることが可能だ。
レベルデザインとは、これらのパラメータを調整して、ゲーム中の面白さを継続するように設定することである。
面白さを継続させるには、ゲームの進行に応じて難しさに変換を付ける「レベルデザイン」が必要である。

はまっている状態を「フロー状態」と呼び、プレイヤの能力と挑戦内容の難易度が釣り合っていると、フロー状態になるとのこと。
フロー状態を作り出すためには、ユーザーにとって最適な難易度の設定が重要となる。

難易度にかかわるパラメータは一括で変更することが出来たほうが都合がよい場合が多いので、それらパラメータをひとくくりにしたpublicの関数を作成しておくと便利である。

そんなこんなで、8完成したゲームがこちら。

ついに「Unity5の教科書」終了しました!
日数としては1日1章なので1週間ですが、間を挟んでしまったりたので、2、3週間かかってしまいました。
次にやる本は「UnityではしめるC#」に取り組もうと思います。
選定理由は、評判が良く、この本の次作が「Unityの寺子屋」という本らしいのですが、次作ではサンプルが収益化しやすいジャンルのゲームで、作ったアプリの収益化をする方法なども載っているので、自分の目指したい方向と合致していると思ったからです。

最終的には大規模な3Dゲームだったりを作りたいとも思っていますが、まだまだ先は長そうなので、目先の目標としてアプリとしてリリースしやすいジャンルに挑戦したいと思います。

UnityではじめるC#はもっとサクサク進んで行きたいと思います。
(できるだろうか…w)

ここまで読んでくださってありがとうございました。
それではこの辺で。

Unity5の教科書6日目

今日の学習内容

  • 3Dゲームの作り方
  • Terrainを使った地形の作成
  • タップした場所にオブジェクトを飛ばす

◇3Dゲームの作り方

ほぼ2Dゲームと同じ。座標系が3次元になっているだけ。オブジェクトを配置する際、画面をくるくる回し

ながら作業をするため、自分がどこを向いているのか見失いがちになるので、画面右上のシーンギズモを

見ながら、自分の方向を確認する。

◇Terrainを使った地形の作成

・Terrain:Unityに用意されている地形オブジェクト。山や川などの地形をペイント感覚で作成可能。テ

クスチャも作成でき、草や木などもの地面を塗るだけで塗った場所にはやすことが出来る。
・Terrainで地形の作る
起伏などは、作成したTerrainのインスペクタから、Raise/Lower Terrainボタンを選択し、その状態で起

伏を付けたい部分をドラッグするとドラッグした部分が隆起する。シフトを押しながらドラッグすると隆

起させた部分を沈み込ませることが可能。

・Terrainにテクスチャをペイント
テクスチャはテクスチャ柄のブラシを使って地形を塗るイメージで配置できる。
テクスチャはEnvironment Packageをプロジェクトにインポートすることで使用可能になる。
ツールバーのAssets→ImportPackage→Environmentを選択すると、Importing Unity Packageウィンドが表示されるので、好きなテクスチャや3Dモデルを選択しImportする。

※自分の場合はImportPackageの後の選択肢が、Custom Packageのみでした。
どうやら、現在自分が使用しているVer(2018 2.18f)ではStanderd AssetsというAssetをAsset StoreからダウンロードしてImportする必要があるようです。

Import方法:シーンビューにAsset Storeのタブがあるので、そこからStanderd Assetsと検索すると、Topに目的のAssetが出てくるのでクリック→ダウンロード→インポートと進めて、使用可能になります。

Asset StoreのStandard Assetsのページ。画像はダウンロード後のため、Importと表示されている。

TerrainのペイントからEdit Textureを選択すると、Import前にはなかったテクスチャが表示され、使えるようになっているはずです。

Import後

ただ、この方法ですと、この本のように使いたいテクスチャだけインポートするということが出来ないので、少し不便かもしれません。試せていないので可能なのかは不明ですが、本のとおり、Import PackageからインポートしたいアセットだけImportするには、Standard Assetsの拡張子をunitypackageにする必要があります。
上記のAssetのダウンロードを行うと、プロジェクトビュー内にダウンロードしたStandard Assetsのフォルダが出来ているかと思います。
おそらく、このフォルダの拡張子をunitypackageにすることが出来れば、本の通り、目的のアセットのみインポートすることが出来るようになるのかと思います。
ですので、Export PackageでStandard AssetsフォルダをStandard Assets.unitypackageとしてエクスポートすれば、ImportPackageから本通りにインポートすることが出来るかもしれません。
もし、ImportPackageにStandard Assetsが表示されていなくても、Custam PackageからImportできるのではないかと思います。
一応、Standard Assetsフォルダの拡張子をunitypackagに変えることはできたので、おそらくできると思います。

・OnCollisionEnter関数:Physicsを使ったオブジェクトの衝突時に呼び出される関数。
isKinematic:OnCollisionEnter関数内のbool型のメンバ変数。この値をtrueにするとオブジェクトの動きが停止、falseでオブジェクトが動く。

◇パーティクル:Unityではパーティクルをコンポーネントとして用意されているため、パラメータをエディタで簡単にいじることが出来る。
パーティクルを表示するにはオブジェクトにparticleSystemコンポーネントをアタッチ。
ParticleSystemのパラメータを調整して、エフェクトを作成。
スクリプトでパーティクルの再生を指定。

◇タップした場所にオブジェクトを飛ばす

タップした場所にオブジェクトを飛ばすには、タップした場所をInput.mousePosition関数で取得可能であるが、3Dではその値をそのまま使うことはできない。
これは、mousepositionの値が、スクリーン座標系の値であるからである。
スクリーン上の座標はゲーム画面上の座標を表すときに使う2Dの座標系である。実際のオブジェクトは3Dのワールド座標系であるため、スクリーン上の座標をワールド座標系に変換する必要がある。
UnityにはScreenPointToRayという関数が用意されている。これは、スクリーン上の座標を渡すと、「カメラ」から「スクリーン座標」に向かうワールド座標系でのベクトルを取得することが出来る関数である。

これを使うことで、カメラからタップ地点に向かうベクトルを計算することが可能になる。

※本のほうでは、
Ray ray = GameCamera.ScreenPointToRay(Input.mousePosition);
と記述していましたが、この部分でエラーが発生。
エラー分は以下の通り
NullReferenceException: Object reference not set to an instance of an object
igaguriGene.Update () (at Assets/igaguriGene.cs:21)

修正前

いろいろと調べてみると、MainCameraのオブジェクトをシーン上から探せていないらしいことが判明。
原因は、MainCameraのインスペクタ―画面中の「Tag」が「Untagged」なっているためらしい。これを「MainCamera」に選択すると、シーン中からMainCamaraを認識できるようになり、エラーも出なくなりました。

修正後

昔のバージョンではデフォルトでシーン中のMainCameraのTagはMainCameraだったようなのですが、2018.2からはデフォルトがUntaggedになってしまったようです。
ver2018.2以降でScreenPointToRay関数を使う場合はこの点は注意だと思います。
(このエラーを直すのに結構時間取られました…)

なんとか完成したゲームがこちら。

よくわからないですが、なぜかパーティクルがピンクになっていますw
(本来は白い光の粒のようなものになるらしい…)

今回は少し忙しかったのと、テクスチャのインポートやエラーの修正に時間を取られてしまい、予定よりも更新が遅くなってしまいました。
毎日投稿できればよいのですが、そうもいかないと思いますので、やめてしまわない程度にほどほどに更新していこうと思います。
いよいよ次はラストの8章です。
8章終了後、どういったことに取り組めばいいのかを少し調べながら考えております。
もしこの投稿を見られた方で、こんなことに取り組めばいいよというのがありましたら、ぜひコメントに残していただけると幸いです。

では、今日はこの辺で。
ありがとうございました。