トマシープが学ぶ

Unity/VR/AR/デザイン好きのミーハー 記事内容は自分用のメモです

Unityの自動スクロール

ScrollViewの下にコンテンツがたまっていったときに、一番下にスクロールして最新のコンテンツが見えるようにしてほしい。LINEみたいな感じ

Scrollbar

観察してたらScrollbarのValueの0~1でスクロール位置が決まっている。

f:id:bibinbaleo:20210308173347p:plain

docs.unity3d.com

DirectionをButtonToTopにしているときは、Value=0で一番下に行く!

ならコンテンツが追加されたときにValueを0にしたらいい

_Scrollbar.value = 0.0f;

docs.unity3d.com

これでやったけど、完全には下に行かない・・・少し下に下がるけど数値が0にならない;;

 

この人もチャット追加時に、スクロールバーの位置を変えている

scrollPos.y = Mathf.Infinity;

uniblo.biz

scrollRect.verticalNormalizedPosition

ググったら他の方法もあった

application.hateblo.jp

scrollRect.verticalNormalizedPosition = 0.0f;

docs.unity3d.com

これは内部的な値なんだろうか。

これでも試したけど、Scrollbarと同じような挙動で、少し下に行くけど完全にはいかない。

コルーチン使う

ここで議論されていた

forum.unity.com

スクロールrectを更新するのに1フレームかかるため、コードはおそらくUpdateでのみ機能します。そのコードをコルーチンに配置し、フレームの終わりを待つと、機能するはずです。

だって。

1フレーム??チャットが追加されるときに1回呼び出すだけじゃダメなのか?

スレッドにあったコード。コルーチンで1フレーム待って、Canvasのフォーカスしたあと、スクロールバー動かして、再度Canvasフォーカスしている

  1. // Called at the end of instantiation function.
  2.     IEnumerator ForceScrollDown () {
  3.         // Wait for end of frame AND force update all canvases before setting to bottom.
  4.         yield return new WaitForEndOfFrame ();
  5.         Canvas.ForceUpdateCanvases ();
  6.         comScroll.verticalNormalizedPosition = 0f;
  7.         Canvas.ForceUpdateCanvases ();
  8.     }

docs.unity3d.com

他のコメントには2フレーム待っているものもあった

  1.            // auto-scroll
  2.            if (gameObject.activeSelf)
  3.            {
  4.                StartCoroutine(AutoScroll());
  5.            }
  6.        }
  7.  
  8.        private IEnumerator AutoScroll()
  9.        {
  10.            LayoutRebuilder.ForceRebuildLayoutImmediate(container);
  11.            yield return new WaitForEndOfFrame();
  12.            yield return new WaitForEndOfFrame();
  13.            scrollRect.verticalNormalizedPosition = addNewToTop ? 1 : 0;
  14.        }

私の場合は1回呼び出すだけで動いた

            // スクロールバーを一番下にする。
            StartCoroutine(ForceScrollDown());
        }

        IEnumerator ForceScrollDown()
        {
            // 1フレーム待たないと完全に実行されない
            yield return new WaitForEndOfFrame();
            _ScrollRect.verticalNormalizedPosition = 0.0f;
        }

これは良いやり方なのだろうか?