【Unity2d】引っ張ると押す処理の再実装:後編

Unity2D

Unity2D ARPG

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

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

設計力が甘いというか未だに行き当たりばったりで作ってるので、
ちゃんとやってたと思っても後に弊害が出てきたりしていますがなんとか成長している感はあります。

前編で引っ張ると押すのメソッドを呼び出すところまでは行けました。

問題はステートをディレクションをきめる箇所で決定してしまっていたことです。

いきなり役割無視をしてしまっていましたね。

ちゃんとsetState関数で切り替えるように変更してみましょう。

  // 押しているキーによってステートを変更
  protected void setState(List<KeyCode> keyList, List<KeyCode> arrowDirect) {
    // とりあえずステートリセット(その場止まり)
    _actState = 0;
    // 移動状態にするかどうか
    if (keyList.Contains(KeyCode.DownArrow) || keyList.Contains(KeyCode.UpArrow) || keyList.Contains(KeyCode.LeftArrow) || keyList.Contains(KeyCode.RightArrow)) {
      _actState = 1;
    }
    // 掴み状態にする(今はグリッド切り替えよう)
    if (keyList.Contains(KeyCode.G)) {
      _actState = 5;
      // 指定のステートの場合は何もしない
      if (_actState >= 5 && _actState <= 7) {
        switch (_direction ) {
          case 0:
            if (arrowDirect[0] == KeyCode.UpArrow) { _actState = 6; }
            if (arrowDirect[0] == KeyCode.DownArrow) { _actState = 7; }
            break;
          case 1:
            if (arrowDirect[0] == KeyCode.DownArrow) { _actState = 6; }
            if (arrowDirect[0] == KeyCode.UpArrow) { _actState = 7; }
            break;
          case 2:
            if (arrowDirect[0] == KeyCode.RightArrow) { _actState = 6; }
            if (arrowDirect[0] == KeyCode.LeftArrow) { _actState = 7; }
            break;
          case 3:
            if (arrowDirect[0] == KeyCode.LeftArrow) { _actState = 6; }
            if (arrowDirect[0] == KeyCode.RightArrow) { _actState = 7; }
            break;
        }
      }
    }
  }

第二引数にarrowDirectも渡しているので注意してください。

Gキーを押してる時に強制で5になってその後は前後で6か7に切り替わるといった感じです。

何も押さなければ5に戻る感じです。

これはそのままですね。

これで押す引く関数を呼び出すことが出来るようになりました。

引くの処理

引く関数は掴んだオブジェクトとプレイヤーを後ろに移動させます。

キャラクター以外はグリッド移動にしないと色々とシビアなゲームになってしまうので
早速グリッド移動を設けてみましょう。

グリッド移動開始している時はプレイヤーと対象物は一切操作出来ないようにしておきます。

そうしないとグリッド移動処理が破綻してしまいますのでしっかりとやりましょう。

まずは引くメソッドが呼ばれた瞬間キー入力を制限する仕組みを作ります。

いわゆるグリッド移動中かどうかですね。

新たなステート変数を作るのももったいないので現状のステートに+100とすれば、
「_actState」を流用出来そうです。

早速やってみましょう。

  // 押しているキーによってステートを変更
  protected void setState(List<KeyCode> keyList, List<KeyCode> arrowDirect) {
    // グリッド移動中であれば関数を抜ける
    if (_actState == 106 || _actState == 107) {
      return;
    }
    // とりあえずステートリセット(その場止まり)
    _actState = 0;
    // 移動状態にするかどうか
    if (keyList.Contains(KeyCode.DownArrow) || keyList.Contains(KeyCode.UpArrow) || keyList.Contains(KeyCode.LeftArrow) || keyList.Contains(KeyCode.RightArrow)) {
      _actState = 1;
    }
    // 掴み状態にする(今はグリッド切り替えよう)
    if (keyList.Contains(KeyCode.G)) {
      _actState = 5;
      if (_actState >= 5 && _actState <= 7) {
        // 十字キーがどれか1つ押されて居たら稼働
        if(arrowDirect.Count > 0) {
          switch (_direction ) {
            case 0:
              if (arrowDirect[0] == KeyCode.UpArrow) { _actState = 6; }
              if (arrowDirect[0] == KeyCode.DownArrow) { _actState = 7; }
              break;
            case 1:
              if (arrowDirect[0] == KeyCode.DownArrow) { _actState = 6; }
              if (arrowDirect[0] == KeyCode.UpArrow) { _actState = 7; }
              break;
            case 2:
              if (arrowDirect[0] == KeyCode.RightArrow) { _actState = 6; }
              if (arrowDirect[0] == KeyCode.LeftArrow) { _actState = 7; }
              break;
            case 3:
              if (arrowDirect[0] == KeyCode.LeftArrow) { _actState = 6; }
              if (arrowDirect[0] == KeyCode.RightArrow) { _actState = 7; }
              break;
          }
          // もし_actStateが6か7であればグリッド移動中ステートに変更
          if (_actState == 6 || _actState == 7 ) {
            _actState = _actState+100;
          }
        }
      }
    }
  }

これで対象をつかんでいる状態で前後を押せばステートが100プラスされて
グリッド移動状態になりました。

106か107の場合はステート変更も行いません。

関数の先頭にリターンを設けています。

これによりディレクションも変更できないようにしてしまいましょう。

  // 向き変数変更
  protected void setDirection(List<KeyCode> arrowDirect) {
    // 指定のステートの場合は何もしない
    if (_actState >= 5 && _actState <= 7 || _actState == 106 || _actState == 107) {
      return;
    }

    // 省略
  }

一応Atcion_Playerのコードも載せておきます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Action_Player : Action_Manager
{

    // プレイヤーオブジェクト
    private GameObject _Player;
    // プレイヤーステートスクリプトの取得
    private State_Player _State;

    [SerializeField]
    private LayerMask _layerMaskGrab;

    // コンストラクタ
    protected override void Start() {

        // Linecast発生ポイント座標
        castPositionFront = new Vector3(0,0,0);
        castPositionBack = new Vector3(0,0,0);
        castPositionObjBack = new Vector3(0,0,0);
        castPositionDistance = new Vector3(0,0,0);
        DummyVector3 = new Vector3(0,0,0);        
        // プレイヤーオブジェクトの取得
        _Player = GameObject.FindGameObjectsWithTag("Player")[0];
        _State = GameObject.FindGameObjectsWithTag("State_Manager")[0].GetComponent<State_Player>();

    }
    // 更新処理
    protected override void Update() {
        Grab();
    }

    // 掴み処理
    protected override void Grab() {
        if (_State.ActState >= 5 && _State.ActState <= 7 || _State.ActState == 106 || _State.ActState == 107) {
            // 衝突判定をしたオブジェクトのcolliderがnullでなければ
            if (getLineCast2Object(_State.Direction, _Player, _layerMaskGrab, true).collider != null ) {
                Debug.Log(_State.ActState);
                switch (_State.ActState) {
                    case 106:
                        Pull();
                        break;
                    case 107:
                        Push();
                        break;
                    default:
                        break;
                }
            }
        }
    }
    // 引っ張り処理
    protected override void Pull() {
        Debug.Log("引っ張り");
    }
    // 押す処理
    protected override void Push() {
        Debug.Log("押し");
    }

}

掴み処理のところを少し変えました。

該当ステートの時Linecastで判定を飛ばし、グリッド移動中の時のみPullかPush関数を呼び続けます。

これでPullかPushにグリッド移動処理を書けばOKです。

しかしアクションに移動処理を書きたくないのですが、一旦コチラに書いておきます。

次回、回りくどいかもしれませんがMove関数側に対象を渡して動かせるように修正しましょう。

とりあえずこのままだと衝突判定を取ったオブジェクトを確保してないので
Action_Managerで定義した「is_lcastFront」に保持するようにしてみましょう。

もう一度改良したAction_Playerを載せます。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Action_Player : Action_Manager
{

    // プレイヤーオブジェクト
    private GameObject _Player;
    // プレイヤーステートスクリプトの取得
    private State_Player _State;

    [SerializeField]
    private LayerMask _layerMaskGrab;

    // コンストラクタ
    protected override void Start() {

        // Linecast発生ポイント座標
        castPositionFront = new Vector3(0,0,0);
        castPositionBack = new Vector3(0,0,0);
        castPositionObjBack = new Vector3(0,0,0);
        castPositionDistance = new Vector3(0,0,0);
        DummyVector3 = new Vector3(0,0,0);        
        // プレイヤーオブジェクトの取得
        _Player = GameObject.FindGameObjectsWithTag("Player")[0];
        _State = GameObject.FindGameObjectsWithTag("State_Manager")[0].GetComponent<State_Player>();

    }
    // 更新処理
    protected override void Update() {
        Grab();
    }

    // 掴み処理
    protected override void Grab() {
        if (_State.ActState >= 5 && _State.ActState <= 7 || _State.ActState == 106 || _State.ActState == 107) {
            // 衝突判定をしたオブジェクトのcolliderがnullでなければ
            is_lcastFront = getLineCast2Object(_State.Direction, _Player, _layerMaskGrab, true);
            if (is_lcastFront.collider != null ) {
                Debug.Log(_State.ActState);
                switch (_State.ActState) {
                    case 106:
                        Pull();
                        break;
                    case 107:
                        Push();
                        break;
                    default:
                        break;
                }
            }
        }
    }
    // 引っ張り処理
    protected override void Pull() {
        Debug.Log("引っ張り");
        if(is_lcastFront.collider != null) {
            float vx=0,vy=0;
            int speed = 30;
            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;
            }
            is_lcastFront.transform.Translate(vx/50, vy/50, 0);
            _Player.transform.Translate(vx/50, vy/50, 0);
        }
        // xもyも16で割り切れたら
        if(Math.Floor(is_lcastFront.transform.position.x)%16 == 0 && Math.Floor(is_lcastFront.transform.position.y)%16 == 0) {
            Debug.Log("割り切れた");
        }

    }

    // 押す処理
    protected override void Push() {
        Debug.Log("押し");
    }


}

これで掴んで引っ張ることが出来るはずです。

ただ、割り切れた後の処理を作ってないので動き続けています。

次回は移動処理を移動スクリプトに移して割り切れた場合止まるようにしてみましょう。

それでは。