No.002 進捗状況14[人に話しかける挙動]
みなさんこんにちは🌚
さて今回は以前作ったメッセージスクリプトと組み合わせてゲームのような話しかける処理を実装していこうと思います。しかしこの話しかける処理を考えてみたのですがやることが
まず
・会話可能範囲内で対象にカーソルを表示 ←この時複数のキャラが被った場合の処理も考える
そして
・カメラを会話用の位置に移動
・メッセージウィンドウを表示
・キャラ同士を向かいあわせる
と、意外に多いのでとりあえずまだわからないカメラの移動をおいといて他の機能をどうにか実装しようと思います。
カーソルの実装
話しかけることのできるキャラクターをわかりやすくするためにカーソルをまず設けました。
カーソルという空のオブジェクトの子にそれぞれ上部の逆三角錐と下部の円を置いています。地味にこの逆三角錐は初めてのProBuilderで製作したものだったりします。
unity3d.com
最近標準搭載された3Dモデリングツールです。とても簡単!
そしてこれにMessageManagerスクリプトと、対象のオブジェクトに話の内容と位置情報を格納したActiveMessageスクリプトを作成
ActiveMessageスクリプトは以前作成したメッセージウィンドウのものをちょっといじっただけですがMessageManagerスクリプトは一から書いたためスパゲッティになっています笑笑
わかりにくいので解説するとMessageManagerスクリプトでその名の通りActiveMessageスクリプトを持つオブジェクトを一括管理し、一番プレイヤーに近い会話オブジェクトと同じ座標にカーソルが常にいます。そしてカーソルオブジェクトのトリガー範囲内に入った時だけカーソルが可視化&話すことができるというわけです。製作過程でキャラの範囲が被った場合はどうしようか悩みましたがOnTriggerEnterとExitで実装すると被っている場合でもすんなり処理してくれたのでラッキーでした。そもそも実際のゲームプレイではNPCは離して配置すれば良いだけですしね。
キャラ同士を向かいあわせる
この動きがなかなか大変でした。
数学なんてここ最近ちっともやっていないので一応実装に成功した今でもベクトルだとかQuaternionだとかの理解がちゃんとできていないと思いまする。どうしてもお互い向き切った後の角度の参照の仕方がわからなかったので時間で管理しました。一応2秒あればどんな角度でも向けるはずなので問題ないです。実行すると...なんとかできました!!
ずいぶん時間が空いた&リアルが忙しかったですがなんとかまた一つ実装に成功しました。次回以降はいよいよゲームシステムの大枠に移っていきたいと思います。
No.002 進捗状況13[ジャンプする箱]
みなさんこんにちは🌚
では今回は現在進行中のプロジェクトの最後(の予定)のオブジェクトを作っていきたいと思います。次回以降はゲームの中身的なものを作っていきます。
ジャンプする箱
速く動いてやりたいスタイリッシュなことというわけで考えた結果、落ちる崖やガレキの上を飛んでわたるというアクションを実装することにしました。イメージとしては下の感じまあ加速とは関係ないですがイメージということで
まずはいつも通りBoxを用意
目の前には飛び乗るためのジャンプパネルを配置
さらに飛んで渡るためにボックスを連続して配置し、その上にジャンプパネルこの長いボックスはプレハブ化しておきます。そしてジャンプパネルはもうあるのでこのボックスの動きを制御するスクリプトを作成
重力の適用を遅くするという挙動はなかなか実装方法が思い浮かばなかったので代わりにこの箱のみRigidbodyではなくAddforceによる重力の実装をし、この値を変えることで重力の変化を表現しました。しかし絶対にもっと良い方法があるはずなので少し不満が残りますね。まあさっさと作るために今回は仕方ないです。また今度勉強しましょう。さあ動きを確認すると...
だいぶイメージっぽい感じにできました!!無駄に3つのアングルから撮ってみました。
でもジャンプパネルに乗った時の挙動が一回ごとにやけに前に飛んだり逆に飛ばなかったり安定しないんですよね。一番健闘できた動きがこれなので今回はこれまでにしておきますがまだまだ改善の余地はありそうです。
No.002 進捗状況12[RPG的なメッセージウィンドウ]
みなさんこんにちは🌚
今回はオブジェクトではなく、RPGゲームでよくある会話ウィンドウを実装したいと思います。といっても、例によってこちらのサイトの方法を実践するだけなので、こちらをみてもらった方がとてもわかりやすいです。かめくめちゃんさんには毎回お世話になってます😊
gametukurikata.com
まずは最初にある通りキャンバスに色々配置。
MobileJoyStickもキャンバスなんだけどいいのか。いや、とりあえずやってみよう。操作とメッセージは同時に表示しないからあとで切り替えれば大丈夫だろう
次にメッセージスクリプト作成。勉強のため中身を謄写することを試みましたがUpdate()メソッドの中で迷子になったためそこだけコピペしたのは内緒。
これを全部手で写しましたなどと言えばコメントアウトまで綺麗に写したのかと褒められるか見破られるかの2択でしょう。
Updateメソッドの途中でこんがらがってしまったのですが用意した変数や他のメソッドの中身とサイトの記述から大体の仕組みは理解できたと思います。特に最後のSetMessagePanelはこのスクリプト内では呼び出されないものの他のスクリプトから呼び出す際に便利なよう設計されているのは勉強になりました。普通のことかもしれませんが私の中にはなかった概念です。
そしてこれを呼び出すゲームオブジェクトを作ります。
空のゲームオブジェクトに次のスクリプトをアタッチし、今回はmキーで会話を呼び出してみます。実行してみると...いやすごいですね。ですが今回作りたいゲームは縦画面なのでUIの構成とかを調整していく必要がありそうです。では今回はここまでにしておきます。
No.002 進捗状況11[NavMesh]
みなさんこんにちは🌚
一口サイズに材料を切るのが苦手なブルーノです。
では今回も新しいオブジェクトを作っていきたいと思います。
ところで最近Youtubeで仮面ライダーカブトの動画を見たんですが、これも今私が作っているゲームと同じく時間を圧縮した中で敵との戦いを繰り広げるといった内容で、とてもかっこいいんですね。というか、このゲームの元ネタはぶっちゃけこの仮面ライダーカブトです。そして仮面ライダーには敵がつきもので、このカブトの敵も超高速で動くため常人には捉えられないんですね。というわけで、今回作るオブジェクトは「超高速で動き回る敵」にしたいと思います。そして動かす敵は、街を作った際にノリでストアから手に入れたこの人にしようと思います。
にしてもなんでこのゴリラおしゃぶりしてるんだろう。では頑張っていきます。
NavMesh
昔Unityの勉強の記事で少しだけ触れたNavMesh、自動で歩ける道を判別しその上をAIが勝手に動いてくれるという代物を今回は使いたいと思います。こちらのサイトを参考にしました。というか、まんまこのサイト通りです。毎回お世話になっています。kanさん。
kan-kikuchi.hatenablog.com
まずはテスト用のフィールドと、ゴリラを配置。
Window→AI→Navigationを開き、Objectタブから歩かせたいエリアに該当するオブジェクトを選択し、NavigationStaticにチェック。
NavigationAreaは[Walkable]を選択しておきます。
準備ができたらBakeしましょう。そしたら今度は、ゴリラにNavMeshAgentというコンポーネントをつける。これだけ。なんて簡単なんだ。
動きを速くするため、SteeringのSpeed, AngulerSpeed, Accelerationを、アホみたいに速くしてみました。これらはそれぞれマリカでいうスピード、曲がりやすさ、加速ですね。
あ、さきほどこれだけと言いましたが、最後にスクリプトから目的地を設定してあげる必要がありました。嘘ついてごめんなさい。
しかし目的地の設定も、NavMeshAgent.destinationにVector3型の座標を指定するだけ。そこで今回は、目的地をこんなオブジェクトにしてみました。
コライダー だけのCubeを用意し、時間経過もしくはゴリラが触れることで特定の座標を移動する目的地です。
これでゴリラが常にある目的地を目指して走り出すはず.....とおもったんですが......
ゴリラが恥ずかしいことになったまま走り回ってるんですが.....原因を調べてみると、どうやらこのアセットにもともとついていたAnimationが、NavMeshと競合してしまっているようです。
NavMesh Agent を他のコンポーネントと共に使う - Unity マニュアル
NavMeshAgentは独自のPhysicsとAnimationコンポーネントを持っているらしく、そのまま一緒に使うと競合を起こしてしまい正常に機能しないようです。ちなみに競合というのは複数のプログラムなんかが同じデータを使おうとして競り合ってしまうことです。まあゴリラがブルブルするアニメーションは今回いらないのでアニメーションは今回は捨てることにしました。Animationコンポーネントを外すと...
直りました。が、今度はまた別の問題が。ゴリラが速すぎてプレイヤーの当たり判定が貫通してしまいました。
どうやらこれは物理演算の関係上速い動き全てを計算すると負荷がかかってしまうのでコマ送りになってしまっているそうです。というのも全てこちらのサイトに書いてあったんですよね笑
【Unity】物理演算で動かすオブジェクトが壁を貫通する問題と対策 - テラシュールブログ
というわけでゴリラにRigidbodyコンポーネントをつけてCollision Detectionを[Continuos Dynamic]にします。ちなみにIs KinematicにチェックをつけないとNavMeshAgentと競合を起こします。
そして...成功しました。今回はここまでにしておきます。
No.002 進捗状況10[オブジェクトプーリング][ビルボード]
みなさんこんにちは🌚
ステファノス・チチパスってなんか口に出したくなっちゃうよね。ブルーノです。
では今回もオブジェクトを製作していきます。
今回作ろうと考えたのはズバリ「雷」。雷を避けるなんてかっこいいですよね。というわけでこれを作成していこうと思います。
雷ってぐにゃぐにゃしてるから3Dモデルを用意したらその表現がとても難しいしめんどくさそうですよね。というわけで今回はまずこの雷の表現に「ビルボード」という技法を使いたいと思います。
ビルボード
ちょっと昔のゲームをやっていると時々かなりグラフィックが写実的なのにどこからみてもその面しか見えないオブジェクトとかありますよね?これはビルボードという技術で2Dの見た目のものを常にカメラの方を向かせることで立体感を出す技法で、3Dモデルの節約ができます。
nn-hokuson.hatenablog.com
こちらの方がとても詳しく解説しています。というかこれ見て作りました🌝
まずは背景を透過させた雷の画像をインポート
背景の透過仕方は
mtimsno.hatenablog.jp
こちらに詳しく載っています。
そして新しく作ったQuadオブジェクトに適用。名前はLightningにしときました。見た目はペラペラですがコライダーは普通にCapsule Colliderを使っているので当たり判定はあります。
そしてビルボードのスクリプトを作り、Lightningにアタッチ。
常にカメラの方を向くようになりました。良かった良かった。
しかしこの雷、実際に光を発しているわけではないので日陰だととても暗くなってしまうんですよね。
オブジェクトへの光の当たり具合や見た目の影響を管理するのはマテリアルのエミッション(Emission)が関係しているようなのですがこちらのサイトを参考にしてみたもののUnityのバージョンが違うためかメニューが変わっていて記事通りにいかなかったです。
[Unity]色を失わないオブジェクト | KENスクールブログ
しかたないのでオブジェクトの目に前に光源を置くという強硬手段に。そして下に降る動きと地面の下に入ったら消えるようスクリプトで制御します。ちゃんとタイマーで遅くできるようpublicなスピードの値も導入。ただ落ちるだけだと物足りない気もしたので34行目で地面に落ちた時に光っぽいパーティクルも発生させました。
しかし、これが後述するオブジェクトプーリングというあらたな壁に大きく関わってくることになるのです。
オブジェクトプーリング
さあさっき作ったLightningを生成するスクリプトを作ってたくさん雷を降らせるぞーと思い、こちらのジェネレータースクリプトを作ったところ....
お、重い。。。。
全くゲームプレイができないわけではないですが結構な頻度で画面が角つきました。パソコンでこれならスマホはどうなってしまうんだ....
どうやら先ほどスクリプト内で頻出していたInstantiate()メソッドが原因で、新たにオブジェクトを生成する作業は負荷が大きいそうです。でもこの量でもこれだけカクつくのにシューティングゲームとかはどうやってあれだけの弾を動かしているのでしょうか。
そこでオブジェクトプーリングという技法の出番というわけです。
【Unity】オブジェクトプーリングでオブジェクト節約術 | Unity | DoRuby
こちらのサイトを参考にしました。どうやらオブジェクトをゲーム開始時にたくさん作っておき、そのアクティブ/非アクティブを切り替え使い回す方法のようです。なるほど。
では実際にスクリプトを書いていきます。var型とかforeachとか自分では全然使わないから理解が大変だ😵😵😵
オブジェクトプールのスクリプトはリストの生成と取り出し周りだけなので全く同じ記述で良いですね。
こちらの雷生成スクリプトは大幅な変更が余儀なくされましたが、おかげでオブジェクトプールの仕組みと使い方がよくわかりました。使用する際はGetObject()メソッドのみなので楽ですね!
一応雷のスクリプトもオブジェクトプールの仕様により用済みになったら非アクティブにするように変更。このスクリプトの22行目で世界時間をかけているので加速に伴って雷のスピードが1/10になるのは当然なのですが雷の生成も遅くなるように前の雷生成スクリプトの51行目でも工夫してあります。
結果は....
成功!!
雷の中を加速して避けるのはなかなか面白いですよ。さあゲーム内容が面白くなってきた!!今回はここまでにしておきます。
No.002 進捗状況09[ワープするチェックポイント]
ペルー/クスコ -レインボーマウンテン-
みなさんこんにちは🌚
隻狼というゲームが気になっているもののゲームしている暇もお金もなくて動画をみてしまいたい欲と葛藤するブルーノです。ゲーム動画って100%ネタバレだから見るかどうかすごく悩みます。
では前回に続き今回は通過したら次の地点まで移動して現れるタイプのチェックポイントの作成に移りたいと思います。
前回のものとの違いは
- 触れてもオブジェクトは消えない
- 出現するための座標・角度を複数格納できる
- 触れると次の指定された座標に再び現れる(最終地点の場合は消える)
といったところでしょうか
このチェックポイントは前回のCheckPoint02の中身を改良してその結果を分岐させようと思います。
長くなってしまいましたがようやくできた...!!
本当に時間がかかってしまいました。この記事の投稿が遅れた原因の8割はこのスクリプトで詰まっていたからといっても過言ではないです。気分転換すると突然解決策が浮かぶことってありますよね。
当初の予定通り、次に現れる位置と向きを格納する配列を2つ作り、コライダーがプレイヤーに触れると次の予定された座標に移動、回転し、もし次の座標がなければクリアフラグを立てる。といった風になりました。
52行目のMoveCheckPoint()関数はアニメーションから呼び出しています。今回はこのアニメーションの途中で関数を呼び出せることを学ぶことができました。結果は。。回転もうまく反映させてることがわかるようにイーサンに対して違う向きを向いている写真を撮ってみました。イーサンも感動のあまり立ち尽くしてますね。
試行錯誤の途中はアニメーションが変なことになったりスクリプトが無駄に3枚に増えたり大変でした。こうして一つのスクリプトに収められたのはとても良かったです。
オブジェクト一つ作るのにこれだけ時間がかかってしまうのはとてもまずいですね。もっと簡単な形にしてペースを上げていこうと思います。
No.002 進捗状況08
みなさんこんにちは🌚
キングダムハーツ3やApex Legendsに最近はまっていてPS4の家庭内勢力がSwitchを上回ってきているブルーノです。PSの圧倒的なグラフィックは定期的にみたくなりますね。
では今回もオブジェクトを制作していきます。
移動するチェックポイント
今回はキャラが触れた時に消えるようないわゆるチェックポイントを作りたいと思います。イメージとしてはゼルダの伝説ブレスオブザワイルドの光の輪くぐりの感じですまず簡単に見た目だけ作ります。この中をくぐることにします。
そして今置いたオブジェクトたちにはデフォルトでコライダーがついていますが彼らにぶつかる必要はあまりないので取り除き、逆に空のオブジェクトに適当なコライダーを通過した判定のため追加しておきます。
大きさを変更し、Is Triggerにチェックをつけます。これで物理的な干渉をせずに当たり判定を行うことができます。
今回実装する感じとしては
- ただ触れた瞬間に消える。
- 座標を格納する変数を任意の数指定し、触れたら次の座標に現れる
という二つの方法を考えつきました。
後者はまんまゼルダのイメージですね。実装が簡単なのは間違いなく前者ですが、今回は両方作りたいと思います。
触れた瞬間に消える
これは簡単ですね。コライダーが当たりを感知したらDestroyするようにすればOKです。が、いきなりパッと消えると変なのでアニメーションでとても小さくしてから消します。
dreameaters5239.hatenablog.com
アニメーションの参考過去記事わかりにくいですが、0.3秒でちょっと大きくなり、0.5秒までで小さくなって消えるアニメーションです。こんな風にスクリプトを書いてみました。ついているAnimatorの取得とコライダー反応時にアニメーションを再生する動きのみとりあえず記述です。再生してみると
一応できたのですが、アニメーションがループ再生してしまいました。これでアニメーションの方はOKですが、まだオブジェクトを消す事と触れたことを知らせるフラグを実装することが残っています。というわけでスクリプトを改良します。
アニメーション後にオブジェクトを消す
簡単そうに思えましたが意外にネットに方法がなかったので、アニメーションウィンドウにあったこれを利用してみました。
アニメーション内でスクリプトのアクティブ化・非アクティブ化を操作できるみたいです。これでオブジェクトを消す下のスクリプトを有効化します。フラグについて
ゲームにおいてフラグというのは欠かせない存在ですよね。しかしこのフラグ、どういう風に実装するのがゲーム作りにおいて主流なのでしょうかね。独学なのでいまだによくわかりません。今回はこのCheckPointScriptの中でbool値を操作し、ゲームシステムのスクリプトでそれを検出するという風にしようと思います。これで検出できるはずです。記事が長くなるので今回はここまでにして次回移動する機能の実装を作りたいと思います。
キングダムハーツ3のシークレットムービー、気になる内容ばかりでしたねえ〜〜😄結局黒い箱とマスターオブマスターは出てきませんでしたが、次回で深く関わってきそうですよね。Verum Rexの存在も新しく今後に関わってくるような描写もあってせっかくゼアノートを倒したのにもう世界観が広がりまくりでソラたちの冒険は終わらなそうです。まだまだキンハーは楽しめるコンテンツとして続きそうで楽しみです😍