ゴマちゃんフロンティア

気まぐれと勢いで作るUnityゲーム開発日記です。

【開発メモ】「オブジェクトを掴む・投げる」アクションの修正

time 2016/08/02

というわけで、今回は「オブジェクトを掴む・投げる」というアクションの修正になります!
「修正」ということで、既にそれっぽいアクションは実装してあります。

shot2ss20160802234413497

流れとしては以下のようになっております。
1.キー入力で掴むアクションを行い、手に掴み専用の判定を出す
2.掴み判定に当たったオブジェクトを持ち上げる
3.再度キー入力でオブジェクトを投げる

これがゲーム的にはかなりの欠陥品で、
・掴み判定に当たらないと持てない
→目の前のオブジェクトでもすぐに持てない
・掴む動作自体がモッサリなので、掴み判定と相まってテンポが悪い
・持ち上げた際のオブジェクトの位置が掴んだ位置に依存
→判定の出始めや終わり際で持つと持ち上げた際にズレまくる
・一度に複数のものを掴めてしまう
・持ち上げた状態で敵を押すと楽々場外KOが可能

などなど、実用に耐えうる代物ではありません。
特に致命的なのがテンポの悪さなので、今回はそこに重点を置いて修正を考えてみます!
アクションゲームらしく、キー連打で次々と投げまくれるようなものがいいですね!

様々なクラスやオブジェクトで処理している関係上、ソースを全て書くと長くなってしまうので、最低限のものだけ載せます!

オブジェクトを掴む処理の変更

以下のようなシンプルなものに変えてみます。
・キー入力時に前方に掴むことができるオブジェクトがあるか確認する
・掴めるオブジェクトがある場合は持ち上げる

処理としては、キー入力時にプレイヤー前方に短く RayCast を行い、当たったオブジェクトを判定、掴める場合は特定の位置に移動させながらプレイヤーの子オブジェクトにします。

上記修正から、掴み判定という概念を削除します。
モッサリ感解消の他、複数オブジェクトを一度に持ち上げてしまう問題も解決できます。

語っていてもしょうがないので、レッツコーディング(`・ω・´)
Player クラスの Update() 内に処理を追加します。

if (Input.GetButtonDown("Grab") && !stateInfo.IsTag("Throw")) {
    Ray grabRay = new Ray(transform.position, transform.forward);
    if (Physics.Raycast(grabRay, out hit, 3f)) {
        if (hit.collider.tag == "ThrowableObject") {
            StartCoroutine("setThrowingTarget", hit.collider.gameObject);
        }
    }
}

1つ目のif文で「ボタン入力時」且つ「掴み&投げ系のモーションではないこと」を判定します。
予め掴み&投げ系のステートに「Throw」というタグを割り当てておく必要があります。
また、Raycast() の際は maxDistance を指定しないとあらぬところまで届いてしまうので注意します。

if文が通ったら setThrowingTarget() であれこれ処理を行います。
詳しい処理は割愛させて頂きますが、モーション切り替えや持ち上げたオブジェクトの親子設定などを行っています。

前の仕様では敵に掴み判定を当てると専用の掴み攻撃が発動しましたが、システム的に面倒な上にゲーム的にもどうでもいい機能だったため、こちらも無くしてしまいました。

連続で入力した際の挙動の調整

掴む際のプロセスが短くなりましたが、そこから投げるまでの過程はまだテンポが悪いです。
モーション的には「掴む→持ち上げて保持→投げる」となっており、各モーションが完全に終了するまで遷移しないことが問題のようです。
そこで即投げする場合は「持ち上げて保持」のモーションを経由せず、掴みから直接投げるモーションへ遷移できるようにしてみます。

shot2ss20160802234236073

上は AnimatorController の掴む&投げるアクション用のサブステートマシン内です。

制御用にbool型パラメータとして Hold を作ってあります。
trueになった際に Grab→Hold と遷移し、falseになった際には Hold→Throw と遷移します。
上記は何れも ExitTime にチェックを入れているので、モーションが終わるまでは遷移しません。

ここに Grab から Throw へ遷移を追加し、直接遷移できるようにします。
遷移条件は Hold→Throw と同じで、Hold パラメータが false になったときです。

ということで、Grab ステートに以下のスクリプトを設定します。

using UnityEngine;
using System.Collections;

namespace StateController.PlayerAnimator {
    public class Grab : StateMachineBehaviour {
        public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
            if (Input.GetButtonDown("Grab")) {
                animator.SetBool("Hold", false);
            }
        }
    }
}

超シンプルに、掴みモーション中に入力があった場合はそのまま Hold を false にしてしまいます。
この状態で Grab→Throw への遷移で ExitTime のチェックを外せば、入力された段階でそのまま投げるモーションに遷移してくれます。

まとめ

そんなわけで、オブジェクトを掴む・投げる処理に修正を入れてみました!
システムとして要るかどうかはともかく、アクションゲームでは割とありそうなものなので、ひとまず使えるレベルのものにしておきたいです。

最近更新していなかった故に急いで書いたのでかなりざっくりです。
分かりにくいところがあればコメント等頂ければ頑張って書きます!

スポンサーリンク

down

コメントする



ツイッター