【Unity】アプリで画面タッチを利用したカメラスクロール

Unityカメラスクロール
スポンサーリンク

Unityのアプリで、画面タッチを利用したカメラのスクロール処理を実装します。今回は、スマホ画面のタッチ(スワイプ操作)にある程度追従する形でカメラを動かします。

また、スマホだけでなくPC操作の際はマウスでも操作できるように調整したいと思います。

こんな人におすすめ

・アプリで画面タッチを利用したカメラスクロールを行いたい
・PCでもスクロールを行いたい

プロジェクトの準備

まず初めに、今回は以下の記事で昔書いたスワイプ処理を利用します。

記事のサンプルコードの項目に、以下の「ScreenInput」がありますので、コピーしてスクリプトを作っておいてください。

スクリプト参考

スクリプトがコピーできたら、プロジェクト内に空のオブジェクトを作り、アタッチを行います。ちょうどプロジェクトが以下のような状態になればOKです。

プロジェクトの状態

※プラットフォームはiOSまたはAndroidに変更しておきます。

また、スクロール状態を確認しやすいように、Cubeのオブジェクトを一つ出し、さらにカメラを傾けて斜め下を見ている状態にしておきます。今回はこの位置を基準にスクロール処理を実装していきたいと思います。

カメラの角度

サンプルコード

次に実際にカメラを動かすためのサンプルコードを実装します。以下のコードをコピーして、カメラにアタッチしてください。

■CameraMove

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

public class CameraMove : MonoBehaviour
{
    [SerializeField]
    private ScreenInput _input;
    [SerializeField]
    private float Speed = 0.02f;
    private bool MoveFlg;
    private Vector3 pos;

    // カメラ位置の更新
    void Update()
    {
        if(_input.GetNowSwipe() != ScreenInput.SwipeDirection.NONE)
        {
           if(!MoveFlg) pos = this.transform.localPosition;
            MoveFlg = true;

            this.transform.localPosition = new Vector3(
                pos.x - _input.GetSwipeRangeVec().x * Speed,
                pos.y,
                pos.z - _input.GetSwipeRangeVec().y * Speed);
        }
        else
        {
            MoveFlg = false;
        }
    }
}

メインカメラにアタッチしたら、ScreenInputの設定されているオブジェクトをインスペクターに設定してください。

アタッチ後の画面

これで、スクロール処理の実装は完了です。実際に再生して、Game画面でマウスの左クリックを押しっぱなしにしてカーソルを左右に動かしてみてください!

※スクロールのスピードが速いと感じた場合はインスペクターにある「Speed」の値を下げてみてください。

追加実装 ピンチイン・ピンチアウト

追加の実装として、ピンチインとピンチアウト(拡大と縮小)を実装してみたいと思います。こちらも比較的簡単に実装できるので、ぜひ試してみてください!

まずはScreenInputに以下のコードを追加します。行数は201行目付近でOKです。

// ピンチイン・ピンチアウト
private bool PinchFlg;
private float PinchDistance;
private float PinchSpeed = 0.02f;
private float PinchMin = -20;
private float PinchMax = 20;
private Vector3 UnityPinchStartPos;
private float StartDistance;
private float PinchAdj;
private void CheckPinch()
{
    if (Input.touchCount == 2 || Input.GetMouseButton(1))
    {
        // Unity上での操作取得
        if (Application.isEditor)
        {
            if (!PinchFlg) UnityPinchStartPos = Input.mousePosition;
            PinchFlg = true;
            if (UnityPinchStartPos.y < Input.mousePosition.y) PinchAdj = 1.0f;
            else PinchAdj = -1.0f;
            PinchDistance += Vector3.Distance(UnityPinchStartPos, Input.mousePosition) * PinchAdj * PinchSpeed * Time.deltaTime;
            if (PinchDistance < PinchMin) PinchDistance = PinchMin;
            else if (PinchMax < PinchDistance) PinchDistance = PinchMax;
        }
        // 端末上での操作取得
        else
        {
            if (!PinchFlg) StartDistance = Vector2.Distance(Input.touches[0].position, Input.touches[1].position);
            PinchFlg = true;
            if (StartDistance < Vector2.Distance(Input.touches[0].position, Input.touches[1].position)) PinchAdj = 1.0f;
            else PinchAdj = -1.0f;
            PinchDistance += Vector2.Distance(Input.touches[0].position, Input.touches[1].position) * PinchAdj * PinchSpeed * Time.deltaTime;
            if (PinchDistance < PinchMin) PinchDistance = PinchMin;
            else if (PinchMax < PinchDistance) PinchDistance = PinchMax;
        }
    }
    else
    {
        PinchFlg = false;
    }
}

// 制限設定
public void SetPinchLimits(float _min, float _max, float _speed)
{
    PinchMin = _min;
    PinchMax = _max;
    PinchSpeed = _speed;
}

// フラグ取得
public bool GetPinchFlg()
{
    return PinchFlg;
}

// 距離取得
public float GetPinchDistance()
{
    return PinchDistance;
}
追加の位置

追加後は48行目のUpdateに「CheckPinch()」を追加します。追加は51行目に行えばOKです。

追加の確認

ここまで追加できたら、上書き保存を行いCameraMoveの編集を行います。

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

public class CameraMove : MonoBehaviour
{
    [SerializeField]
    private ScreenInput _input;
    [SerializeField]
    private float Speed = 0.02f;
    private bool MoveFlg;
    private Vector3 pos;
    private Camera _camera;
    private float StartFieldOfView;

    private void Start()
    {
        _input.SetPinchLimits(-20, 20, 0.2f);
        _camera = this.transform.GetComponent<Camera>();
        StartFieldOfView = _camera.fieldOfView;
    }

    // カメラ位置の更新
    void Update()
    {
        if (_input.GetNowSwipe() != ScreenInput.SwipeDirection.NONE && !_input.GetPinchFlg())
        {
            if (!MoveFlg) pos = this.transform.localPosition;
            MoveFlg = true;

            this.transform.localPosition = new Vector3(
                pos.x - _input.GetSwipeRangeVec().x * Speed,
                pos.y,
                pos.z - _input.GetSwipeRangeVec().y * Speed);
        }
        else
        {
            MoveFlg = false;
        }

        if (_input.GetPinchFlg())
        {
            _camera.fieldOfView = StartFieldOfView - _input.GetPinchDistance();
        }

    }
}

あとは上書き保存を行い再生をするだけです。Unityでの操作は、Game画面上で右クリックを押したままカーソルを上もしくは下に動かすことで拡大縮小が行われます。

Startで呼び出している「_input.SetPinchLimits(-20, 20, 0.2f);」でそれぞれのパラメーター制限を設定しています。第一引数から「最小値、最大値、移動速度」です。それぞれプロジェクトに合った数値を入れてお使いください。

ピンチインなどの操作を実装すると、拡大や縮小が完了した際に急にカメラがスクロールしてしまう現象が発生します。これはピンチインなどの操作中もスクロール距離を取得していることが原因です。

ScreenInputの以下の場所を「== 1」に変更すると現象が解消されます。気になる方は変更してみてください!

変更ポイント

まとめ

以上がカメラスクロールと、追加でピンチイン・ピンチアウト(拡大縮小)についてのまとめでした。Unityだと結構簡単に実装ができるようになっているので、どんどん試してみてください!