Unity Learn home
View Tutorial Content
Steps

Recorded Video Training: Shop UI with Runtime Scroll Lists

Tutorial
Intermediate
1 Hour15 Mins
(19)
Summary
This recorded live training demonstrates a workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop interface where items can be bought and sold between two lists.
Select your Unity version
Last updated: December 22, 2021
5.x
Language
English

1.Intro and Setup

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 1/9: Intro and Setup.

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from teh collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

2.Scroll View

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 2/9: Scroll View

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from teh collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

3.Adding Buttons

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 3/9: Adding Buttons

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from teh collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

4.Button Prefab

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 4/9: Button Prefab

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from teh collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

5.ShopScrollList Script

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 5/9: ShopScrollList Script

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from the collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

6.Adding Buttons Via Script

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 6/9: Adding Buttons Via Script

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from teh collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

7.Creating Items and Testing

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 7/9: Creating Items and Testing

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from teh collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

8.Adding Interactivity

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 8/9: Adding Interactivity

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from teh collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

9.Creating Second Shop, Q&A

In this live training we will learn the updated workflow for creating and populating scroll-lists at run time using the Scroll Rect interaction component. We will use this to create a simple two column shop where items can be bought and sold between two lists. A Scroll Rect can be used when content that takes up a lot of space needs to be displayed in a small area. The Scroll Rect provides functionality to scroll over this content.
This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.
Type caption for embed (optional)

Part 4/9: Button Prefab

SampleButton

using UnityEngine; using System.Collections; using UnityEngine.UI; public class SampleButton : MonoBehaviour { public Button buttonComponent; public Text nameLabel; public Image iconImage; public Text priceText; private Item item; private ShopScrollList scrollList; // Use this for initialization void Start () { buttonComponent.onClick.AddListener (HandleClick); } public void Setup(Item currentItem, ShopScrollList currentScrollList) { item = currentItem; nameLabel.text = item.itemName; iconImage.sprite = item.icon; priceText.text = item.price.ToString (); scrollList = currentScrollList; } public void HandleClick() { scrollList.TryTransferItemToOtherShop (item); } }

ShopScrollList

using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Collections.Generic; [System.Serializable] public class Item { public string itemName; public Sprite icon; public float price = 1; } public class ShopScrollList : MonoBehaviour { public List<Item> itemList; public Transform contentPanel; public ShopScrollList otherShop; public Text myGoldDisplay; public SimpleObjectPool buttonObjectPool; public float gold = 20f; // Use this for initialization void Start () { RefreshDisplay (); } void RefreshDisplay() { myGoldDisplay.text = "Gold: " + gold.ToString (); RemoveButtons (); AddButtons (); } private void RemoveButtons() { while (contentPanel.childCount > 0) { GameObject toRemove = transform.GetChild(0).gameObject; buttonObjectPool.ReturnObject(toRemove); } } private void AddButtons() { for (int i = 0; i < itemList.Count; i++) { Item item = itemList[i]; GameObject newButton = buttonObjectPool.GetObject(); newButton.transform.SetParent(contentPanel); SampleButton sampleButton = newButton.GetComponent<SampleButton>(); sampleButton.Setup(item, this); } } public void TryTransferItemToOtherShop(Item item) { if (otherShop.gold >= item.price) { gold += item.price; otherShop.gold -= item.price; AddItem(item, otherShop); RemoveItem(item, this); RefreshDisplay(); otherShop.RefreshDisplay(); Debug.Log ("enough gold"); } Debug.Log ("attempted"); } void AddItem(Item itemToAdd, ShopScrollList shopList) { shopList.itemList.Add (itemToAdd); } private void RemoveItem(Item itemToRemove, ShopScrollList shopList) { for (int i = shopList.itemList.Count - 1; i >= 0; i--) { if (shopList.itemList[i] == itemToRemove) { shopList.itemList.RemoveAt(i); } } } }

SimpleObjectPool

using UnityEngine; using System.Collections.Generic; // A very simple object pooling class public class SimpleObjectPool : MonoBehaviour { // the prefab that this object pool returns instances of public GameObject prefab; // collection of currently inactive instances of the prefab private Stack<GameObject> inactiveInstances = new Stack<GameObject>(); // Returns an instance of the prefab public GameObject GetObject() { GameObject spawnedGameObject; // if there is an inactive instance of the prefab ready to return, return that if (inactiveInstances.Count > 0) { // remove the instance from teh collection of inactive instances spawnedGameObject = inactiveInstances.Pop(); } // otherwise, create a new instance else { spawnedGameObject = (GameObject)GameObject.Instantiate(prefab); // add the PooledObject component to the prefab so we know it came from this pool PooledObject pooledObject = spawnedGameObject.AddComponent<PooledObject>(); pooledObject.pool = this; } // put the instance in the root of the scene and enable it spawnedGameObject.transform.SetParent(null); spawnedGameObject.SetActive(true); // return a reference to the instance return spawnedGameObject; } // Return an instance of the prefab to the pool public void ReturnObject(GameObject toReturn) { PooledObject pooledObject = toReturn.GetComponent<PooledObject>(); // if the instance came from this pool, return it to the pool if(pooledObject != null && pooledObject.pool == this) { // make the instance a child of this and disable it toReturn.transform.SetParent(transform); toReturn.SetActive(false); // add the instance to the collection of inactive instances inactiveInstances.Push(toReturn); } // otherwise, just destroy it else { Debug.LogWarning(toReturn.name + " was returned to a pool it wasn't spawned from! Destroying."); Destroy(toReturn); } } } // a component that simply identifies the pool that a GameObject came from public class PooledObject : MonoBehaviour { public SimpleObjectPool pool; }

Recorded Video Training: Shop UI with Runtime Scroll Lists
Recorded Video Training: Shop UI with Runtime Scroll Lists
General Tutorial Discussion
0
0
1. Intro and Setup
0
0
2. Scroll View
0
0
3. Adding Buttons
0
0
4. Button Prefab
0
0
5. ShopScrollList Script
0
0
6. Adding Buttons Via Script
0
0
7. Creating Items and Testing
0
0
8. Adding Interactivity
0
0
9. Creating Second Shop, Q&A
0
0