【Unity】CharacterMotor使用時のキャラクター移動を2Dに限定する

というわけで、今回の目標はタイトル通り「CharacterMotor 使用時のキャラクター移動を2Dに限定する」です!

shot2ss20160918121015592

「3Dベースで局所的に2D」は前に一度チャレンジしましたが、キャラクターの移動や敵の行動、オブジェクトの動きなどを全て2D向けに合わせなければなりません。
Unityには2Dモードもありますが、あれは本当に真横から見たドット絵のゲームを作るのに適したもので、3Dゲームで局所的に2Dっぽくするには向かない気がします。
元々3Dを想定して作っていたので、プレイヤーの移動関連はコンポーネントに丸投げで、当たり判定も CharacterController のコライダーをそのまま使っている状態です。

何故こんなことをしたいかと言うと、「場面に応じて2Dと3Dを切り替えたいから」です。
全エリア自由に3次元移動ができる場合でも、カメラワークとステージ構成次第で「2Dっぽいステージ」は出来ますが、画面の手前・奥にどれだけ移動させるかを制御するのが大変です。
所謂「見えない壁」を設置するのが手っ取り早い方法ですが、「行けそうなのに行けない」というのは私的に嫌いな要素です。
それなら特定のエリアだけ2Dにしてしまいたいと言うわけです。

前置きが長くなりましたが、今回はとりあえず自キャラクターの移動制御を2Dに限定させれるようにしてみました!
当たり判定自体は3Dであること、3Dモードにもスイッチできるようにしたいことから、CharacterController + CharacterMotor + PlatformInputController が付いた状態でやります。

移動入力を2D方向へ限定させる方法

CharacterMotorはソースコードが公開されており、C#版を作っている方もいたので、どんな処理をやっているか確認できます。
相応に複雑なので簡単なことではありませんが・・・。

http://forum.unity3d.com/threads/charactermotor-fpsinputcontroller-platforminputcontroller-in-c.64378/

本来は外部的なコンポーネントには手を加えたくないところです。
が、CharacterMotor を Player クラス側からあれこれしても上手くいかないので、(なるべく) 元の動きを崩さないように修正するしかありませんでした。
今回は上記のC#版をインポートして作っているため、既存スクリプトとの重複やメンバのアクセスレベルに注意する必要がありました。
特に「アクセス修飾子が省略されていてprotected扱い」というものが多かったです。

実際にキャラクター移動している部分は UpdateFunction() になります。
その中で「Move our character!」とド直球なコメントが書いてあるあたりを修正します。

// Move our character!
currentMovementOffset.z = 0;
movement.collisionFlags = controller.Move(currentMovementOffset);

「currentMovementOffset」の分だけ CharacterController.Move() で動かしているようなので、その手前でZ軸を0にしてしまいます。

また、上記コードのちょっと上に MovingPlatform に関する処理が書いてあります。
ステージ上に動く足場がなければ問題ありませんが、こちらもZ軸を0にしておきます。

 
moveDistance.z = 0;
if (moveDistance != Vector3.zero)
    controller.Move(moveDistance);

どうでもいい話ですが、ブロックのないif文って個人的に嫌いなんですよね。
ちょっとした処理だとしてもブロック付けてインデントして・・・が見やすいです。

これで移動に関しては2Dっぽくなります!
雰囲気でいえば「スマブラ」や「ロックマンX8」あたりに近いです。

ただし現状では CharacterMotor を直接書き換えた関係上、3Dで動きたいときでも2D方向に限定されてしまいます。
適当にフラグを1つ持たせて制御するのが手っ取り早そうです。

 
// Move our character!
if (invalidMoveZ) {
    currentMovementOffset.z = 0;
}
movement.collisionFlags = controller.Move(currentMovementOffset);

invalidMoveZ というフィールドを定義し、制御してみました!
あとは Player クラスから CharacterMotor を GetComponent() して切り替えたりすれば、移動に関しては問題なさそうですね。

回転方向を2D方向に限定させる方法

現状では PlatformInputController が入力方向にキャラクターを回転させてしまいます。
つまり移動方向は2D限定なのにZ軸 (手前や奥) に振り向くことができます。

空間は3D・移動は2Dのゲームで左右に振り向く際、回転を入れずに瞬時に振り向いているゲームが多い気がします。
2D限定なら手前や奥にキャラクターを向ける必要もないので、当然といえば当然ではあります。
リアリティなんて要らないので、自分もこの方法を取り入れてみました。

ということで、PlatformInputController をいじってみます。
まずは入力方向に一瞬で振り向くようにするため、ConstantSlerp() を修正します。

Vector3 ConstantSlerp(Vector3 from, Vector3 to, float angle)
{
    float value = Mathf.Min(1, angle / Vector3.Angle(from, to));

    if (invalidRotateZ) {
        value = 1;
    }

    return Vector3.Slerp(from, to, value);
}

CharacterMotor と同じように、invalidRotateZ というフィールドを定義して制御します。
Vector3.Slerp() で入力方向に振り向く際の角度を補完しているようなので、第3引数に1を指定すれば瞬時に向き直すようになります。

もう1つ、Z軸に向かないようにするための修正を加えます。
コメント「Set rotation to the move direction」のあたりです。

// Set rotation to the move direction   
if (autoRotate && directionVector.sqrMagnitude > 0.01)
{
    Vector3 newForward = ConstantSlerp(transform.forward, directionVector, maxRotationSpeed * Time.deltaTime);
    newForward = ProjectOntoPlane(newForward, transform.up);

    if (invalidRotateZ) {
        newForward.z = 0;
    }

    if (newForward != Vector3.zero) {
        transform.rotation = Quaternion.LookRotation(newForward, transform.up);
    }
}

newForward が振り向く方向のようなので、これのZ軸を0にすればOKです。
ただしこれだと零ベクトルが渡された場合に奥を向いてしまう上、Unity から警告が出たりしてしまいます。
なので、零ベクトルだったらそもそも LookRotation() を実行しないようにしました。

20160910

これで移動も回転も2Dに限定にすることができました。
GIFアニメーションでは分かりませんが、Z軸に移動入力しても移動・回転が行われていません。

まとめ

そんなわけで、CharacterMotor 使用時の移動方向を2Dに限定させてみました!
キャラクターの動き的にはだいぶ近づいた気がします。

ただし敵は自在に3Dで動いていたりするので、ゲーム的な意味で2Dにするのはなかなか大変ですね。
とはいえ、敵やオブジェクトは RigidBody の Constraint である程度制御できるので、プレイヤーキャラクターの制御よりは楽かもしれません。
今度また挑戦してみます!

今日のイラスト

本ブログのマスコット (?) のシルリスを描いてみました。
メインキャラ3匹のデザインを一新するため、シルリスも新しいデザインを考えているところです。

また、線画でペンタブを使う練習も兼ねていたりします。
パスツールで書くより難しいですが、機械的ではない線が描けるため味が出ます。
ただ影の描き方がだいぶ適当な気もします・・・。

shilriss7

【Unity】パーティクルシステムのSkinned Mesh Rendererについて

というわけで、Unity5.3 からパーティクルシステム (Shuriken) の Shape に「Skinned Mesh Renderer」が加わったそうです!
ちょっと気になったので、どんな感じの機能か使ってみました!

パーティクル設定

当然ですが、「Skinned Mesh Renderer」が付いたオブジェクトが必要です。
3Dモデルをインポートすればメッシュに付いてくるので、適当な自作キャラクターの体を使います。

shot2ss20160907233803185

シーン内の Skinned Mesh Renderer を指定すると、パーティクル本体をどこに配置しても、指定したメッシュに合わせてレンダリングされます。
故に空オブジェクト内に整理して置いたり、キャラクターの子オブジェクトにしても問題ないようです。
他にもメッシュからの生成位置(オフセット)を調節したり、マテリアルの色をメッシュに合わせたりできます。

shot2ss20160908001214777

この状態で再生すると、上のようにキャラクターのメッシュに合わせてパーティクルが生成されます。
体からオーラが出ているような感じですね。
「Start Speed」や「Color Over Lifetime」をいじるともっとそれっぽくなります。

キャラクターのメッシュを分けている場合、その分だけパーティクルを作成・設定しておく必要があります。
画像のマリンパも「頭」「上半身」「下半身」と無駄に分かれていたりします。

何が良いかと言えば、「アニメーションの動きに合わせてパーティクルを出せる」ことでしょうか。
今までは固定のメッシュに対してレンダリングするのが限界だったので猶更ですね。
「ダッシュ中にキャラクターの形に合わせてエフェクトを出す」といったことも簡単にできるようになるかも。

いじって分かったこと

「アニメーションの動きに合わせてパーティクルを出せる」と書きましたが、その時点のメッシュの位置に合わせて生成するだけです。
生成後もメッシュに合わせて追従してくれる・・・なんてことはありません。
「Simulation Space」を Local にするとオブジェクト自体の移動には付いてきてくれますが、メッシュの移動には付いてきてくれません。
「アニメーションに合わせてリアルタイムで動かしたい」というケースでは不向きかと思われます。

また、流石に Cloth コンポーネント適用時の動きには対応してくれないようです。

shot2ss20160907232506900

マント (赤い部分) に Cloth を追加し、軽く動かした状態でパーティクルを出してみましたが、(分かりにくいですが) SkinnedMeshRenderer 元々の位置にレンダリングされます。
Cloth の動きに合わせてパーティクルを出すのは大変そうなので、こればかりはしょうがない部分でしょうか。

という点を踏まえると、使い道がありそうでないかもしれません。
手持ちの武器を光らせるのに手っ取り早いかなーと思いきや、パーティクルが追従してくれないので微妙でした。

応用例

「生成後はアニメーションの動きに合わせて移動しない」ことから、アニメーション中に断続的に生成すると残像っぽいエフェクトになります。
これを高速で動くオブジェクトに適用すると面白そう。

shot2ss20160910201151286

「Duration」と「Start Lifetime」の値を短めに調節します。
短時間にドバッとパーティクルを出す場合、Rate を0にして Bursts を設定するといい感じです。
「Simulation Space」は World に設定。
色やサイズ、スピード等はお好みで。

20160910_01

自分のキャラは小さめなのであまり実感はありませんが、頭身の高い人型ならもっと見栄えはよくなるかも。
もっとサイズやスピードを上げても良さそうですね。

まとめ

そんなわけで、パーティクルシステムの「Skinned Mesh Renderer」を試してみました!
ネタがないときはこんな感じで「Unityの気になった機能」を調べてみるのもいいかもしれません。

【Blender】モデリング練習メモ「ペンギン」編

というわけで、久しぶりの Blender モデリング練習です。
今回のお題は「ペンギン」です!

shot2ss20160903183123386

すごくペンギンっぽくないですが、ペンギンです!

「海の仲間たち」というゲームタイトル故、ペンギンは外すことができません。
動物園や水族館で大量のペンギンが泳いだりぼーっとしていたりする姿は微笑ましいですね。
卒業研究として提出したゲームでもペンギンがプレイアブルキャラとなっていたりします。

しかしながら、今回は敵として作成する予定です!
というのも、プレイヤーキャラは既に3キャラで決まっており、アシストキャラとしてもどこか乗れるような体格をしていないためです。
また、ペンギンといえばお腹で滑ってくるイメージもあるので、敵としての攻撃方法も作りやすいです。

ここまでくると一種のタイトル詐欺のようにも思えますが、「敵に洗脳されている」とかそれっぽい理由はいくらでも付けられます。
「スーパーマリオ64」でも、ピンク色のボム兵と黒色のボム兵で敵味方別れていますよね!
つまり気にしなくて良いということです。

モデリング

何もなしで3Dモデルを作るのは難しいです。
というわけで、今回も補助用に(下手な)絵を描いてみました!

penguin3

これを Blender の背景として設定し、頂点を作っていきます。
いつも通り面を2当分して Mirror モディファイアを付与し、下書きに沿って頂点を延ばします。
真ん中を開ける必要があるので、ある程度面を細分化した後に中央をごっそり消してしまい、頂点を繋ぎ合わせました。

shot2ss20160903183532873

エルードや頂点追加&面貼りを使ってそれっぽい形にします。
SubdivisionSurface モディファイアを追加し、更に頂点を動かして調整していきます。

shot2ss20160903183331033

やや歪んでいる気もしますが、とりあえず完成しました。
敵として出ることを想定しているため、やや小柄な体型です。
「これはペンギンなのか」と言われるとそれまでですが・・・腕とか頭はそれっぽくなっている気がします。

攻撃方法は決めていませんが、氷の息を吐いたりでいいんじゃないでしょうか (適当)
あるいはスケート靴で滑って (後述) くるくる回転攻撃とかでも良さそうです。

スカーフ

自作キャラは首元に何かしら付けているものが大半です。
マントやマフラー、ストールなどなど・・・。
純粋な動物としてモデリングしても面白くないこと、二足型キャラクターモデルの形状的に首元が一番いろいろ付けやすい(と感じる)ためです。

shot2ss20160903183643512

これも Cube をエルード、ループカットであれこれして形にしています。
ある程度できたら SubdivisionSurface を追加して調整します。

shot2ss20160903183615784

何かスカーフっぽくないですが、形自体は下書きに近いので良しとします。
布としてのシミュレートは Unity の Cloth コンポーネントで行う予定なので、Blender 側ではモデリングだけにしておきます。

これを機に、主要な敵キャラにお揃いのスカーフを巻くのも一興かもしれません。
こういうのは敵側ではなく味方側がやっていることが大半な気もしますが・・・。

スケート靴

上でも書きましたが、ペンギンはお腹で滑るイメージがあります。
実際のペンギンもお腹で滑ったりしているみたいです。

が、モデルを見た親が「スケート靴にして滑れるようにしなさい」と言い放ちました。
スケート靴を履いているペンギンなんてなかなかいないと思いますが、下半身が寂しかったので取り入れることに。
最早ペンギンとして作った意味が崩壊している気もしますが、自分の開発ではよくあることなので気にしないようにします!

shot2ss20160903183758584

スケート靴をモデリングしてみました。
競技によって形状に微妙な差があるようですが、こだわる部分でもないため一般的なゲームっぽいスケート靴を作っています。

エッジ部分の曲線が曲者・・・かと思いきや、これもSubdivisionSurface であっさり解決。
このモディファイアを知ってから世界が変わったと言っても過言ではありません。
スカルプトモードで形作るなら「Sculptris」等もっといいソフトがあるので、尚更ですね。

shot2ss20160903184053799

元のオブジェクトはこんな感じ。
エルードや頂点移動、ループカットなどを知っていれば簡単にできる形です。

まとめ

そんなわけで、ペンギンのモデリングに挑戦してみました!
愛着が沸くとは言えない出来ですが、昔ほど崩壊したモデリングでもないので、妥協ラインでしょうか。
もっといろいろ作って経験を積んでいきたいですね。