Unityで湖や海に入ったら水面を泳げるようにする

記事内に広告が含まれています。

今回はUnityのゲームで湖や海といった水面をキャラクターが泳げるような機能を作成してみたいと思います。

湖や海を作成するやり方は

Unityで湖や海を作成する
Unityのスタンダードアセットにある水を使うと簡単に湖や海を綺麗に作成する事が出来ます。

の記事を参考にしてください。

水中にカメラが入った時の表現は

Unityでカメラが水中に入った時にエフェクトを加えて映す
UnityのスタンダードアセットにあるWaterを使って水の表現が出来ました。しかしWaterは平面なので水中に入っても地上と同じようにカメラに表示されます。そこで水中に入った時はスクリプトからカメラに映る映像にエフェクトを加え、水中にいるようにしてみます。

の記事で作成しました。

今回作成する機能は水面をキャラクターが泳ぐ機能を作成しますが、水中では泳げない仕様にします。

その為、水中にカメラが入った時の表現は使わないかもしれませんね。

水中でも泳げるような機能はまた別の機会に作るかもしれません(作らないかもしれません)。

スポンサーリンク

今回の機能で使うキャラクターとカメラについて

今回作成する機能で使うキャラクターとカメラは

キャラクターのラジコン操作機能を作成する
Unityでキャラクターをラジコン操作で動かす為の機能を作成していきます。

で作成したものを改造して使います。

特別↑の記事のキャラクター移動スクリプト等を使う必要はありませんが、一応サンプルとして使っているので紹介しておきます。

泳ぐ機能のスクリプトはRadioControlスクリプトに追記する形で作成しますが、普通のキャラクター移動スクリプトを変更するだけで大丈夫です。

AnimatorControllerの作成

通常のキャラクター移動のアニメーションの状態と遷移の他に、泳いでいる状態と遷移を追加します。

移動と泳ぎが一緒のレイヤーに表示されていると解り辛いので、サブステートマシンでNormalとSwimmingを作成し、それぞれの状態と遷移をその中に移動させます。

サブステートマシンについては

アニメーターコントローラのサブステートマシンを使ってみる
Unityのアニメーターコントローラーのサブステートマシンを使ってアニメーターの状態と遷移をわかりやすくしていきます

を参照してください。

AnimatorControllerを見ると

移動と泳ぎのサブステートマシンを作ったアニメーターコントローラー

↑のようになります。

アニメーションパラメータにはbool型のSwimを作成しておきます。

Normalサブステートマシン

まずはNormalのサブステートマシンを見てみます。

Normalサブステートマシンの中身

↑のような状態と遷移を作成しておき、それぞれの状態からSwimがtrueになったら、SwimmingサブステートマシンのStandSwimmingに遷移するように作成します。

StandSwimmingへの遷移のSettingsでInterruption SourceにNext Stateを設定しておきます。

Interruption Sourceに関しては

UnityのAnimatorControllerのアニメーションのブレンドと割り込み
UnityのAnimatorControllerのアニメーションのブレンド方法や遷移の設定、Interruption Sourceの設定等を見ていきます。アニメーションの遷移途中で中断し次の状態へとうまく移行させる為のサンプルも作成します。

を参照してください。

現時点では、まだSwimmingサブステートマシンの中身を作成していないので、作成してから遷移を繋げます。

その他の状態と遷移に関しては、先ほど紹介したラジコン操作キャラクターの記事で作ったものです。

キャラクターの移動を簡単にする為に、IdleとWalk状態だけを作るだけでも構いません。

NormalのIdle状態を選択して右クリック→Set as Layer Default Stateを選択しておきます。

Swimmingサブステートマシン

次にSwimmingサブステートマシンの中身を作成します。

Swimmingサブステートマシンの中身

↑のような状態と遷移を作成します。

StandingSwimming(立ち泳ぎ状態)

StandingSwimmingに設定するアニメーションは、立ち泳ぎをしているアニメーションを設定します。

立ち泳ぎアニメーション

自作したアニメーションですが出来が悪いですね・・・・(^_^;)

なんだか変なダンスを踊っているようです。(;一_一)

このアニメーションのY座標は手の位置を基点としてBlenderで作りました。

元は手の位置がY座標の基点になっている

↑のような感じですね。

しかし、今回の機能を作る時に足元に基点があった方が作りやすかった為、アニメーションのY座標の基点を足元に変更します(アニメーションの作り方によって変わります)。

立ち泳ぎアニメーションの基点を足元にする

↑のようにRoot Transform Position(Y)のBake Into Poseにチェックを入れ、Based Upon(at Start)をFeetに変更してApplyボタンを押します。

StandingSwimming→ForwardSwimmingへの遷移条件は、SpeedがGreaterで0.1とし、Has Exit Timeのチェックを外しておきます。

StandingSwimming→Idleへの遷移は、Swimがfalseの時でHas Exit Timeのチェックを外します。

StandingSwimming→Idleの遷移を作成するには、StandingSwimmingを選択した状態でMake Transitionをして(Up) Base Layerを選択すると、StateかStateMachineを選択出来るのでStates→Normal→Idleを選択します。

また、SettingsのInterruption SourceにNext Stateを選択します。

ForwardSwimming(前方に泳ぎ出す状態)

次はFowardSwimmingの状態に設定するアニメーションです。

FowardSwimmingに設定するアニメーション

↑のように、立ち泳ぎから平泳ぎへと移行するアニメーションになります。

これもいまいちな出来ですね・・・・(;一_一)

ForwardSwimmingに設定するアニメーションは、再生が終わるとBreaststroke状態へと遷移させています。

つまり泳ぎ始めのアニメーションをさせた後に、平泳ぎを繰り返すBreaststrokeアニメーションを再生させています。

こちらのアニメーションも、Root Transform Position(Y)の位置を足元に変更しておきます。

ForwardSwimming→Breaststrokeへの遷移条件は、Has Exit Timeにチェックを入れアニメーションの再生が終わったら遷移するようにしておきます。

ForwardSwimming→StandingSwimmingへの条件はSpeedがLessで0.1でHas Exit Timeのチェックを外しておきます。
またSettingsのInterruption SourceにNext Stateを設定します。

ForwardSwimming→IdleはSwimがfalseで、Has Exit Timeのチェックを外しておきます。Idleの選択方法はStandingSwimmingの時と同じです。
また、SettingsのInterruption SourceにNext Stateを選択します。

Breaststroke(平泳ぎ状態)

次は平泳ぎを繰り返すアニメーションです。

平泳ぎのアニメーション

これまた動きがおかしいですが・・・泳ぎが苦手な人の平泳ぎということにしておきましょう・・・・(-.-)

このアニメーションもRoot Transform Position(Y)を足元に設定します。

また、平泳ぎで息継ぎをする時に水面から出るようにする為、下にあるOffset値を調整する可能性があります。

アニメーションのOffset値を調整する

↑のように変更する可能性もありますが、これもアニメーションの作りによりますので変更する必要がないかもしれません。

Breaststroke→FowardSwimmingの遷移条件は、SpeedがLessで0.1でHas Exit Timeのチェックを外します。
また、SettingsのInterruption SourceにNext Stateを設定します。

Breaststroke→IdleはSwimがfalseで、Has Exit Timeのチェックを外します。Idleの選択方法はStandingSwimmingの時と同じです。
またSettingsのInterruption SourceにNext Stateを選択します。

これでSwimmingサブステートマシンの作成も終了しました。

アニメーターコントローラーの作成が面倒くさいですね・・・・・(ーー;)

キャラクター操作スクリプトに水面との接触処理を追加する

キャラクター操作スクリプトには通常の移動状態と、泳いでいる状態とで処理を分けます。

また、キャラクターが水と接触したかどうかをキャラクター操作スクリプトに追加します。

キャラクターが水と接触したかどうかを判定する為に、水にはコライダを設定し、TagにWaterを設定しておく必要があります。

Unityでカメラが水中に入った時にエフェクトを加えて映す
UnityのスタンダードアセットにあるWaterを使って水の表現が出来ました。しかしWaterは平面なので水中に入っても地上と同じようにカメラに表示されます。そこで水中に入った時はスクリプトからカメラに映る映像にエフェクトを加え、水中にいるようにしてみます。

それではキャラクター操作スクリプトに処理を加えます。

今回の機能で使う処理を追記していってください(一部の移動スクリプトで使うフィールド等は記載していません)。

フィールド宣言部と初期化部

まずは宣言等の追加です。

キャラクターの状態を2つ作成し、StartメソッドでState.Normalを設定しています。

offsetはキャラクターの基点から、その距離だけ上の位置にキャラクターが来たら重力の操作を切り替えます。

キャラクターの移動と泳ぎの処理

次はキャラクターの状態によって動きを変えている処理です。

重力の計算以外は動かす処理を同じにするので動かす処理をMoveというメソッドに切り分けました。

ノーマル状態の時で地面に接地していれば、アニメーションパラメータのSwimをfalseにし、Moveメソッドを呼び出し動かします。

泳いでいる状態の時は重力を働かせたくないので、velocityのyの値も0にしていますが、泳いでいない時は重力をそのまま計算します。

その後、キャラクターの足元+オフセット値が水面の高さ以下になったら泳ぐようにしています。

キャラクター位置は水面の高さとオフセット値を使って再設定をします。

その後Moveメソッドを呼び出してキー押しでの移動処理の計算をします。

泳いでいる時は重力値を計算しないようにし、最後にCharacterControllerのMoveメソッドで移動させています。

このUpdateメソッド内の処理はもっと簡単な記述が出来るかもしれませんが、わたくしはこの処理だけでだいぶ時間を使ってしまったので多少変でもこのままいきます・・・。

水に入っていてもある程度の深さまでは泳ぐアニメーションに遷移させず、ある程度陸に上がったら通常のアニメーションにするという単純な事がうまく出来ず大変でした・・・(^_^;)

レイを複雑に使ったり、コライダで検知してどうにかしようとしたり、あとはパソコンの処理が遅いせいで処理が間違っているように見えて修正した後に気付いたり。

とにかくずいぶん時間を使ってしまいました・・・・(+_+)

ここら辺の処理はうまい具合にやってください・・・・(T_T)/~~~

自前のMoveメソッド内の処理はキャラクターのラジコン操作の処理なので今回は割愛します。

キャラクターの状態変更部分

次にキャラクターの状態を変更したり水を検知する処理の追加です。

SetStateはキャラクターの状態を設定するメソッドで、OnTriggerEnterとOnTriggerExitは水に入ったか、出たかを判定する為に使っています。

キャラクターが接触したコライダのタグがWaterだったら、水と接触したか外れたのでキャラクターの状態をそれぞれ変更しています。

今気づいたんですが、キャラクターはCharacterControllerのコライダを使っていますがOnTriggerEnterとOnTriggerExitが使えてますね・・・・。

OnControllerColliderHitは相手方に力を加えたい時に使って、相手を検知する時はOnTriggerEnterとかが使えたんですね。

RigidbodyがついていたりIsKinematicの有無、普通のCollider、CharacterControllerのお互いの接触で発生するメッセージは未だに混乱しますね・・・・(^_^;)

それに関しては以前記事を書いたんですが、Rigidbodyの場合動いていない時は無効化されたりなんだりもあってよくわからなくなってしまいました。

そこら辺はUnityのマニュアルを見た方が正確かもしれません。

衝突の基本 - Unity マニュアル
Unity はゲームオブジェクト同士の衝突をコライダーで処理します。コライダーはゲームオブジェクトに取り付けられ、物理演算に基づく衝突を適用する際のゲームオブジェクトの形状を定義します。コライダーは不可視で、ゲームオブジェクトのメッシュと全...

キャラクターが水面を泳ぐかどうか確認

機能が完成したのでキャラクターを水に接触させて確認してみましょう。

↑のようになりました。

アニメーションはどうあれ水面を泳いでいるように見えなくもないですね・・・・(^_^;)

水面を後ろ向きに動かした時は立ち泳ぎのままで、平泳ぎで泳いでいる時と同じスピードで後ろに進みます。

水中にいる時は後ろ向きに動けないようにした方がいいかもしれません。

とりあえず水面を泳がせる事が出来ました!

あとは水中を泳ぐキャラクター機能か・・・・(-.-)

放置・・・・(゚Д゚=)ノ⌒゚

タイトルとURLをコピーしました