Unity 星の上を歩く~完成編~
ここしばらく放置しておいた星の上を歩くスクリプトですが、ようやく完成しました。
今度はスクリプトと重力圏をコライダーで作った星があれば動く簡単なものになりました。
いやー長かった。
・・・しかしながら出来上がってみるとやっぱり単純なんですよね。
今までの苦労は何だったのかと思わされてしまう・・・。
とりあえずイーサンを改造してカプセルの上を歩いてもらいました。
本当はソースコードとか載せてみたいんですが、載せるソフトの使い方が分からなかったので、概念的なお話だけです。
まず面の上をキャラクターに歩いてもらうためには・・・というお話はこちらのページがとても参考になりました。
基本的にはほぼこれだけと言っていいです。
・・・まあ、結局それを実現するのに回り道を色々してしまったんですが。
まず、キャラクターを歩かせたい星の上に配置します。もちろん接触判定が必要なので、コライダーとリジッドボディをつけます。
リジッドボディの回転はFreezeRotationのXYZ全てにチェックが必要です。そうしないと物理エンジンで勝手に回転します。(ちなみにイーサンのスクリプトではこれをスクリプト側でロード時にフリーズさせているようです)
それからリジッドボディのUseGravityのチェックは外します。重力の方向は星の上ではキャラクターの位置によって違いますからね。
星の上に配置したら、キャラクターが最初に必要な処理は自分の立っている面の確認です。
これはStandardAssetsのThirdPersonCharacterにあるCheckGroundStatus()関数を利用すれば足元の面の法線方向と自分が接地しているかが分かります。
これで得た面の法線方向にキャラクターのtransform.upの方向を向ければ面の上に立てます。
ただし、そのままtransform.upに法線ベクトルを入れるとその次の工程が面倒臭くなります。
私はここで引っかかって泥沼にはまりました・・・。
キャラクターの上方向を決めて面上に立たせた後に、進行方向を決めるという処理が必要なんですが、これを上方向を先に決定すると旋回できなくなりました。
どうもローカル座標を特定のベクトルの向きに合わせるというだけだと全ての軸において一定の方向に決まるようで、Quaternion.FromToRotation()やtransform.upに直接入力しただけだと毎フレーム進行方向もリセットされてしまい旋回できなくなりました。
・・・もちろんやり方が悪かっただけかもしれませんが。
何にしても、もっと簡単な方法があったので、そっちの方がいいと思います。
Quaternion.LookRotation()という関数が用意されているので、これを使います。
これはキャラクターに向かせたい方向のベクトルを入れることで、その向きのクオータニオンを作ってくれる関数です。
つまり、上方向じゃなくて進行方向を決めましょうということです。
ただ、もちろんそのままだと今度は面の上に立たなくなってしまいます。
でも大丈夫。LookRotationは上方向の引数も持っていて上方向も決められるんです。
・・・ただし、進行方向に直角であることが条件ですが。
これが上手く利用できずに一度使ったのに放り投げてしまったんですよ。・・・あの時気付いていれば・・・!!
進行方向の決め方ですが、旋回の計算も全部やってから使えばいいんでしょうけど、分かりにくいので、まずは球体の上前方に進んだ時の動きを1フレーム分動かしたことを考えてみましょう。
球体なので、球体の中心に向かって重力が働いているとすると、一歩前に進むとその分中心に向かって落ちます。
そしてこの時、立っている面の法線方向も変わります。
そうすると、進む前の前方となるベクトルと進んだ後の前方となるベクトルは球体の中心に向かって落ちた分だけ角度が変わります。
ちょうどX軸でキャラクターの前方向に回した感じでしょうか。
今回、LookRotationで前方に指定しするのはこの一歩踏み出した後のベクトルになります。
その求め方は、Unityなら簡単で、進む前の前方のベクトルを進んだ後の面に投影すれば求まります。
これにはVector3.ProjectOnPlane()を使います。
これで進行方向も決まったので、LookRotationに求めた進行方向と面の法線方向を渡せば星の上に立てます。
後はもう簡単で、毎フレーム法線方向と反対方向に力(これが重力に当たります)を加えて、進みたい方向に動かせばいいというわけです。
旋回はtransform.RotateでY軸のとこだけ入れてやれば旋回できますしね。
・・・といっても、実は移動とかは少し考えてやらないと動かしにくいです。キャラクター基準にするかカメラ基準にするかとか、操作性を考えると実はもう少し改良を加える必要があります。
とりあえず、長くなったので今日はここまで。
ジャンプとかも改良しないといけないし、まだまだやることが山積みです。
でも、星の上を歩くスクリプトはようやく落ち着いた感じですね。
UnityのStealth Unity 4x をUnity5で動かす
今日はUnityのアセットを色々と遊んでいました。
今までStealthというアセットは見かけていたけど、まだダウンロードしたことが無かったので今日は試しに落としてみました。
どうもUnity4用のアセットらしく、ダウンロードしたら警告されました。
とりあえず気にせずダウンロードしてサンプルシーンを読み込んだらなんだか動きそうだったので、試しにプレイしてみたんですが・・・。
なんだか敵と思しきロボットが動かない・・・。
声をかけたり後ろを走っても全然こっちに気が付かないんです。
というよりその場から動かない。
ついでによく見てみるとコンソールにエラーがいっぱい出てる・・・。
再生を止めて調べてみたら、ナビメッシュが無かったようです。
だから動かなかったんですね。
ナビメッシュの作成はWindowでNavigationのウインドウを開いて、後はキャラクターに合わせてパラメータを調整して最後に右下のBakeで焼いたら出来上がり。
ナビメッシュを作ってもう一度起動したら敵は動いているけどまだエラーが・・・。
どうも監視カメラのコライダーにメッシュコライダーを使ってるのが原因のようです。
そこで、適当なボックスコライダーに入れ替えてやったら動きました。
ようやく動いたので試しに遊んでみたんですが、意外と難しい・・・。
ついでに敵が途中においてあるバスを貫通してくる・・・。
あのバスはstaticじゃないんですね・・・。
今回ナビメッシュの勉強にと思ってダウンロードしてみたStealthですが、ナビメッシュって球体みたいなものにも使えるんでしょうか?
使えるなら使いたいところですが、どう見ても無理っぽいしなぁ。
自前で作ることになることはほぼ確実でしょうね。
Blenderベイク機能
Blenderのベイク機能でどうにも分かりにくかった部分について。メモメモ・・・。
Blenderのベイク機能でテクスチャを作成するときに新規で画像を作って、
それにテクスチャを焼こうとしても上手くいかなかったときのメモ。
ベイクで焼くテクスチャは、焼く直前に画像エディターに表示してあるものに焼くというわけではなく、オブジェクトの編集モード中に焼きたいオブジェクトの面を選択したときに画像エディターに表示される画像に焼くようです。
・・・何でこんな分かりにくい仕様なのか・・・。
オブジェクトモードでノーマルやテクスチャ、AOとかを順番に焼こうとしてたらなぜかいつも同じ画像に焼かれてしまい上手くいかなかったんですよね。
何故か編集モードに入り、面を選択すると、その面のUVマップに対応した画像に切り替わる模様。
これは分かりにくい・・・。
UVマップを作ってなければテクスチャは切り替わらないですが、これだと当然焼けないですね。
なので、UVマップを作ってそれからそのUVマップに対応する画像を選ばないといけないようです。(無ければ新規作成)
参考の本を読みながらやって覚えたもので、手順こそ知ってましたが、内部でどういうことをしているかよくわからないで使っているとこういうことになるんです。
とりあえず、ようやくテクスチャが作れました。
打ち合い構想
Unityで剣の打ち合いを実装するに当たってMMD杯のFF再現動画にあったような感じなら出来そうですね。
攻撃を走りながら繰り出すアニメーションはAnimatorのレイヤー機能とアバターのマスクで作れそうです。
それから動画を参考にして剣の動きを見ると、打ち合ってますが、はじき返されてはいないようなので、そのままアニメーションすればよさそうです。
剣同士が当たった時にエフェクトで火花を散らして、その場合はダメージの判定が無くなるようにすればそれっぽくなりそうな気がします。
・・・並走しないと難しいですが。
問題は敵との距離感でしょうか。
スターウォーズみたいな打ち合いもやりたいですが、流石に難しそうなので、とりあえずはこんな感じで行こうと思います。
余裕があったらもっと凝った感じにしようと思います。
剣を剣で弾くアクションのアイディアについて
UnityではAnimatorを使うことで何かをしながら別のアニメーションをすることが出来るようです。
今回、剣を剣で弾くというアイディアを実装するに当たってどんな感じにしようか考えてたんですが、普通に止まったまま敵の攻撃モーションに合わせて剣を振ると敵の攻撃が弾けるというのもなんだか面白くないような気がして来ました。
それだと普通に防御するのとあんまり変わらないですしね。
もっとかっこ良くしたいと考えた時にふとWiiのゼルダのトワイライトプリンセスで、走りながら剣を振ってたのを思い出しました。アニメーション的に難しい気もしますが、走りながら剣の打ち合いとかしたら楽しそうです。
スターウォーズ的な感じになればいいですが、たぶん無理なので、もっとアバウトな感じなりそうです。
コライダーの衝突から計算して弾くのが普通な気もしますが、それだとなんだか重くなりそうです。
とりあえずアニメーションはおいて置いて、簡易アニメーションでどんな感じになるか一度作ってみようと思います。
・・・これは時間がかかりそうです。
ワイヤーアクション完成
先ほどワイヤーアクション(結局ビーム風なエフェクトになりましたが)が完成しました。
キャラクターの移動自体は簡単だったんですが、エフェクトに手間がかかりました・・・。
大したエフェクトでもないんですがパーティクルの方向がなぜか合わず、おかしな方向を向いてしまって、その修正に時間がかかってしまいました。
Transform.TransformDirectionを使ってワールド座標に・・・とかやってたんですが、
値をいろんなところに渡してるうちに段々わけが分からなくなってしまいました。
とりあえず、完成はしたものの、移動がまだ完全に出来ていないので、進めるうちに修正の必要が出てくるかもしれません。
次は剣で剣を弾くシステムを作る予定ですが、よく考えたら、これはほとんどモデルの動きがメインになる気がします。
・・・モデルまだないんですよね。
何か適当に用意するか・・・。
ワイヤーアクション導入
星の上を歩かせるのは一度おいて置いて、メールで頂いたアイディアのワイヤーアクションを導入しました。
これは進撃の巨人のゲームをUnityでつくってる人もいたからそこまで苦労しないと踏んでいたんですが、ものの見事にはまりました。
キャラクターをRayの当たったところに徐々に移動するのは簡単だったんですが、星から星へ移るときの重力の変化に時間がかかってしまいました。
・・・ただのスペルミスと符号のつけ間違いという凡ミスでしたが。
そして、重力圏にコライダーを使っていたのにRayがそのコライダーに反応しないようにするのを忘れていたので、余計に時間がかかってしまいました。
とりあえず実装出来ましたが、エフェクトが無いので寂しい感じです。
ついでに一人称の視点のせいで、結構酔いそうです。
重力は星のサイズより少し大きめのコライダーに接触した時点と離れた時点でON,OFFして重力圏に入るときだけ星の中心方向に足が向くように星のTransformを渡してます。(ポジションですね)
出るときは単にboolをfalseにするだけ。
ワイヤーアクションは、カメラをある程度操作できるように調整して、Canvasの中心にそれっぽいマークを設置。
そこめがけてRayが飛ぶようにカメラからRayを飛ばしました。
後はヒットした情報をプレイヤーの方に渡して、そのポイントと自分の位置を差し引きして出た方向に毎フレーム移動させればそれっぽくなります。
一応ワイヤーアクション中には他のポイントにワイヤーを飛ばせないようにしました。
・・・別に飛ばせても問題なさそうですが。
ある程度目標のポイントに近づいたら移動させるのを止めるようにしましたが、Rigidbodyを使う場合は単純にその方向に速度を追加してあげればよさそうですね。
・・・そういえば、物理エンジン作る必要ないから別にRigidbody使ってもよかったんだった。