【unity】ScrollRectを使ったScrollViewでスクリプトから位置を移動したい時の話。【ugui】
困ったときのサンプル参照先で毎度お馴染みテラシュールブログさんを参考にuguiでスクロールビューを作ってみたわけなんですけれども。
UnityのuGUIでスクロールビューを作る - テラシュールブログ
とりあえずマウスのドラッグとかフリックとかでスクロールできるものは作れたわけですが、困ったことにこのスクロールした位置をスクリプト側から制御する方法がわからない。
今回やりたかったことは、「新規に突っ込んだアイテムが画面内に入るよう自動的にスクロールさせて調整する」といったもの。
インスペクタ右上の三本線からDebugモードにしてパラメータまわりを覗いても、どうにも動いてるパラメータはScrollRectのPrevPositionという値。
しかしこちらの値はprivateな上に、どうやらどこかから引っ張ってきた値らしく、こちらを変更したところでスクロールの位置が変わるとも思えない。
……結論から言えば、子オブジェクト側のRectTransformのインスペクタが自動更新されておらず、値の変化がわからなかったという事実が発覚。
クリックして最新値が更新されるというね。
ともあれ、この値を変更すればスクロールが制御できることがわかってめでたしめでたし。
……とはうまくいかないものですよね。
どうにも想定外の位置でスクロールが止まる。
繰り返してみると、どうやら「新規に突っ込まれたアイテムではなく、一つ前のアイテムの位置にスクロールされる」という挙動のようでした。
さてその原因はというと、先ほどの謎挙動が関係していそうでして。
問:なぜインスペクタが自動更新されていなかったか
答:Layoutされたアイテムが出そろってからScrollの値を更新するので、1フレーム後に最新の値が取得できるようになるため
つまり、スクロールビューにアイテムを突っ込んだ直後のRectTransformのsizeDelta.y(=スクロールできる最大値)は突っ込まれる前の値のようで、今回やりたかった自動スクロールで言えば「突っ込む前の最下部の位置までスクロール」することになって、一つずつズレてしまう挙動になってしまうということのようです。
とりあえず、コルーチン側で1フレーム待ってから最新の値を取得して、改めてスクロールするか判定、スクロールが必要であれば最新の値(更新された現在の最大スクロール位置)を取得して更新をかけるということで、想定通りの挙動となりました。
※ひとまずメモまで。後ほど時間があるときにソースやスクショなどはUPしておきます。