【Unity2d】押す処理の再実装とバグの修正

Unity2D

Unity2D ARPG

こんにちは。なおキーヌです。

ブログ毎日更新は343日目になります。

前回は引く処理とグリッド移動を実装しました。

現状押す処理をしても引く状態になってしまっているのでそこの修正と、
グリッド移動が終わった瞬間に十字キーを連打しているとバグが発生しましたので直します。

endGridMoveを修正

作っていて気づいたのですが、最後に位置補正する時に既にステートを0にしてから補正していて
どっちに押していたかわからなくなってしまうのでendGridMoveはステートを切り替えるだけにします。

現状はリターンで真偽値を返しているのでそれを取り払う感じですね。

  // グリッド移動終了関数
  public void endGridMove() {
    _actState = 0;
  }

よく考えてみたら別にこの関数を通して真偽値をきめる必要がなかったです(笑)

ステートを変更するだけのシンプルな関数になりましたね。

果たして必要なのかどうか……

まぁ余計な値にならないのでバグは防げそうですね。

押す処理の実装

最初に言ったバグは押す処理が実装し終わったらまとめて修正します。

押す処理の実装は引く処理の反対を実装すればいいので楽ですね。

grabGridMoveのところでステートによって加算か減算かを決めるようにしてみます。

早速やっていきましょう!

    // 掴みグリッド移動関数
    protected override void grabGridMove() {
        if(_Action.IsLcastFront.collider != null) {
            float vx=0,vy=0;
            int speed = _State.ActState == 106 ? _State.MoveSpeed : -(_State.MoveSpeed);
            switch(_State.Direction) {
                case 0:
                    vy = speed/4;
                    break;
                case 1:
                    vy = -(speed/4);
                    break;
                case 2:
                    vx   = speed/4;
                    break;
                case 3:
                    vx = -(speed/4);
                    break;
            }
            _Action.IsLcastFront.transform.Translate(vx/50, vy/50, 0);
            _Player.transform.Translate(vx/50, vy/50, 0);

            // 割り切れたら位置補正
            fixedGridPosition(_State, _Action.IsLcastFront, _Player);
        }
    }

引っ張りは106なのでそのままspeedに値を入れて、それ以外の時はマイナスを掛けたものを入れます。

こうすることで押す引く逆の移動ができるようになりました。

三項演算子便利ですね。

便利がゆえに入り組んでくると可読性が落ちてくるので、
こういったシンプルな時以外はあまり使わない方が賢明です。

次に位置補正をするための関数「fixedGridPosition」も修正します。

    // 割り切れたら位置補正
    private void fixedGridPosition(State_Player state, RaycastHit2D castFront, GameObject player) {
        // 見やすいようにローカル変数を使用
        Vector3 castPos = castFront.transform.position;
        Vector3 playerPos = player.transform.position;
        // 割り切れたらTrue
        bool cxF = false;
        bool cyF = false;
        switch(state.Direction) {
            case 0:
            case 2:
                if (state.ActState == 106) {
                    cxF = Math.Ceiling(castPos.x)%16 == 0 ? true : false;
                    cyF = Math.Ceiling(castPos.y)%16 == 0 ? true : false;
                } else {
                    cxF = Math.Floor(castPos.x)%16 == 0 ? true : false;
                    cyF = Math.Floor(castPos.y)%16 == 0 ? true : false;
                }
                break;
            case 1:
            case 3:
                if (state.ActState == 106) {
                    cxF = Math.Floor(castPos.x)%16 == 0 ? true : false;
                    cyF = Math.Floor(castPos.y)%16 == 0 ? true : false;
                } else {
                    cxF = Math.Ceiling(castPos.x)%16 == 0 ? true : false;
                    cyF = Math.Ceiling(castPos.y)%16 == 0 ? true : false;
                }
                break;
            default:
                break;
        }


        // xもyも16で割り切れたら強制ステート0
        if(cxF && cyF) {
            // 位置補正
            switch(state.Direction) {
                case 0:
                case 2:
                    if (state.ActState == 106) {
                        castFront.transform.position = new Vector3((float)Math.Ceiling(castPos.x),(float)Math.Ceiling(castPos.y),0);
                        player.transform.position = new Vector3((float)Math.Ceiling(playerPos.x),(float)Math.Ceiling(playerPos.y),0);
                    } else {
                        castFront.transform.position = new Vector3((float)Math.Floor(castPos.x),(float)Math.Floor(castPos.y),0);
                        player.transform.position = new Vector3((float)Math.Floor(playerPos.x),(float)Math.Floor(playerPos.y),0);
                    }
                    break;

                    break;
                case 1:
                case 3:
                    if (state.ActState == 106) {
                        castFront.transform.position = new Vector3((float)Math.Floor(castPos.x),(float)Math.Floor(castPos.y),0);
                        player.transform.position = new Vector3((float)Math.Floor(playerPos.x),(float)Math.Floor(playerPos.y),0);
                    } else {
                        castFront.transform.position = new Vector3((float)Math.Ceiling(castPos.x),(float)Math.Ceiling(castPos.y),0);
                        player.transform.position = new Vector3((float)Math.Ceiling(playerPos.x),(float)Math.Ceiling(playerPos.y),0);
                    }
                    break;
                default:
                    break;
            }
            // ステートを強制的に0に戻す
            state.endGridMove();
        }
    }

endGridMove関数を最後に持ってきました。

こうすることで最期の補正もちゃんとできます。

これに気付くまでなんで微妙にずれるんだろうなと思ってたのですが、
最初にステート0にしてたら分岐一切きかなくなってたわけです(笑)

これで押すも処理は完璧ですね!

掴みバグを直す

何度か押す引く処理を検証してて引いてる最中に連打しながらGを押してたら
虚無をつかんでエラーで止まってしまうバグが発生しています。

どうやら数フレーム単位でディレクションを動かせてしまうようなので
移動が終わったら強制0でなくて5にしてみたところ、問題なくバグが解消された感じがします!

とりあえずこの状態で一旦様子見ですね……

  // グリッド移動終了関数
  public void endGridMove() {
    _actState = 5;
  }

それでは!