maimai_jp's blog

twitterでは書ききれないことなどをこちらに。

【unity】ScrollRectを使ったScrollViewでスクリプトから位置を移動したい時の話。【ugui】

困ったときのサンプル参照先で毎度お馴染みテラシュールブログさんを参考にuguiでスクロールビューを作ってみたわけなんですけれども。


UnityのuGUIでスクロールビューを作る - テラシュールブログ

とりあえずマウスのドラッグとかフリックとかでスクロールできるものは作れたわけですが、困ったことにこのスクロールした位置をスクリプト側から制御する方法がわからない。

今回やりたかったことは、「新規に突っ込んだアイテムが画面内に入るよう自動的にスクロールさせて調整する」といったもの。

インスペクタ右上の三本線からDebugモードにしてパラメータまわりを覗いても、どうにも動いてるパラメータはScrollRectのPrevPositionという値。

しかしこちらの値はprivateな上に、どうやらどこかから引っ張ってきた値らしく、こちらを変更したところでスクロールの位置が変わるとも思えない。

……結論から言えば、子オブジェクト側のRectTransformのインスペクタが自動更新されておらず、値の変化がわからなかったという事実が発覚。


Watch maimai's Vine "わかったーーーー!!! ScrollRectでスクロールさせた値が子オブジェクト側に影響してない、と思って親側のパラメータ漁ってたのに、実は更新された子オブジェクトのRectTransformにInspectorの自動更新がかかってなかったんじゃねえかッ!!"

クリックして最新値が更新されるというね。

ともあれ、この値を変更すればスクロールが制御できることがわかってめでたしめでたし。



……とはうまくいかないものですよね。

どうにも想定外の位置でスクロールが止まる。
繰り返してみると、どうやら「新規に突っ込まれたアイテムではなく、一つ前のアイテムの位置にスクロールされる」という挙動のようでした。

さてその原因はというと、先ほどの謎挙動が関係していそうでして。



問:なぜインスペクタが自動更新されていなかったか

答:Layoutされたアイテムが出そろってからScrollの値を更新するので、1フレーム後に最新の値が取得できるようになるため



つまり、スクロールビューにアイテムを突っ込んだ直後のRectTransformのsizeDelta.y(=スクロールできる最大値)は突っ込まれる前の値のようで、今回やりたかった自動スクロールで言えば「突っ込む前の最下部の位置までスクロール」することになって、一つずつズレてしまう挙動になってしまうということのようです。

とりあえず、コルーチン側で1フレーム待ってから最新の値を取得して、改めてスクロールするか判定、スクロールが必要であれば最新の値(更新された現在の最大スクロール位置)を取得して更新をかけるということで、想定通りの挙動となりました。

※ひとまずメモまで。後ほど時間があるときにソースやスクショなどはUPしておきます。