超初心者のゲーム開発記~Unity~

超初心者がUnityでゲーム(目標はAndroidアプリ )を開発していくブログです!

【Unity 2Dローグライク】公式チュートリアルをやってみる part.7~オブジェクトの動かし方

こんばんは!ヤギです!

Unityの2Dローグライクの
公式チュートリアルをやってみる part.7になります!
※前回(part.6)の記事はこちら
www.yagigame.com

記事概要

今回の記事では、プレイヤーや敵などのオブジェクトを動かすためのスクリプトについてご説明していきます。
※今回作成するスクリプトは抽象クラスとなります。
※part.7に対応する公式チュートリアルの章は、Moving Object Scriptです!
unity3d.com
※この記事は、ひよこのたまご様の記事をリスペクトしています。
hiyotama.hatenablog.com

オブジェクトを動かすスクリプトの作成

1. MovingObject.csを作成します。
2. ソースを書いていきます。
※解説をコード内に記載いたしました。ご参照ください。

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

//抽象クラスとして作成していく
public abstract class MovingObject : MonoBehaviour {

    public float moveTime = 0.1f; //    //動く時間
    public LayerMask blockingLayer;

    private BoxCollider2D boxCollider; //コンポーネント
    private Rigidbody2D rd2D; //コンポーネント
    private float inverseMoveTime;

    // Use this for initialization
    //継承クラスでオーバーライドできるようにする
    protected virtual void Start () {
        //コンポーネントを取得する
        boxCollider = GetComponent<BoxCollider2D>();
        rd2D = GetComponent<Rigidbody2D>();
        inverseMoveTime = 1f / moveTime;
	}
	
    //移動可能か判断する ※blockingLayerに衝突する場合、移動しない
    //boolはtrueかfalseを返す
    //outで指定した変数は、取得可能になる
    protected bool Move(int xDir,int yDir, out RaycastHit2D hit){
        //現在地を取得
        Vector2 start = transform.position;
        //移動先を取得
        Vector2 end = start + new Vector2(xDir, yDir);
        //自身のColliderを一旦無効化する ※startとendの間にblockingLayerがあるか確認するときに不要なため
        boxCollider.enabled = false;
        //現在地と移動先の間にblockingLayerがあるか確認、ある場合取得
        hit = Physics2D.Linecast(start, end, blockingLayer);
        //確認が終わったため、Colliderを有効化する
        boxCollider.enabled = true;

        //現在地と移動先の間に、BlockingLayerがなければ移動する
        if(hit.transform == false){
            StartCoroutine(SmoothMovement(end));
            //移動可能
            return true;
        }

        //移動不可
        return false;
    }

    //継承クラスでオーバーライドできるようにする
    //移動を試し、書が異物がある場合、移動不可の場合の処理を呼び出す
    protected virtual void AttemptMove <T>(int xDir, int yDir)
            where T : Component //後からコンポーネントを決める
    {
        RaycastHit2D hit;
        //Moveメソッドを実行し、移動可能か判定する
        bool canMove = Move(xDir, yDir, out hit);
        //hitがnullの場合 ※現在地から目的地の間にblockingLayerに該当するものがない場合
        if(hit.transform == null){
            return;
        }
        //現在地から目的地の間にblockingLayerに該当するものがある場合
        //障害物のコンポーネントを取得
        T hitComponet = hit.transform.GetComponent<T>();

        //障害物がある場合、移動不可の場合の処理を呼び出す
        if(!canMove && hitComponet != null){
            OnCantMove(hitComponet);
        }

    }

    //現在地から目的地までの距離を求めて移動する
    protected IEnumerator SmoothMovement(Vector3 end){
        //目的地までの距離を計算 ※現在地:transform.position、目的地:end、距離を求める:.sqrMagnitude
        float sqrRemainingDistance = (transform.position - end).sqrMagnitude;

        //目的地に限りなく近くまで繰り返し実行する
        while(sqrRemainingDistance > float.Epsilon){
            //1フレームあたりの移動距離を計算する ※Time.deltaTime:1フレームあたりの時間
            Vector3 newPosition = Vector3.MoveTowards(rd2D.position, end, inverseMoveTime * Time.deltaTime);
            //移動距離分、移動する
            rd2D.MovePosition(newPosition);
            //移動した場所から、目的地までの距離を再計算する
            sqrRemainingDistance = (transform.position - end).sqrMagnitude;
            //移動するのに1フレーム使うため、1フレーム待機
            yield return null;
        }
    }

    //抽象クラス 
    protected abstract void OnCantMove<T>(T component)
        where T : Component;
}

スクリプトの説明

  • Generic機能:後から、型を指定する機能になります。障害物が敵と壁というように複数ある際に、どちらに衝突しているかで、衝突後の処理を変えるために使います。
  • 抽象クラス:継承して使うためのクラスです。※抽象クラスだけでは、処理が完成しません。
  • 継承クラス:抽象クラスを継承して使います。※抽象クラス内のabstractを指定したメソッドを上書きして処理を行えるようにします。
  • AttemptMove (int xDir, int yDir):移動を試し、障害物がある際は、移動不可の場合の処理を呼び出します。
  • Move(int xDir,int yDir, out RaycastHit2D hit):移動可能か判断します。可能な場合移動します。※AttemptMoveから呼び出されます。
  • SmoothMovement(Vector3 end):現在地から目的地までの距離を求めて移動します。
  • OnCantMove(T component):障害物がある場合の処理を行います。※Generic機能を使い、障害物(敵や壁)によって処理を切り替えます。

次回予告

次回の記事では、壊せる壁の作り方について書いていきたいと思います。
※次回の記事はこちら
www.yagigame.com

※Unityのチュートリアルの章としては、次回は(Creating Destructible Walls)となります!

読んでいただきありがとうございました!