【问题标题】:Unity - Creating a UI list at runtime programmaticallyUnity - 以编程方式在运行时创建 UI 列表
【发布时间】:2016-03-25 06:23:15
【问题描述】:

我有一个场景,我应该能够从项目列表中选择一个 3D 模型,然后将其加载到下一个场景中。我想根据本地数据库中已存储的内容以编程方式生成项目列表。但是我在获取要在场景中显示的项目列表时遇到问题...

所以我有一个项目类:

[System.Serializable] public class Item { 
     public string ObjectGuid;
     public string Name;
     public string Description;
     public Sprite Icon;
     public Button.ButtonClickedEvent SelectObject;
}

我的场景的脚本,其中包含项目列表和我调用以从数据库加载对象的方法:

public class ObjectSelectionScript : MonoBehaviour {
public List<Item> itemList;
public Transform contentPanel;

void LoadObjects() {
     StreamReader str = new StreamReader (Application.persistentDataPath + "/" + DataManager.LOCATION_XML_PATH);
     string result = str.ReadToEnd ();
     str.Close();
     var jo = SimpleJSON.JSON.Parse (result);

     if (jo ["Objects"] != null) {
         for (int i = 0; i < jo["Objects"].Count; i++) {
             if (!string.IsNullOrEmpty(jo["Objects"][i]["FileGuid"])) {
                 Item newObject = new Item();
                 newObject.ObjectGuid = jo["Objects"][i]["ObjectGuid"];
                 newObject.Name = jo["Objects"][i]["Name"];
                 newObject.Description = jo["Objects"][i]["Description"];
                 //newObject.SelectObject = new Button.ButtonClickedEvent();
                 itemList.Add(newObject);
             }
         }
     } 
 }

ModelObject 类:

 public class ModelObject : MonoBehaviour {
     public Button button;
     public Text Name;
     public Text Description;
     public Image Icon;
 }

还有一个包含名称、描述、缩略图的预制 ModelObjectPrefab,已添加到我的资产文件夹中。

PopulateList() 方法是我的问题。我无法初始化预制件,然后创建可以在界面中的 contentPanel 中放入的 ModelObjects。这是我的代码:

void PopulateList()
{
     try {
         foreach (var item in itemList)
         {
             GameObject newModel = Instantiate(ModelObject) as GameObject;
             ModelObject myModelObject = newModel.GetComponent<ModelObject>();
             myModelObject.Name.text = item.Name;
             myModelObject.Description.text = item.IDescription;
             myModelObject.icon.sprite = item.Icon;
             myModelObject.button.onClick = item.selectObject;
             newModel.transform.SetParent(contentPanel);

         }

     } catch (System.Exception ex) {

     }
 }

我目前在实例化时得到空指针。我尝试过 Resources.Load 和 Instatiate 方法的变体,但没有找到解决方案。

谁能给我一个提示是什么问题? PopulateList() 应该如何将项目获取到界面?

【问题讨论】:

  • 尝试更改您的预制件的名称。它与类类型的名称相匹配,这绝不是一件好事。
  • 试过了。还是不行。
  • 谢谢。我只是不明白问题是什么,任何建议都可以工作
  • 预制件不为空吗?它是否包含 ModelObject 组件?
  • 预制件不包含模型对象。它有名称、描述和图像。

标签: c# list user-interface unity3d populate


【解决方案1】:

请注意,Instantiate() 方法不应以类型(例如ModelObject)作为参数。相反,您应该向它传递一个对象实例(在这种情况下,您的预制件GameObject“ModelObjectPrefab”)。文档特别指出它需要:

要复制的现有对象

否则,您可能会遇到这样的意外行为。在您的代码中,我们需要传递对“ModelObjectPrefab”的引用作为Instantiate() 调用的参数。我建议将包含PopulateList() 的类修改为:

// New variable to hold prefab object
public GameObject modelObjectPrefab;

// ...

void PopulateList()
{
     try {
         foreach (var item in itemList)
         {
             // Reference prefab variable instead of class type
             GameObject newModel = Instantiate(modelObjectPrefab) as GameObject;
             ModelObject myModelObject = newModel.GetComponent<ModelObject>();
             myModelObject.Name.text = item.Name;
             myModelObject.Description.text = item.IDescription;
             myModelObject.icon.sprite = item.Icon;
             myModelObject.button.onClick = item.selectObject;
             newModel.transform.SetParent(contentPanel);

         }

     } catch (System.Exception ex) {

     }
}

然后,在编辑器窗口中,将您的预制件“ModelObjectPrefab”从资产面板拖到脚本属性中的新 Model Object Prefab 字段中,以形成脚本和预制件之间的连接。

希望这会有所帮助!如果您有任何问题,请告诉我。

【讨论】:

  • 谢谢,我试过了,但是当我执行 GetComponent() 时,我仍然得到 'myModelObject' 的空值......我完全不知道为什么会这样。
【解决方案2】:

注意给读者。 Unity 中不再提供“GUI”。只需使用新的 UI 系统。示例http://www.folio3.com/blog/creating-dynamic-scrollable-lists-with-new-unity-canvas-ui/


唯一有效的方法是以编程方式创建整个 GUI。 我创建了一个GUI.matrix 并在其中添加了所有内容。它看起来不太好,所以我花了很多时间试图让它看起来更好并在移动设备上响应,但最终这是唯一有效的解决方案。

作为可能遇到相同问题的人的快速参考,该解决方案具有以下结构:

public void OnGUI ()
{
var savedMatrix = GUI.matrix;
scrollPosition = GUI.BeginScrollView (new Rect (10f, 10f, Screen.width - 10f, Screen.height - 10f), scrollPosition, new Rect (10f, 10f, Screen.width - 10f, (_files.Count + 2) * 200f));
        if (Input.touchCount == 1) {
            Vector2 touchDelta2 = Input.GetTouch (0).deltaPosition;
            scrollPosition.y += touchDelta2.y;
        }
        var selected = GUILayout.SelectionGrid (gridInt, _files.ToArray (), 1, MyStyle);
        if (selected >= 0) {
            if (selected == 0) {
                if (selectedItem != null )
                    if (selectedItem.Parent != null)
                        selectedItem = selectedItem.Parent;
                else 
                    selectedItem = null;
            } else {
                SelectFolder (selected);
            }

            RefreshViewModel ();
        }
        GUI.EndScrollView ();
        GUI.matrix = savedMatrix;
}

【讨论】:

    猜你喜欢
    • 2021-05-17
    • 2015-10-21
    • 1970-01-01
    • 2016-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多