UGUI ScrollViewの自動無限スクロールについては、クリックスクロールとドラッグスクロールの組み合わせ
ここではメモとしてダイレクトアップコードを使用します(イベントがまとめられています)
using UnityEngine; using System.Collections; using UnityEngine.UI; using DG.Tweening; using System.Collections.Generic; using UnityEngine.Analytics; [RequireComponent(typeof(GridLayoutGroup))] [RequireComponent(typeof(ContentSizeFitter))] public class SuperScrollView : MonoBehaviour { [SerializeField] int minAmount = 0;// , child 。 + , 2 , 2 。 2 *2 + 1 * 2 = 6 。 RectTransform rectTransform; GridLayoutGroup gridLayoutGroup; ContentSizeFitter contentSizeFitter; ScrollRect scrollRect; RectTransform lockPos; List<RectTransform> children = new List<RectTransform>(); Vector2 startPosition; int amount = 0; float itemHeight = 0; float itemSpacing = 2; public delegate void UpdateChildrenCallbackDelegate(int index, Transform trans); public UpdateChildrenCallbackDelegate updateChildrenCallback = null; int realIndex = -1; int realIndexUp = -1; // ; bool hasInit = false; Vector2 gridLayoutSize; Vector2 gridLayoutPos; Dictionary<Transform, Vector2> childsAnchoredPosition = new Dictionary<Transform, Vector2>(); Dictionary<Transform, int> childsSiblingIndex = new Dictionary<Transform, int>(); #region ///
/// /// bool isSlide = false; bool isInitEnd = false; bool isDragging = false; ///
/// /// float targethorizontal = 0; ///
/// /// //float smooting = 0.3f; ///
/// ( ) /// float timeInterval = 3f; ///
/// ( ) /// //float executionTime = 2f; ///
/// /// float currentTime = 0; ///
/// /// //float currentExecutionTime = 0; #endregion // Use this for initialization void Start() { //StartCoroutine(InitChildren()); } IEnumerator InitChildren() { yield return 0; if (!hasInit) { // Grid ; rectTransform = GetComponent<RectTransform>(); gridLayoutGroup = GetComponent<GridLayoutGroup>(); gridLayoutGroup.enabled = false; contentSizeFitter = GetComponent<ContentSizeFitter>(); contentSizeFitter.enabled = false; gridLayoutPos = rectTransform.anchoredPosition; gridLayoutSize = rectTransform.sizeDelta; // ScrollRect ; scrollRect = transform.parent.parent.GetComponent<ScrollRect>(); scrollRect.onValueChanged.AddListener((data) => { ScrollCallback(data); }); // lockPos = transform.parent.Find("CenterPoint").GetComponent<RectTransform>(); // child anchoredPosition SiblingIndex; for (int index = 0; index < transform.childCount; index++) { Transform child = transform.GetChild(index); RectTransform childRectTrans = child.GetComponent<RectTransform>(); childsAnchoredPosition.Add(child, childRectTrans.anchoredPosition); childsSiblingIndex.Add(child, child.GetSiblingIndex()); } } else { rectTransform.anchoredPosition = gridLayoutPos; rectTransform.sizeDelta = gridLayoutSize; children.Clear(); realIndex = -1; realIndexUp = -1; //children ; foreach (var info in childsSiblingIndex) { info.Key.SetSiblingIndex(info.Value); } //children anchoredPosition; for (int index = 0; index < transform.childCount; index++) { Transform child = transform.GetChild(index); RectTransform childRectTrans = child.GetComponent<RectTransform>(); if (childsAnchoredPosition.ContainsKey(child)) { childRectTrans.anchoredPosition = childsAnchoredPosition[child]; } else { Debug.LogError("childsAnchoredPosition no contain " + child.name); } } } // child; for (int index = 0; index < transform.childCount; index++) { Transform trans = transform.GetChild(index); trans.gameObject.SetActive(true); children.Add(transform.GetChild(index).GetComponent<RectTransform>()); // ; UpdateChildrenCallback(children.Count - 1, transform.GetChild(index)); } startPosition = rectTransform.anchoredPosition; realIndex = children.Count - 1; hasInit = true; // ; for (int index = 0; index < minAmount; index++) { children[index].gameObject.SetActive(index < amount); } if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedColumnCount) { // , GridLayout ; int row = (minAmount - amount) / gridLayoutGroup.constraintCount; if (row > 0) { rectTransform.sizeDelta -= new Vector2(0, (gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y) * row); } } else { // , GridLayout ; int column = (minAmount - amount) / gridLayoutGroup.constraintCount; if (column > 0) { rectTransform.sizeDelta -= new Vector2((gridLayoutGroup.cellSize.x + gridLayoutGroup.spacing.x) * column, 0); } } pos = new Vector2(rectTransform.anchoredPosition.x, rectTransform.anchoredPosition.y + 160f); isInitEnd = true; isSlide = true; Init(); OnClickItemInit(); } Vector2 pos; // Update is called once per frame void Update() { if (isInitEnd) { if (isSlide && !isStartMove && !isDragging && !isMove) { currentTime += Time.deltaTime; if (timeInterval + Mathf.Epsilon <= currentTime) { //Debug.Log("currentTime :" + currentTime); //currentExecutionTime += Time.deltaTime; if (pos.y - m_Content.anchoredPosition.y < 0.6f/*executionTime + Mathf.Epsilon <= currentExecutionTime*/) { pos = new Vector2(m_Content.anchoredPosition.x, m_Content.anchoredPosition.y + itemHeight /*160*/); currentTime = 0; //currentExecutionTime = 0; } //Debug.Log("currentExecutionTime :" + currentExecutionTime); //Debug.Log("Y scrollRect.verticalNormalizedPosition:" + scrollRect.verticalNormalizedPosition); //scrollRect.verticalNormalizedPosition = Mathf.Lerp(scrollRect.verticalNormalizedPosition, targethorizontal, Time.deltaTime * smooting); m_Content.anchoredPosition = Vector2.Lerp(m_Content.anchoredPosition, pos, Time.deltaTime * speedSlide/*smooting*/); } } ItemOnClickMoveUpdate(); centerUpdate(); } } void ScrollCallback(Vector2 data) { UpdateChildren(); } ///
/// /// void UpdateChildren() { if (transform.childCount < minAmount) { return; } Vector2 currentPos = rectTransform.anchoredPosition;// UI if (gridLayoutGroup.constraint == GridLayoutGroup.Constraint.FixedColumnCount) { float offsetY = currentPos.y - startPosition.y; if (offsetY > 0) { // , ; { if (realIndex >= amount - 1) { startPosition = currentPos; return; } float scrollRectUp = lockPos.transform.TransformPoint(Vector3.zero).y;//scrollRect.transform.TransformPoint(Vector3.zero).y; Vector3 childBottomLeft = new Vector3(children[0].anchoredPosition.x, children[0].anchoredPosition.y - gridLayoutGroup.cellSize.y, 0f);// float childBottom = transform.TransformPoint(childBottomLeft).y; if (childBottom >= scrollRectUp) { //Debug.Log("childBottom >= scrollRectUp"); // ; for (int index = 0; index < gridLayoutGroup.constraintCount; index++) { children[index].SetAsLastSibling();// UI children[index].anchoredPosition = new Vector2(children[index].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y - gridLayoutGroup.cellSize.y - gridLayoutGroup.spacing.y); realIndex++; if (realIndex > amount - 1) { children[index].gameObject.SetActive(false); } else { UpdateChildrenCallback(realIndex, children[index]); } } //GridLayoutGroup ; rectTransform.sizeDelta += new Vector2(0, gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y); // child; for (int index = 0; index < children.Count; index++) { children[index] = transform.GetChild(index).GetComponent<RectTransform>(); } } } } else { //Debug.Log("Drag Down"); // , ; if (realIndex + 1 <= children.Count) { startPosition = currentPos; return; } RectTransform scrollRectTransform = scrollRect.GetComponent<RectTransform>(); Vector3 scrollRectAnchorBottom = new Vector3(0, -scrollRectTransform.rect.height - gridLayoutGroup.spacing.y, 0f); float scrollRectBottom = scrollRect.transform.TransformPoint(scrollRectAnchorBottom).y; Vector3 childUpLeft = new Vector3(children[children.Count - 1].anchoredPosition.x, children[children.Count - 1].anchoredPosition.y, 0f); float childUp = transform.TransformPoint(childUpLeft).y; if (childUp < scrollRectBottom) { //Debug.Log("childUp < scrollRectBottom"); // for (int index = 0; index < gridLayoutGroup.constraintCount; index++) { children[children.Count - 1 - index].SetAsFirstSibling(); children[children.Count - 1 - index].anchoredPosition = new Vector2(children[children.Count - 1 - index].anchoredPosition.x, children[0].anchoredPosition.y + gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y); children[children.Count - 1 - index].gameObject.SetActive(true); UpdateChildrenCallback(realIndex - children.Count - index, children[children.Count - 1 - index]); } realIndex -= gridLayoutGroup.constraintCount; //GridLayoutGroup ; rectTransform.sizeDelta -= new Vector2(0, gridLayoutGroup.cellSize.y + gridLayoutGroup.spacing.y); // child; for (int index = 0; index < children.Count; index++) { children[index] = transform.GetChild(index).GetComponent<RectTransform>(); } } } } startPosition = currentPos; //targethorizontal = currentPos.y; } void UpdateChildrenCallback(int index, Transform trans) { if (updateChildrenCallback != null) { updateChildrenCallback(index, trans); } } ///
/// /// /// /// public void SetAmount(float height,float spacing = 2f) { amount = int.MaxValue; itemHeight = height; itemSpacing = spacing; StartCoroutine(InitChildren()); } public void DragStart() { isSlide = false; isDragging = true; isMove = true; Debug.Log(" :" + isSlide); } public void DragEnd() { isSlide = true; isDragging = false; newPos = new Vector2(m_Content.anchoredPosition.x, children[minEleNum].anchoredPosition.y-m_CenterPoint.anchoredPosition.y - 2); Debug.Log(" :" + isSlide); } #region private RectTransform centerPoint; private Vector2 newPos; /// /// /// private int distanceBetweenEles; /// /// /// private float[] distanceToCenter; /// /// /// private int minEleNum; private bool isMove = false; private void Init() { int elelength = children.Count; centerPoint = lockPos; distanceToCenter = new float[elelength]; // distanceBetweenEles = (int)Mathf.Abs(children[1].anchoredPosition.y - children[0].anchoredPosition.y); } /// /// /// private void centerUpdate() { //if (isSlide) return; if (isDragging) { if (Vector2.Distance(rectTransform.anchoredPosition, newPos) > 5f) { for (int i = 0; i < children.Count; i++) { // distanceToCenter[i] = Mathf.Abs(centerPoint.transform.position.y - children[i].transform.position.y); Debug.Log(" "+ i + " :" + distanceToCenter[i]); } // float minDist = Mathf.Min(distanceToCenter); for (int i = 0; i < children.Count; i++) { // if (minDist == distanceToCenter[i]) { minEleNum = i; break; } } } } if (!isDragging) { if (isMove) { // , if (newPos.y - m_Content.anchoredPosition.y < 0.6f) { isMove = false; } rectTransform.anchoredPosition = Vector2.Lerp(m_Content.anchoredPosition, newPos, Time.deltaTime * 5f); } //newPos = new Vector2(m_Content.anchoredPosition.x, minEleNum * -distanceBetweenEles); } } #endregion #region List<RectTransform> currentRectTList = new List<RectTransform>(); List<Button> currentButtonList = new List<Button>(); ScrollRect currentScrollRect; RectTransform m_Content; RectTransform m_CenterPoint; bool isStartMove = false; float offsetY = 0; Vector2 tagetPos; float speedSlide = 2f; void OnClickItemInit() { currentScrollRect = scrollRect; m_Content = currentScrollRect.content; m_CenterPoint = lockPos; foreach (RectTransform itemButton in m_Content) { currentRectTList.Add(itemButton); } Debug.Log("Content :" + currentRectTList.Count); for (int i = 0; i < currentRectTList.Count; i++) { int index = i; currentButtonList.Add(currentRectTList[i].GetComponent<Button>()); currentButtonList[i].onClick.AddListener(delegate { OnClickMoveContent(currentRectTList[index]); }); } } /// /// Update /// void ItemOnClickMoveUpdate() { if (isStartMove && !isMove) { if (offsetY - m_Content.anchoredPosition.y < 0.6f /*Mathf.Epsilon + m_Content.anchoredPosition.y == offsetY*/) { isStartMove = false; Debug.Log(" ContentY :" + m_Content.anchoredPosition.y); for (int i = 0; i < currentButtonList.Count; i++) { int index = i; currentButtonList[i].onClick.AddListener(delegate { OnClickMoveContent(currentRectTList[index]); }); } } m_Content.anchoredPosition = Vector2.Lerp(m_Content.anchoredPosition, tagetPos, Time.deltaTime * speedSlide); Debug.Log(" ContentY :" + m_Content.anchoredPosition.y); Debug.Log(" offsetY:" + offsetY); } } /// /// /// void OnClickMoveContent(RectTransform currentR) { Debug.Log("currentR :" + currentR.anchoredPosition); //float temp = m_Content.anchoredPosition.y; offsetY = Mathf.Abs(currentR.anchoredPosition.y - m_CenterPoint.anchoredPosition.y - itemSpacing); //offsetY = temp + offsetY; tagetPos = new Vector2(m_Content.anchoredPosition.x, offsetY); Debug.Log(" :" + offsetY); isStartMove = true; } #endregion }
:
ScrollView Content
superScrollView.SetAmount(160f,2f);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TestSuperScrollView : MonoBehaviour
{
SuperScrollView superScrollView;
int amount = 500;
private void Start()
{
//
superScrollView = transform.Find("Viewport/Content").GetComponent<SuperScrollView>();
superScrollView.SetAmount(160f,2f);
//superScrollView.updateChildrenCallback = UpdateChildrenCallback;
}
void UpdateChildrenCallback(int index, Transform trans)
{
Debug.Log("UpdateChildrenCallback: index=" + index + " name:" + trans.name);
Text text = trans.Find("Text").GetComponent<Text>();
text.text = index.ToString();
}
}