【開発メモ】アシストキャラクターの実装 その2

というわけで、今回は前に実装したアシストキャラクターの続きになります!
前回の記事はこちら

【開発メモ】アシストキャラクターの実装 その1

前回でアシストキャラクターへの乗り降りまで実装したので、今回は実際にアシストキャラクターを操作する部分を実装してみようと思います!
基本操作はプレイヤーに合わせ、移動・攻撃・ジャンプなどの基本アクションを作っていきます。
処理を流用できる部分も多いため、実装だけならあまり苦戦はしなかったです。

移動系

基本的な移動はプレイヤーと同じく、CharacterMotorとPlatformInputControllerで行います。
今はアザラシをベースに作っているため、移動速度は少し遅めにしてみます。

また、アシストキャラには回避や二段ジャンプなどの特殊な移動は実装しない予定です。
そういう意味ではプレイヤーキャラに比べて単純かもしれません。
その分各キャラに特殊な能力を付けたいと思いますが、それはまた追々ということで!

攻撃系

攻撃判定の生成ロジックはプレイヤーと一緒です。
参考になりそうな過去記事はこちら

【再編集】Unity開発メモまとめ 「攻撃処理系」

【開発メモ】攻撃判定制御のリファクタリング

同じこと書いてもしょうがないので、アザラシに持たせる攻撃方法について考えます。
これは前々から決めていて、強力な遠距離攻撃を持たせる予定です。
通常攻撃は高威力の弾を発射し、特殊攻撃には敵を追尾するレーザーを放ちます。

shot2ss20151226120459482

使わなくなったパーティクルで良いものがあったため移植し、通常攻撃としました。
口から出すには弾が大きい気がしますが、あまり気にしないことにします!
特殊攻撃のレーザーはロジックが難しそうなので後回しにします。

問題点

今回までの実装で抱えている問題点を挙げてみます。

乗り降りの際の円形エフェクトの表示

円形エフェクトはEffekseerを使って表示していますが、エフェクト毎に個別でインスタンス化されているわけではなく、Effekseerオブジェクトから全体をコントロールしている(?)ようです。
それ故、「特定のエフェクトだけを有効・無効にする」ということが困難です。

EffekseerのUnityマニュアルを見てみると、コンポーネントの他にスクリプトからでも再生ができるようです。
これを使えば個別でエフェクトをコントロールできそう。
使う機会は多いと思われるため、EffectUtilityというユーティリティクラスを作成し、その中でハンドルを生成する関数を実装します。

using UnityEngine;
using System.Collections;

public static class EffectUtility {
    public static EffekseerHandle createEffekseerHandle(string fileName, Transform transform) {
        EffekseerHandle handle = EffekseerSystem.PlayEffect(fileName, transform.position);
        handle.SetRotation(transform.rotation);
        handle.SetScale(transform.localScale);

        return handle;
    }
}

このEffekseerHandle型にはStop()という関数が含まれており、これを実行することで止めることができます。
もっと効率の良い方法がありそうですが、とりあえずこれで解決!

AnimatorのAnyStateからの割り込み

ある意味最大の問題点です。
アシストキャラに乗っている場合、プレイヤーキャラは待機orダメージモーションのみで他のモーションは入りません。
が、AnyStateから設定されているダメージや回避などは割り込んで再生されてしまいます。

Controllerを動的に切り替えることができれば行けそうですが、Animatorを動的に変えること自体がかなり怖いです。
遷移しないようにスクリプトから無理矢理制御できなくもなさそうです。
とてもスマートとは言えませんが・・・。

CharacterControllerの当たり判定

アザラシは横長な動物なわけですが、CharacterControllerのカプセルコライダーは横向きにすることができません。
仕方なくHeightを小さくし、Radiusで調整するようにしましたが・・・

shot2ss20151226120714778

見ての通り胴体前後の判定がスッカスカです。
NPCの敵が相手なので致命的ではありませんが、これが対戦ゲームとかだったらクレーム殺到なレベルですね。
CharacterController自体の判定は移動制御のみに使い、別でダメージ判定用のコライダーを付けれれば何とかなりそうです。

まとめ

今まで「まとめ」が全然まとめじゃなかったので、今度から箇条書きでやったこと/分かったことを書いていくようにします!

・アシストキャラクターの基本コントロールはプレイヤーと同じ
・アザラシは遠距離型キャラクターにする
・Effekseerはスクリプトから生成することでhandleから個別に停止できる
・いろいろと問題あり

細かい部分に難がありますが、見てくれだけは一応完成。
上手くゲームシステムやステージ構成に組み込んで行きたいです。

今日のイラスト

またまたシルリスちゃんです。
輪郭はパスツールで、影はペンタブ+エアブラシで塗ってみました!
マウスで適当に影を付けるよりは味が出ている・・・気がする。

shilriss5

【開発メモ】アシストキャラクターの実装 その1

というわけで、前回の投稿から時間が空いてしまいましたが、今回のお題はこれです!

shot2ss20151215210405763

新要素として「アシストキャラクター」を実装してみようと思います!
プレイヤーキャラとは別にステージ上にいる仲間キャラで、乗ることで操作することができるというものです。

元々はプレイヤーキャラとしてアザラシやカンガルーも入れようとしたのですが、開発中に厳しいと判断し3キャラに絞った経緯があります。
そのキャラを何とかゲームに組み込めないかと思い、「ステージ上で一時的に操作できるキャラ」という結論に至りました。

今回はプレイヤーキャラがアシストキャラに乗り降りするシステムを作ってみます。
焦っても雑になってしまうので、まったりやっていきます!

下準備

当たり前ですが、アシストキャラクターのモデルを作る必要があります。
ということでさくっと作ります!

shot2ss20151215210217326

作成したアザラシ(のつもり)です。
カンガルーとどちらにしようか迷いましたが、アザラシの方が乗るのに違和感なさそうという点と、単純に自分が大好きな動物なのでチョイスしました!
見直すとあまりアザラシっぽくないですが、そのうち修正します!
今回は乗り降りだけなので、モーションも作っていません。

乗る場合の処理

乗っていないアシストキャラには円形のエフェクトを出し、その範囲内でボタンを押すことでプレイヤーキャラが飛び乗るようにします。
アシストキャラの位置はプレイヤーの操作以外で動かすことはないと思われます。

円形の判定はアシストキャラクター本体に子オブジェクトとして作ります。
エフェクトはEffekseerのサンプルを参考にを作成・使用しています。
専用のスクリプト「RideArea」を作成します。

using UnityEngine;
using System.Collections;

public class RideArea : MonoBehaviour {

    private AssistCharacter assistCharacter;

    public void OnTriggerStay(Collider c) {
        if (TagUtility.getParentTagName(c.gameObject) == "Player") {
            if (Input.GetButtonDown("Action")) {
                Player player = c.GetComponent<Player>();
                assistCharacter.setPlayer(player);
                player.onRideOnAssistCharacter(assistCharacter);
            }
        }
    }
}

判定内でボタンが入力された場合、Playerクラスの「onRideOnAssisstCharacter」を実行します。
プレイヤーキャラをアシストキャラの上に飛び乗るように移動させ、transform.parentにアシストキャラを設定して子オブジェクトにします。
また、各種コントロール系を無効化します。

public void onRideOnAssistCharacter(AssistCharacter assistCharacter) {
    // コントロール系の無効化
    charControl.enabled = false;
    charMotor.enabled = false;
    platForm.enabled = false;

    // プレイヤーのtransform修正
    transform.parent = assistCharacter.transform;
    transform.rotation = assistCharacter.transform.rotation;

    // ジャンプ時のモーションパス定義
    var pathList = new List<Vector3>();
    pathList.Add(transform.position);
    pathList.Add((transform.position + assistCharacter.ridePoint.transform.position) / 2 + new Vector3(0f, 10f, 0f));
    pathList.Add(assistCharacter.ridePoint.transform.position);

    iTween.Stop(gameObject);
    iTween.MoveTo(gameObject, iTween.Hash(
        "path", pathList.ToArray(),
        "time", 1f,
        "delay", 0.01f,
        "easetype", "easeOutSine",
        "oncomplete", "onPlayerRideOn",
        "oncompletetarget", assistCharacter.gameObject
    ));
}

ジャンプ時の移動処理はiTweenで行います。
アシストキャラクターの子オブジェクトとして「ridePoint」という空オブジェクトを用意しておきます。
iTween.MoveTo()の移動先は”position”で指定しますが、今回は”path”を使ってみました!
Vector3型のListを作り、「プレイヤーキャラ→ジャンプの頂点→ridePoint」となるように挿入してします。
あとは”easetype”を”easeOutSine”にすればジャンプが放物線っぽい挙動になります。

iTween.Stop()とdelayを入れている理由は以下の記事を参照して頂ければと思います。

【Unity】iTweenの停止と再実行について

最後はアシストキャラ本体に付与するスクリプトを作成します。
以下はAssistCharacterクラスですが、実際にはそれを継承したSealクラスを付けています。
現状ではスーパークラスの関数を呼んでいるだけなのでほとんど意味はありませんが、後々増やすことも考え、専用に作っておきます。

Start()やUpdate()は特に面白いことをしていないので、プレイヤーが乗った際の関数のみ記載します。

public void onPlayerRideOn() {
    isRiding = true;

    charControl.enabled = true;
    charMotor.enabled = true;
    platForm.enabled = true;
}

関数はiTweenの実行後に呼ばれるよう、oncompleteで指定します。
isRidingフラグをONにし、各種コントロールを有効化します。

プレイヤーの参照としてPlayerクラスも渡して設定しておきます。
どのプレイヤーが乗っているか把握したり、何かと処理で使う機会が多いためです。

降りる場合の処理

乗っている最中にボタンを押すことで飛び降ります。
飛び降りる方向はアシストキャラの後ろ側です。
後ろが崖の状態で飛び降りるとそのまま落下しそうですが、現状ではどうしようもない部分なので気にせずいきます!

AssistCharacterクラスのUpdate()内で「ボタン押下かつ地面にいる状態」を判定し、降りる際の処理を記述した関数を呼んでいきます。
降りた後はアシストキャラを操作しなくなるので、コントロール系を無効化します。

public void onPlayerRideOff() {
    isRiding = false;

    charControl.enabled = false;
    charMotor.enabled = false;
    platForm.enabled = false;

    player.onRideOffAssistCharacter(this);
}

アシストキャラの処理後にPlayerクラスの「OnRideOffAssistCharacter」を実行します。
iTweenで飛び降りる処理と、コントロールを有効化する処理を書きます。

public void onRideOffAssistCharacter(AssistCharacter assistCharacter) {
    // コントロール系の有効化
    charControl.enabled = true;
    charMotor.enabled = true;
    platForm.enabled = true;

    // ジャンプ時のモーションパス定義
    Vector3 assistCharBack = assistCharacter.transform.position - (assistCharacter.transform.forward * 10f);
    var pathList = new List<Vector3>();
    pathList.Add(assistCharacter.ridePoint.transform.position);
    pathList.Add((transform.position + assistCharBack) / 2 + new Vector3(0f, 10f, 0f));
    pathList.Add(assistCharBack);

    transform.parent = null;
    iTween.Stop(gameObject);
    iTween.MoveTo(gameObject, iTween.Hash(
        "path", pathList.ToArray(),
        "time", 1f,
        "delay", 0.01f,
        "easetype", "easeOutSine"
    ));
}

「キャラクターの後ろ側に移動する」という点でちょっと詰まりました。
transform.positionを元にtransform.forward + Vector3() で上手くずらすような感じになります。
transofrm.forwardをそのまま参照すると原点近くまで吹っ飛んでしまうので気をつけます。

iTweenは乗る際と同じく”path”で指定します。
今度は「ridePoint→ジャンプの頂点→アシストキャラの背後」となるように設定してあります。

20151215

実際に乗り降りするとこんな挙動になります!
概ね自分の想定していた挙動になってくれてよかったです。

まとめ

そんなわけで、アシストキャラクターと乗り降りの部分を作ってみました!
次はアシストキャラクターを操作する部分を実装していく予定です。
難しそうなので遅れるかもしれませんが、まったりやります!

【キャラクターメモ】ちょっとしたモーションの作成

というわけで、早くも11月、今年もあと2ヶ月になりました。
未だに「ちょっと前は夏だったのに」と思うこともしばしば・・・。
時間の流れって早いものですね。

今回はタイトル通り、「ちょっとした」モーションの実装になります!
「ゲーム的になくてもいいけど、あると雰囲気いい」といったものですね。

shot2ss20151105230008984

いつもマリンパで作ってばかりなので、今回はシルリスで作ってみました!
小さなリスの体格なので、可愛らしいモーションを付けていきたいところです。
といっても移動やジャンプなどは3匹ほぼ共通だったりしますが・・・。

ストール部分にClothを入れたので、そのテストも兼ねています。
首元なのでマントのように激しくは動かさず、アニメーションから受ける影響も少なめに設定しています。

待機モーション

一定時間操作しないで放置した際のアレです。
最早ほとんどのゲームに搭載されており、ない方が珍しいというレベルかもしれません。

shot2ss20151105225310728

シルリスの場合、杖を後ろ手に持ってキョロキョロします。
FEZの某クラスの待機モーションとすごく似ています。

だいたい5秒無操作で待機モーションを再生し、終了後また5秒無操作で~くらいがちょうど良いでしょうか。
フレーム数で測るのも面倒なので、Time.deltaTimeで何とかします。

体力減少時のモーション

いわゆる「疲れている状態」です。
体力ゲージが減ってきたら通常の待機モーションからこちらのモーションに切り替えます。

shot2ss20151105225632056

通常の待機モーションと同じく、ImportSettingsでLoopを有効にしておきます。
作ってみるとなかなか辛そうなモーションになったので、体力ゲージ1/4以下くらいから切り替えるのが良い感じでしょうか。
AnimatorのParameterに体力値を設定し、それで判定する予定です。

倒された際のモーション

体力ゲージがなくなり、「ミス」した際のモーションです。
別モーションで既に「吹き飛ばされた際のダウン状態」というものがありますが、それとは別で考えてみます。

shot2ss20151105225451864

シンプルにうつ伏せに倒れてもらいます。
体力ゲージがなくなった瞬間、あらゆるモーションから割り込んで再生する予定です。
挙動的にはモンハンの力尽きた際のものに似ています。

決めポーズ

キャラクターに1つは決めポーズが欲しいところです。
長いモーションを作ってもくどいだけなので、サクっとできるレベルのものを作ります。
シルリスの場合は杖を持っているので、くるくる回した後に両手持ちさせてみます。

shot2ss20151105225834184

「これどこで使うのよ」と言われれば・・・ステージクリア時とか、キャラクター選択時とか・・・くらいしかなさそうです。
恐らくプレイヤー操作で起こすモーションではないと思うので、スクリプトも作っていません。
必要なときにAnimator.Play()でいいんじゃないでしょうか (適当)

まとめ

そんなわけで、本当にちょっとしたモーションの実装を行いました!
ステージもできていない今、こんなモーション後回しでいいのは確かですが、自作キャラをカスタマイズするとモチベが上がります。
本作業が止まらない程度に、こういった他の部分も作っていきたいところです。

【キャラクターメモ】敵キャラクター「ビードラ」の作成

というわけで、朝の冷え込みがきつくなってきた山梨です。
こんな時に限ってサーバーメンテ日なので、朝4時起きだったりしました。

shot2ss20151028190854917

今回は新しい敵キャラクター「ビードラ」の作成になります!
既に「バブぴょん」という敵キャラクターを作ってあるので、それに続く第2のデフォルトスタンダードな敵キャラです。

名前の由来は「ビート(殴る、叩く)」とドラゴンを掛け合わせたものです。
あまりドラゴンという感じはしなかったりしますが、爪や尻尾はそれっぽくなっています。
まあ敵キャラなので深い意味はないです。

位置付けはマリオでいうクリボーに対するノコノコといったところでしょうか。
人型に近い体格なので亜種や派生種も作りやすそうです。

モデリングとテクスチャ

パっと見は猫とドラゴンを混ぜたような感じです。
体格だけで言えばモグフィーに近いものがあります。

shot2ss20151025231354379

色合いのせいか、「グランブルーファンタジー」の某トカゲと似ている気がします。
ついでに色合いがバブぴょんとも変わり映えしないので、いっそ青色にしようかと考えていたりします。
勿論リンゴが好きとかそういう設定はありません。

shot2ss20151025231300428

耳は前のめりでカーブの効いた形状になっています。
曲面を普通に作るのは難しいのですが、モディファイアの「Subdivision Surface」を使うと簡単に作れます。
Cubeをベースに、エディットモードでエルード(E)やループカット(Ctrl+R)を使ってみましょう。

shot2ss20151025231412891

足も翼も尻尾もCubeをベースにSubdivision Surfaceで作りました。
個人的にはすごく使いやすいモディファイアなので、最近のモデリングでよく使っています。
ただApply後に頂点数が増えすぎてしまうことがあるので、Decimateモディファイアで適度に減らすといい感じ。

shot2ss20151025231454954

頭のオブジェクトにテクスチャを貼り付けます。
かなり適当ですが、敵キャラをまじまじと見る機会もないと思うので気にしません!

実は最近ペンタブを買ったので、それを用いて描いています。
まだ上手く扱えず、イラストレベルのものは到底描けませんが、ちょっとテクスチャ描く程度なら手軽にできます。

ゲーム的な設定

バブぴょんと同じく、いろいろな場所に登場する予定の敵です。
歩いて移動し、接近してプレイヤーを攻撃します。
バブぴょんよりは体力・攻撃力共に高く設定する予定です。

攻撃アクションは両手を使ったパンチがメインです。
それだけではつまらないので、飛び蹴りや頭突きようなものを入れるのも面白いかもしれません。
人型故の汎用性があるので、何か持たせたり付けたりしてもよさそうです。

ちなみに翼に相応する部分はありますが、飛べるようにするつもりはありません。
何のためについているかは気にしない方向で!
現実でもペンギンとか翼あっても飛ばないですよね。それと一緒です!

まとめ

そんなわけで、新しく敵キャラクターを増やしてみました!
ゲームを進めても同じような敵ばかりでは飽きてしまうので、敵キャラクターもなるべく増やしていきたいところ。
とりあえずはあと1体くらい体格の異なる敵を作ってみたいと考えています。
バランスを見ると宙に浮く敵が欲しいですね。