Unityを使ったゲーム開発で直面した問題。
NGUIのScroll Viewを使って100個以上のリストをスクロールしたときに、ものすごくもっさりとした動作になった。そこでUIWrapContentを使ったら、かなり快適になったので共有させていただきます。
NGUIのScroll Viewでリスト表示について
解決したい問題
リストの数が増えれば、ゲームオブジェクトもリスト分生成することになります。
リストが100個と多くなってくると、それに伴いスクロールのスピードが遅くなり、
気持ちよくスクロールできなくなります。
解決策
それを解決するため、UIWrapContentを使う方法があります。
UIWrapContentを使うことにより、モッサリしていたものが、すーとスクロールするようになり気持ち良くなりました。
UIWrapContentの仕組み
UIWrapContentは描画されていないリスト(UIPanelから隠れているところ。ユーザー側からみると非表示部分)は、ゲームオブジェクトを非アクティブにすることにより負荷を抑えることができます。
今回、私がやったことはリストの数は4個だけにし、あとの95個分の表示分のデータは、スクロールしたら切り替えています。つまり、100個分のリストを4個のリスト(ゲームオブジェクト)を使いまわして表示しています。
どんな感じで動くかは、以下の動画を御覧ください。
動画においてリストに該当するものは、「UIWrap Content」オブジェクトの子オブジェクト「01,02.03,04」です。
動作確認環境
Unity 5.3.4f
NGUI 3.0.8
実装方法
(1)任意のゲームオブジェクトにUIScrollViewをアタッチする
画面の例では「Scroll View」オブジェクトにアタッチしています。
(2)UIScrollViewをアタッチした子オブジェクトに「UIWrapContent」をアタッチします。
画面の例では「UIWrap Content」オブジェクトのアタッチしています。
(3)UIWrapContent.onInitializeItemコールバックの設定
任意のスクリプト(下記のScrollViewWrapContentSample.cs参照)を作成してUIWrapContent.onInitializeItemコールバックを
受け取れるようにします。
onInitializeItemコールバックは、UIPanel上にリストアイテムが表示されたときに呼び出されます。onInitializeItem関数には、どの位置のリストを表示しているのかの情報があるため、それをもとにリストのデータを更新(詳しくはスクリプト参照)します。
実際に使ったソースコードを記載します。
UIWrapContent.onInitializeItemコールバックを受け取れるようにする
ScrollViewWrapContentSample.cs
using UnityEngine;
using System.Collections;
public class ScrollViewWrapContentSample : MonoBehaviour {
[SerializeField]
private UIWrapContent con;
void Start()
{
//UIPanelの表示物(リスト)が変わったときに呼び出されるようにする
con.onInitializeItem += OnInitializeItem;
}
void OnInitializeItem ( GameObject go,
int wrapIndex,
int realIndex
)
{
//表示されようとしたら呼び出される
Debug.Log ("name:" + go.name + " wrapIndex:" + wrapIndex + " realIndex:" + realIndex);
//リストに対して数字を渡してあげる
WrapItemSample item = go.GetComponent ();
//リストの基準値は真ん中にある
//一番上からリストを描画させたい場合は、Range Limitにはマイナスの値から0のような設定が必要である
int no = (-1) * realIndex;
item.SetNumber (no);
}
}
リスト側のゲームオブジェクトにアタッチするスクリプト
WrapItemSample.cs
using UnityEngine;
using System.Collections;
public class WrapItemSample : MonoBehaviour {
[SerializeField]
private UILabel label;
// Use this for initialization
public void SetNumber (int number) {
label.text = number.ToString ();
}
}
使用する際は自己責任でお願いします。
まとめ
リストの動作が重いと気持ちよくプレイできないため、ダウンロードしてくれても離脱につながります。
もしリストの動作が重いと思ったらUIWrapContentを使ってみてはいかがでしょうか?
きっと解決するかと思います!