【Unity】ScrollRectで、スクロールの制御をする

Unity

 

こんばんは、ちきなるです。

 

今、カードゲームを作っているのですが・・・。

 

Scroll Viewが、言うことを聞いてくれない!!

あーしたい。

こーしたい。

 

色々あるのですが、思うように動いてくれません。

 

ネットで調べたり、実際に動かしたり、試行錯誤。

 

何とか、

最低限の動きが出来たので、書いておきます。

具体的に言うと、

スクロールの制御。

 

条件を満たすと、スクロールをして、

満たさないと、スクロールをしない。

(カードの一覧をスクロールさせたり、カードを掴んだりしたい)

 

参考にさせて、いただいたのは、

こちらのブログ。

【Unity】ScrollViewに配置しているオブジェクトをDragAndDropする | KAZUPON研究室
ScrollViewのコンテンツに配置してあるGameObjectをスクロール処理と干渉しない様にドラッグ&ドロップさせるコンポーネントです。 実装のポイントは二つ。 親のスクロー...

 

なのですが、

私の頭では、理解しきれませんでした。

 

なんとなくは、わかるのですが、

応用出来るほど、理解出来ませんでした。

(ゲームに合わせた調整が出来なった)

 

なので、

これは、こうかな?

と、試して、上手くいった方法を書いておきます。

 

 

ScrollRectを継承させる

まずは、

Scriptを作って、ScrollRectを継承させます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
//ScrollRectを継承する
public class ScrollTest : ScrollRect
{

}

 

これをすると、

Scroll Viewでのマウスイベントを取ることが出来ます。

ですが、

ScrollRectを継承した後、Scroll Viewにスクリプトを追加しようとすると、エラーが出ます。

(Inspectorビューで追加)

(ScrollRectが、重複しているよ。って、エラーです)

 

なので、

元々ついている、ScrollRectを削除(Remove Component)して、

 

追加します。

設定は、リセットされるので、入力し直す必要があります。

 

Content, Viewport, Horizontal Scrollbar, Vertival Scrollbarを忘れない。

(Scroll Viewを追加した時、自動で入力されるので、ScrollRectを変える時は、要注意)

 

ScrollRectのイベント

ScrollRectで、使うイベントは4つ。

    //Scroll Viewでマウスボタン押下時    
    public override void OnInitializePotentialDrag(PointerEventData eventData)
    {
        //継承元のOnInitializePotentialDrag処理を呼び出す
        base.OnInitializePotentialDrag(eventData);
    }

    //マウスボタン押下中に初めてマウスを動かした時
    public override void OnBeginDrag(PointerEventData eventData)
    {
        //継承元のOnBeginDrag処理を呼び出す
        base.OnBeginDrag(eventData);
    }

    //マウスボタン押下中にマウスを動かしている間
    public override void OnDrag(PointerEventData eventData)
    {
        //継承元のOnDrag処理を呼び出す
        base.OnDrag(eventData);
    }

    //マウスボタンを放した時
    public override void OnEndDrag(PointerEventData eventData)
    {
        //継承元のOnEndDrag処理を呼び出す
        base.OnEndDrag(eventData);
    }

Scroll Viewで、マウスボタンを押下した時に、

OnInitializePotentialDragが、呼ばれます。

(左右どちらでも呼ばれる)

 

その後、

ボタン押下中に、始めてマウスを動かすと、

OnBeginDragが、呼ばれます。

 

ボタン押下中に、マウスを動かしている間は、

OnDragが、呼ばれ続ける。

(動かしている間は、何度も呼ばれる。

 止めている間は、呼ばれない)

 

ボタンを離すと、

OnEndDragが、呼ばれます。

OnInitializePotentialDragマウスボタンを押下した時
OnBeginDragボタン押下中にマウスが初めて動いた時
OnDragボタン押下中にマウスが動いている間
OnEndDragマウスボタンを離した時

 

 

スクロールを止める

どうやって、スクロールを止めるのか。

 

それは、

継承元のOnBeginDragまたはOnDragを呼ばない。

(どちらかを呼ばないようにすると、スクロールしなくなりました)

(動き的には、OnDragを呼ばないようにする方が、良い気がします)

//マウスボタン押下中にマウスを動かしている間
    public override void OnDrag(PointerEventData eventData)
    {
        //継承元のOnDrag処理を呼び出す
        //base.OnDrag(eventData);
    }

こうすると、スクロールしなくなります。

ですが、

このままだと、Scroll Viewの意味が無くなるので、

条件分岐で、スクロールの有無を判定させます。

 

(マウスの動きが、

 横方向なら、スクロールする

 縦方向なら、スクロールしない)

    //スクロールするかどうかのフラグ
    private bool MoveChack = false;

    //マウスボタン押下中に初めてマウスを動かした時
    public override void OnBeginDrag(PointerEventData eventData)
    {
        //継承元のOnBeginDrag処理を呼び出す
        base.OnBeginDrag(eventData);
        if (Mathf.Abs(eventData.delta.x) < Mathf.Abs(eventData.delta.y))
        {
            MoveChack = false;
            return;
        }
        MoveChack = true;
    }

    //マウスボタン押下中にマウスを動かしている間
    public override void OnDrag(PointerEventData eventData)
    {
        if(MoveChack)
            //継承元のOnDrag処理を呼び出す
            base.OnDrag(eventData);
    }

eventData.deltaってのは、マウスの動いた距離が見れます。

 

説明だと、最後の更新からのデルタポインタ。

と、なっているのですが、デルタポインタがわかりません。

 

多分、

最後の更新時のマウスの位置から、現在のマウスの位置の方向ベクトルかな?

と、思います。

(Mathf.Absで、絶対値を出して比較すれば、

 縦横どちらが大きく動いたのか、わかります)

 

まとめ。

 

ScrollRecを継承すると、

Scroll Viewに対する、マウスのイベントが取れます。

IInitializePotentialDragHandler, IBeginDragHandler, IEndDragHandler, IDragHandlerこれを継承させて、Scroll Viewにスクリプトを付けても同じ事が出来ます)

OnInitializePotentialDragが、ボタン押下時。

OnBeginDragが、ボタン押下中にマウスが始めて動いた時

OnDragが、ボタン押下中に、マウスが動いている間

OnEndDragが、ボタンを離した時。

OnInitializePotentialDragマウスボタンを押下した時
OnBeginDragボタン押下中にマウスが初めて動いた時
OnDragボタン押下中にマウスが動いている間
OnEndDragマウスボタンを離した時

継承元の、

OnBeginDragまたは、OnDrag

どちらかを呼ばないようにすると、スクロールしなくなります。

OnDragを止める方が良さそう)

マウスが横に動いた時、スクロールする。

マウスが縦に動いた時、スクロールしない。

(1度のクリック中常に)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

//ScrollRectを継承する
public class ScrollTest : ScrollRect
{
    //Scroll Viewでマウスボタン押下時    
    public override void OnInitializePotentialDrag(PointerEventData eventData)
    {
        //継承元のOnInitializePotentialDrag処理を呼び出す
        base.OnInitializePotentialDrag(eventData);
    }

    //スクロールするかどうかのフラグ
    private bool MoveChack = false;

    //マウスボタン押下中に初めてマウスを動かした時
    public override void OnBeginDrag(PointerEventData eventData)
    {
        //継承元のOnBeginDrag処理を呼び出す
        base.OnBeginDrag(eventData);
        //マウスの動きが縦か横の判定
        if (Mathf.Abs(eventData.delta.x) < Mathf.Abs(eventData.delta.y))
        {
            //縦ならスクロールを止める
            MoveChack = false;
            return;
        }
        //横ならスクロールする
        MoveChack = true;
    }

    //マウスボタン押下中にマウスを動かしている間
    public override void OnDrag(PointerEventData eventData)
    {
        //横の時スクロールする
        if(MoveChack)
            //継承元のOnDrag処理を呼び出す
            base.OnDrag(eventData);
    }

    //マウスボタンを放した時
    public override void OnEndDrag(PointerEventData eventData)
    {
        //継承元のOnEndDrag処理を呼び出す
        base.OnEndDrag(eventData);
    }
}

てな感じです。

 

 

スクロールを止めることが出来たので、

縦方向にドラッグした時、

カードを掴んで、デッキに追加する処理を作れば完璧です!!

コメント

タイトルとURLをコピーしました