【Unity】【C#】ScrollViewをスクロールさせるボタン(Button)を実装する

#概要
RaycastTargetがtrueのGameObjectをScrollViewの中に置いたら通常のスクロールが上手く行かなかったため、スクロール用のボタンを用意してボタン長押しでスクロールするようにしました。

今回はその内容を共有します。

<blockquote class="twitter-tweet" data-conversation="none" data-lang="ja"><p lang="ja" dir="ltr">通常のタップしてスクロールするのが上手く行かなかったため、ボタンでスクロールするようにしました。押してる間スクロールします。端へ移動するボタンも用意。 <a href="https://twitter.com/hashtag/Unity?src=hash&amp;ref_src=twsrc%5Etfw">#Unity</a> <a href="https://t.co/UGw36nmHRC">pic.twitter.com/UGw36nmHRC</a></p>&mdash; アズマゴロ―@TokyoSandBox出展 (@azumagoro) <a href="https://twitter.com/azumagoro/status/981413798010552320?ref_src=twsrc%5Etfw">2018年4月4日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



#導入手順
1.Button用にImage4つをCanvas配下に置きます。名前は下記の通りにします。
LeftButton ※左へスクロールするボタン
RightButton ※右へスクロールするボタン
LeftestButton ※左端へ飛ぶボタン
RightestButton ※右端へ飛ぶボタン

2.ButtonにEventTriggerをアタッチして、「Add New EventType」からPointerUpとPointerDownを追加します。

3.ScrollView(以外でも大丈夫です)にScrollViewCtr.csをアタッチして、Buttonの種類に応じて2で用意したEventTriggerに対応するメソッドを登録します。

LeftButtonの場合（※画像ではScript名が異なります）
<img width="320" alt="スクリーンショット 2018-04-04 11.23.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/237014/e1279001-3233-bf54-dad3-c856eb9b7d73.png">

4.ScrollbarをScrollViewCtr.csの「Scrollbar」にアタッチします。
<img width="315" alt="スクリーンショット 2018-04-04 16.13.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/237014/31953148-1319-bde7-6a50-ac951bcefc56.png">

5.Gameをプレイして動作するか確認してみてください。

#コードサンプル
```C#:ScrollViewCtr.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class ScrollViewCtr : MonoBehaviour
{
	//for ScrollButton
	public Scrollbar _Scrollbar;

	//Coroutineを中断するために変数として宣言しておく
	Coroutine _Coroutine;

	//スクロールスピード
	[SerializeField]float ScrollSpeed = 0.2f;

	//LeftButtonに登録
	public void ScrollLeft ()
	{
		if (_Coroutine != null) {
			StopCoroutine (_Coroutine);
		}
		_Coroutine = StartCoroutine (TimeForScrollLeft ());
	}

	//LeftestButtonに登録
	public void ScrollLeftest ()
	{
		if (_Coroutine != null) {
			StopCoroutine (_Coroutine);
		}
		_Coroutine = StartCoroutine (TimeForScrollLeft (300f));
	}

	//左スクロールコルーチン
	IEnumerator TimeForScrollLeft (float SpeedRate = 1f)
	{
		while (_Scrollbar.value > 0) {
			_Scrollbar.value -= Time.deltaTime * ScrollSpeed * SpeedRate;
			yield return null;
		}
	}

	//Rightボタンに登録
	public void ScrollRight ()
	{
		if (_Coroutine != null) {
			StopCoroutine (_Coroutine);
		}
		_Coroutine = StartCoroutine (TimeForScrollRight ());
	}

	//RightestButtonに登録
	public void ScrollRightest ()
	{
		if (_Coroutine != null) {
			StopCoroutine (_Coroutine);
		}
		_Coroutine = StartCoroutine (TimeForScrollRight (300f));
	}

	//右スクロールコルーチン
	IEnumerator TimeForScrollRight (float SpeedRate = 1f)
	{
		while (_Scrollbar.value < 1) {
			_Scrollbar.value += Time.deltaTime * ScrollSpeed * SpeedRate;
			yield return null;
		}
	}

	//EventTriggerのPointerUpイベントに登録する処理
	public void StopScroll ()
	{
		if (_Coroutine != null) {
			StopCoroutine (_Coroutine);
		}
	}
}

```

#簡単な解説
メソッドをEventTriggerのPointDownに登録すると、RaycastTargetを押した際にメソッドが実行されます。今回登録したメソッドは、ScrollViewのScrollbar.valueを変化させるものです。

LeftButtonを例に取ります。
```ScrollLeftest ()```では、既に動いているコルーチンを停止して、その後TimeForScrollLeft()コルーチンを開始してます。

この時```_Coroutine = StartCoroutine (TimeForScrollLeft ());```としているのは、後で```StopCoroutine (_Coroutine);```で停止させるためです。

次に```TimeForScrollLeft (float SpeedRate = 1f)```を見ます。

``` 
while (true) {
            //何かの処理
            yield return null;
        }
```

コルーチン中でこう書くと、while文の条件を満たすまで時間経過ごとに処理を行うことができます。今回はScrollbar.valueの値をdeltaTimeに応じて変えてScrollbarを移動させてます。

```ScrollLeftest ()```ではScrollbar.valueの変化速度を300倍にして、一瞬で移動したように見えるようにしてます。単純に```_Scrollbar.value = 1f;```としても良いと思います。

最後に```StopScroll ()```をEventTrigger PointerUpに登録することで、RaycastTargetを押すのをやめた時にコルーチンを停止してスクロールをやめるようにしています。PointerDownに登録するメソッドでも最初にコルーチンを停止するようにしてますが、これは同時にボタンを押した時に後から押した方のメソッドを実行させるためです。


以上になります。

参考になった場合はいいねをお願いします〜