221Games開発記録

痔と腰痛に苦しみながらゲームを作った記録

第九話 伝えたいことがある

ProBuilder様はすばらしいです。

これは重心位置を物体の原点にする素晴らしいボタンです。

f:id:kaninoyokonov:20180705021755p:plain

これは物体のTransform三要素すべてを0,0,0に設定してくれる神のようなボタンです。

f:id:kaninoyokonov:20180705022006p:plain

ProBuilder様はすばらしいです。無料です。いますぐUnityをダウンロードして使いましょう。

blogs.unity3d.com

 

おわり

第八話 ProBuilder様は偉大です。

.Liveの14時間リレーの視聴中、手が暇だったので壺を5周したりUnity2018をインストールしたり牛巻にお便りを読んでもらってめっちゃビビったりしていた(ありがとうございました)。ついでにProBuilderで遊んだのでちょっと書く。

 

ProBuilderって何

これ

assetstore.unity.com

Unity2018から標準装備になったそうなので、AssetStoreに取りに行かなくてもパッケージマネージャという項目から装備する事もできる。

つくった

説明書を読まずに作業した。こういったメカを作るなら普通にBlenderやCADソフトを使った方が早いんだろうけど、なんでも作れるよという事で…。

f:id:kaninoyokonov:20180701004722p:plain

悲しみ

あれ~おかしい。

白いCubeが世界の中心に存在してるんだけど、コックピットの部品の座標を0,0,0にして作業をしてたのにパーツの中心位置がおかしい。DOUSITE・・・?

f:id:kaninoyokonov:20180701005855p:plain

発覚

なるほど~~~~ProBuilderが生み出したCubeのピボット位置はここか~~~~~~~~。

f:id:kaninoyokonov:20180701010222p:plain

対策

というかProBuilderでキャラ作るなんてあんまり無いだろうから割とどうでもいいんだろうけど一応どうすりゃいいのか書いとく。

ProBuilderが産み落としたCubeのTransformをいじって、良い位置に置いたらCenterPivotを押す。

f:id:kaninoyokonov:20180701011011p:plain

すると今の座標が0,0,0になる。やったぜ。でもミラー機能を使う事があるならやらない方が良いかも。というかそういうのを作るならBlenderを使え!

ProBuilder様はすばらしいです。

冗談抜きですごい機能です。ちゃんと使いこなしましょう。

blogs.unity3d.com

 

おわり

 

第七話 Behavior Designer⑤

【注意】この記事は「とりあえず動いた」を記録するものです。記されている内容は、正しい用法ではない可能性があります。

 

ハウディ~~~~

Steamのサマーセールで脳や財布がユルユルになっているのでBEHAVIOR DESIGNER TACTICAL PACKを買ってしまった。

assetstore.unity.com

買ったのでこれを作った。

youtu.be

視界内に入ると敵が追ってきて一定の距離になると足を止めて撃ってくる。

これを作るためにやった事を書いておく。何がどうなっているかという説明はできない(知能ZERO)。各自買って試して欲しい。

 弾を撃つ

EnemyにGunとBuller Spawn Posを追加した。

f:id:kaninoyokonov:20180627220408p:plain

f:id:kaninoyokonov:20180627220132p:plain

Attackタスクを使うだけで追跡と射撃をしてくれるんだけどちょっと準備が要る。

弾を撃つにはShootable(TacticalPackに付属)とかいうコンポーネントが必要。こいつをEnemyに追加した。

Attack Distanceは射撃開始する時の対象との距離。Repeat Attack Delayは射撃間隔。Attack Angleは撃てる角度のこと(?)。0にすると全然撃たないし360にすると真後ろに居ても射撃が開始される。

このままだとEnemyの中心から弾が生まれてしまいロクな事にならないしGunの先端にあるBuller Spawn Posから弾を出したいのでShootableをちょっと改造してBuller Spawn Posを選べるようにした。

f:id:kaninoyokonov:20180627215645p:plain

こういうのを書き足して

public GameObject BulletSpawnPos;

適当に取得して

BulletSpawnPos = transform.Find("Gun/BulletSpawnPos").gameObject; 

 元からあるInstantiateに細工をする。

GameObject.Instantiate(bullet, BulletSpawnPos.transform.position, BulletSpawnPos.transform.rotation); 

 これで弾の出現位置を指定できた。

BulletはTacticalPackの付属品をそのまま使った。BulletにはBulletというコンポーネントが装備されており、こいつの数値をいじると威力や弾速を変更できる。

f:id:kaninoyokonov:20180628000543p:plain

これで良しと思ったけど、ターゲット以外の物にぶつかった時に弾が消えないっぽかったのでif文の所にelseを増やしてDestroy(gameObject);を付け足した。

f:id:kaninoyokonov:20180628000938p:plain

 

次に被弾可能なオブジェクトにHealth(TacticalPackに付属)とかいうコンポーネントを追加しないといけない。というわけでPlayerに装備した。HPとかもここで設定できる。こいつは改造していない。

f:id:kaninoyokonov:20180627222216p:plain

 

Attackタスクの設定。敵をタグで指定できる。ほかの項目は試していないでち…。こいつ単体で追跡してくれるんだけど、速度や加速度を設定する項目は無い。改造して追加しようとしたけどちょっとよくわからなかった。C#に詳しい人なら出来ると思う。

f:id:kaninoyokonov:20180627222435p:plain

とりあえずこれだけで「近づいて射撃」してくる。

 ツリーにする

こいつを前回までに作ったツリーに組み込む。クッソ汚いツリーになった。おそらく無駄な部分がいくつかあるけど動いたのでよしとする。新要素を黄色で囲んである。Can See Objectは調整して1つ減らした。

f:id:kaninoyokonov:20180627231400p:plain

Seekが変な所にいるけどこいつを使ってAttack中の速度と加速度を変えている。つまりWanderより速度と加速度を高くしてある。追跡はAttackがやってくれる。

 

まず下側にAttackを含むParallelのグループについて。Parallel子タスクを全部一斉に実行してくれる。それ以外はSequenceと同じで、いずれかからFalseが返ってきたら実行が中断される。同じ感じでParallel Selectorとかいう奴もいるらしい。

詳しくはこちらの記事を読んだ方が良い。

qiita.com

 

Rotate Towardsを使ってPlayerの方向を向こうとしているけどAttackがやってくれるので多分いらない。なぜ追加したのかは覚えていない。たぶん旋回速度が欲しかったんだと思う。

 

Rotate Tow Childとかいうタスクを作った。作ったと言ってもRotate Towardsの中身をコピーしてちょっと改造しただけ。こいつはGunを敵の方向に向けるための物。

こういうのを書き足して

public GameObject ChildObject;

transform~になっとる部分をChildObject.transform~に変えたら動いた。適当に置換すると余計な部分まで置き換わってしまうので内容を読みながら作業した方が良い。

f:id:kaninoyokonov:20180628001225p:plain

設定はこんな感じ。ほぼRotate Towardsの内容だけどChild Objectが増えてる。Child Objectに回転させたいオブジェクトを選ぶ。Targetにターゲットとなるオブジェクトを設定する。Rotate EpsilonとMax Look At Rotation Deltaについては文字で説明しづらいので実際に色々な数字をいれてみてほしい。

f:id:kaninoyokonov:20180627230705p:plain

 

そして先ほど作ったAttackがある。Parallelのおかげでこの3つが同時に実行される。少なくともAttackしながらRotate Tow Childすれば正しく動くと思う。

 

次に右側のParallelについて。こっちでは元々あったWanderRotate Tow Childを同時に実行している。

Rotate Tow Childを使ってGunの向きを親であるEnemyと同じ向きにするようにした。Vector3の変数を作って、EnemyのTransformのeulerAnglesを入れた。名前はParentDirectionにした。

f:id:kaninoyokonov:20180627232542p:plain

Rotate Tow Childタスクの設定。Targetは無し。Target Rotationにさっき作ったParent Directionを設定した(Targetが存在しない場合Target Rotationの方向を向いてくれるらしい)。

f:id:kaninoyokonov:20180627232827p:plain

Wanderは前回までと同じ。

 

これで動画の通りの動きになるはずだ!!!!皆も試してみてくれ!!!!

おわり!!!!!!!!

第六話 Behavior Designer④

【注意】この記事は「とりあえず動いた」を記録するものです。記されている内容は、正しい用法ではない可能性があります。

 

今回はEnemyをPrefab化する話をします。

 

  • Prefab化するぞ

しました。

f:id:kaninoyokonov:20180623232344p:plain

すると…

SeekやCan See ObjectのInspectorをみるとTargetがNoneになっとるやんけ!!!!

f:id:kaninoyokonov:20180623232502p:plain

Scene内のPlayerをTargetにすると怒られます。

f:id:kaninoyokonov:20180623233422p:plain

というわけでツリーの中に「追跡対象を取得する」を実装しよう!!!!

  • 変数をつくる

Variablesから変数をアレできます。今回はPlayerというGameObjectをゲットしたいのでGameObjectを選びます。名前はPlayerObjectにしました。

f:id:kaninoyokonov:20180623234108p:plain

Addを押すかName欄でエンターキーを押すと追加されます。

f:id:kaninoyokonov:20180623234517p:plain

  • Playerを取得する

という訳でタスクを追加していきましょう…なんか見覚えのある名前がたくさんありますね!!!!

f:id:kaninoyokonov:20180624000203p:plain

今回は大人しくGameObjectのFindを選びます。

Game Object Nameの欄には取得したいGameObjectの名前を入力しましょう。今回はPlayerと入力します。次にStore Valueを先ほど作ったPlayerObjectに指定します。これでPlayerと言う名前のGameObjectをPlayerObjectに格納してくれるようになりました。

f:id:kaninoyokonov:20180624000514p:plain

このタスクを一番初めに実行してほしいので、Sequenceの一番左に設置します。これでPlayerを取得してからほかの処理が実行されるようになったぞ!

f:id:kaninoyokonov:20180624002333p:plain

これで完成…と言いたいところなんだけどもうちょっとだけ付き合ってくれ!

  • おまけ:視界の問題

この状態でPrefabをいくつか配置して追いかけっこしてみるとお分かり頂けると思うんだけど、EnemyがEnemyによって視界を遮られるので、Enemyの後ろのEnemyが追跡を止めてしまう問題が起こります。

なので、第四話でちょっと話した気がするIgnor Layer Maskを使ってEnemyはEnemyを透視できるようにしましょう。やり方は簡単というか皆様お察しの通り透視できるLayerを選ぶだけです。

まずEnemyにLayerを指定します。今回は適当にEnemyというLayerを作りました。

f:id:kaninoyokonov:20180624003039p:plain

次にすべてのCan See ObjectIgnor Layer MaskEnemyを追加しましょう。

f:id:kaninoyokonov:20180624003313p:plain

これでOK!!!!!!!!縦に並んで追ってくるようになった。

f:id:kaninoyokonov:20180624004030p:plain

これでAIっぽいものが組めました。

次回のネタは考え付いていません。お疲れ様でした。

みんなもBehavior Designerを買って楽しいAI製作ライフをおくろう!!!!

 

 

第五話 Behavior Designer③

【注意】この記事は「とりあえず動いた」を記録するものです。記されている内容は、正しい用法ではない可能性があります。

ハウディーーーーーーーーーーーーーーーーーーーーーーーーー今日も元気にツリーを作るぞ!!!!!!!!

 

  • タスクを追加してツリーを改造しよう

今回は前回作ったツリーを改造して、「視界内にターゲットが居ない場合、マップ上を散歩する」ようにします。さっそくタスクを追加していきましょう。

早速SelectorをRepeaterとSequenceの間に追加し、Wanderを追加してSelectorにつなぎましょう。↓こんな感じになる。

f:id:kaninoyokonov:20180623000837p:plain

ついでにSequenceのAbort TypeBothに変えると、これだけで動く。以上!作業完了!お疲れ様でした!

  • 説明

SelectorはSequenceと同じく子タスクを左から順番に実行してくれますが、Falseが返ってきた際に右隣の子タスクを実行してくれます。今回のツリーでは、CanSeeObjectがSequenceにFalseを返した場合Wanderを行ってくれます。

という訳で実行中の子タスクがTrueのとき次の子タスクを実行するSequence実行中の子タスクがFalseのとき次の子タスクを実行するSelectorを組み合わせてツリーを作っていくことになります。もちろんこれらのタスクにTrueかFalseかを返すタスクも必要です。今回はCanSeeObjectしか使ってないけどね。

Wanderは勝手にマップ中をうろうろしてくれるすごい奴です。使い方に関してはInspectorを見ていただいた方が早いと思います。一方で指定の経路をパトロールさせたい場合にはPatrolというタスクを使います。今後使うかもしれません。

SequenceのAbort TypeBothに変えた件に関しては、超絶ふわっとした事を言う感じになってしまって申し訳ないのですが、タスクに表示される矢印のアイコンとタスクの位置が関係してるんじゃないかと思い始めています。前回はSequenceから見て下にあるCanSeeObjectとSeekに遷移するだけでよかったので↓矢印が表示されるSelfでよかったのですが、今回はSequenceの右隣にあるWanderに遷移する必要が出てきました。なので↓矢印と→矢印を兼ね備えたBothを選択することで正しく動作することが出来るようになったのではないかと考えています(この記事はBehavior Designerを初めて1週間も経っとらん奴が書いています)

  • おまけ

CanSeeObjectを増やして視界範囲をそれっぽくしてみたよ。Selectorを使って1つめの視界がFalseのとき次の視界の判定に遷移するようにしたよ。いずれかの視界からTrueが返ってきたとき、SequenceによりSeekが実行されるよ。また、Abort Typeは遷移すべきタスクが下にも右にもあるのでBothにしたよ。しかしLower Priorityでも動作する事が判明。その上この状態でSequenceのAbort TypeをLower Priorityしても問題なく動作した。ちょっとよくわからない。

f:id:kaninoyokonov:20180623010609p:plain

謎が深まりまくるBehavior Designer。使い続ける事で理解できる日が来るのだろうか。

という訳で「動いたけどなんで動いてんのかいまいち理解していない話」でした。次回はEnemyをPrefabにした時のアレを書くかも。

第四話 Behavior Designer②

 【注意】この記事は「とりあえず動いた」を記録するものです。記されている内容は、正しい用法ではない可能性があります。

 とりあえず簡単なツリーから作っていきたいと思います。

長くなる可能性があるのでお好きなバーチャルユーチューバー等の雑談を聞きながら作業される事を推奨します。

 

  • マップを作る

適当に作ってNavmeshを焼いておこう!!!!

f:id:kaninoyokonov:20180621221131p:plain

  • プレイヤーキャラを作る

セールで買ったPlayMaker(これも積んでた)をここぞとばかりに使いました。プレイヤーキャラというかWASDとかで動く物なら何でもいいと思います。

名前を"Player"とします。

f:id:kaninoyokonov:20180621222057p:plain

  • AIを適用するキャラを作る

適当な箱にしました。何でもいいと思います。

NavMeshAgentを装備するのを忘れないでね!パラメータはお好みで。

名前を"Enemy"とします。

f:id:kaninoyokonov:20180621222852p:plain

  • ツリー製作をはじめる

Enemyを選択した状態でBehavior Designerのウィンドウを開くとこんな感じになってると思います。

f:id:kaninoyokonov:20180621223620p:plain

何もない所を右クリックして新しいタスクを追加しましょう。何を追加すりゃええのという話なんですけどとりあえずRepeaterでも置いておきましょう。タスクを召還すると、一緒にツリーのスタート地点となるEntryも現れます。Repeaterの説明は後でします。

f:id:kaninoyokonov:20180621224045p:plain

手始めに「視界内にターゲットがいたら追跡する。視界内にターゲットがいなければ何もしない」ツリーを作ってみましょう。

とりあえずSequenceを追加します。

f:id:kaninoyokonov:20180621225409p:plain

さらにCan See ObjectSeekを追加します。Seekの代わりにFollowとかでもいいと思います。名前が分かっていればTasksの検索窓に名前を打ち込むと出てきます。右クリックして頑張って探してもOKです。

f:id:kaninoyokonov:20180621225653p:plain

次にタスク同士をつなぎます。タスクの上下の出っ張りを引っ張ると線が出てくるので良い感じにつなごう。

f:id:kaninoyokonov:20180622002323p:plain

ツリーができた!

  • タスクの設定をする

お察しの通りこのままでは動きません。まずCan See Objectの設定から始めましょう。これまでにUnityでInspectorと格闘しまくってきた人には何も難しくないと思います。

Can See Objectを選択して、Behavior DesignerのInspectorを開くと次のような項目が現れます。とりあえずTarget Objectさえ指定しておけば動きます。今回はPlayerが視界内に入った事を検知したいのでScene内のPlayerを指定します。後はマップのサイズ等に合わせて視界を調整しておきました。Ignor Layer Maskを指定すると、透視できるオブジェクトを指定できます。今回は指定していないので、地形で視界が遮られることになります。ちなみにUnity側のInspectorでBehavior Designerの項目を展開しておくとScene画面内に選択中のオブジェクトに与えられた視界が表示されます。閉じると消えます。

f:id:kaninoyokonov:20180622003403p:plain

次はSeekの設定をします。Targetを指定してあげるだけで動きます。今回はPlayerを追跡したいのでPlayerを指定。スピードや到着したと見なされるターゲットとの距離なんかはお好みで決めて遊んでください(加速度の項目がここにないのはなんでだろう…)。

f:id:kaninoyokonov:20180622004848p:plain

だいたいできました。

次にSequenceの話。この辺の理解が一番面倒くさい。カルネージハートパンドラプロジェクト等のゲームを遊んでいた人はYES/NOで命令の行き先を変えていたけどこいつはちょっと違う。

Sequenceは自分の下にあるタスクを左から順番に実行して、Trueが返ってくれば右隣の次のタスクを実行してくれる。そしてFalseが返ってきた時点で一番左のタスクに戻る。(戻るわけじゃなくてFalseになるだけな気がする。以下の画像のコメント欄にも「右のタスクに戻る」って書いちゃったけどこれは今回のツリーに限った事であって、Sequenceそのものの機能がそういう事ではないはず。 2018/06/23追記)たぶんツリーを作りまくって体で覚えたほうが早い。

それとAbort Typeというやつを設定しなきゃならない。正直この辺をよく理解せずに先人たちのブログを見ながらこの記事を書いているし、この辺の説明をするにはツリーが小さすぎる。だからここでは、起こった事だけを書いておく事にする。たぶん次の記事でちょっと触れる。今詳しく知りたい人はこの記事のケツに参考にさせて頂いた記事へのリンクを貼っておくのでそっちを読んで欲しい。

とりあえずNoneのままだとCanSeeObjectがFalseを返したきり何も起こらなかった。どうやらCanSeeObjectが再評価されないらしい。このままだと例え視界にターゲットが入ってもCanSeeObjectはTrueを返せない。

という訳でSelf(↓のアイコンが付く)にしてみる。この場合期待通りの動作をしてくれた。ターゲットが視界内にいる場合追跡を行い、視界内に居ない場合は追跡を行わない。

ついでにLower Priority(→のアイコンが付く)にしてみた。すると一度追跡が始まるとターゲットが視界内から居なくなっても追跡は終了しなかった。CanSeeObjectが再評価されていないっぽい?

ちなみにBoth(↓と→のアイコンが付く)はSelfとLower Priorityを合体させた物らしく、これはSelfと同じ動作になった。

f:id:kaninoyokonov:20180622005926p:plain

Sequenceの項目を書いていてだいぶ疲れたので後はRepeaterをサクっと設定して完成にしたい。設定というかRepeat Foreverにチェックを入れるだけ。これでRepeater以下のタスクは無限に繰り返される。

f:id:kaninoyokonov:20180622014440p:plain

  • これで完成だ!動かしてみよう!

これは無限にCanSeeObjectがFalseを返しとる所。こんな感じで今実行しとるタスクが緑に光る。

f:id:kaninoyokonov:20180622014728p:plain

こっちはCanSeeObjectがTrueを返しているのでSeekが実行されている所。この状態で視界内からターゲットが居なくなると↑の状態に戻る。

f:id:kaninoyokonov:20180622014850p:plain

みんなのツリーも動いたかな????動いたよね????今回はここまで!!!!次回はSelectorとかいう奴が登場して、視界内にターゲットが居ない場合のタスクを作るよ!!!!

 

  • 参考にさせて頂いた記事

qiita.com

kurihara-n.hatenablog.com

imaginary.red

unitter.net

第三話 Behavior Designer①

いよいよ本題のBehavior Designerを使っていきます。

この記事は明日の僕およびBehavior Designerを買ったけど詰んどる奴に向けて書かれているためUnityの説明とかはありません。

Behavior Designerの説明もたぶんありません。「こうやったら動いた」を記録するだけです。ご了承ください。

 

  • Behavior Designerで何すんの?

ゲームに登場するキャラのAIを作ります。

↓こういうのを作ると(カルネージハートのアレではない)

f:id:kaninoyokonov:20180621172934p:plain

↓こういうのができます

youtu.be

何をしとるかと言うと

1.追跡対象(プレイヤー)のゲームオブジェクトを取得する

2.視界内に追跡対象があるかを判定する

3.無ければゆっくり散歩する

4.有れば全速力で追う

をしています。2以降がループしているので視界内に出たり入ったりする事で3になるか4になるかが変わります。

何がヤバいかと言うと一切プログラミングしとらんという点です。僕が瀕死になりながらC#で作ったRTSの敵キャラの動きが数時間で組めると思います。

  • Behavior Designer: Movement Packを買え!!!!

AIを作る上で必要不可欠な移動に関するタスクが入っている所謂DLCです。Behavior Designerではタスク(命令の中身とか分岐の中身とかのチップみたいな奴)を自作する事ができるのですが、自作の苦しみと10ドルを天秤にかけた結果、買えという結論に至りました。買え!!!!!!!!

assetstore.unity.com

  • Behavior Designerを装備しよう

ダウンロードしてインポートしたらさっそく召喚しましょう。

f:id:kaninoyokonov:20180621175024p:plain

たぶんToolsに入ってるのでEditorを押すとウィンドウが出ます。

これで準備は完了です。次回からツリーを作っていくよ~~~~!!!!