Изменить готовый образ Unity3D во время выполнения - PullRequest
0 голосов
/ 20 апреля 2020

У меня есть инвентарь объектов в игре с изображением и описанием.

Чтобы представить его, я хочу прокручиваемый список с сеткой (созданный с помощью пользовательского интерфейса с прокруткой внутри) и каждый элемент сетки представляет собой префаб, состоящий из панели пользовательского интерфейса с изображением и текстом.

Prefab appearance

Prefab hierarchy

Я попытался назначить значения изображения и текста программно в сценарии:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PopulateGrid : MonoBehaviour
{
    public GameObject prefab;
    public Sprite mySprite;

    private void Start()
    {
        Populate();
    }

    public void Populate()
    {
        GameObject newObj;

        for (int i = 0; i < 20; i++)
            {
            newObj = (GameObject)Instantiate(prefab, transform); //prefab has image + text
            newObj.GetComponentInChildren<Text>().text = "test" + i;
            newObj.GetComponentInChildren<Image>().sprite = mySprite; //I've also tried .overrideSprite
        }
    }
}

Самое смешное, что текст корректно обновляется, а Изображение не . Я получаю к ним доступ таким же образом, но один ведет себя так, как я хочу, а другой делает свое дело.

Это конечный результат:

List with updated text but not updated images

ОБНОВЛЕНИЕ : подробнее! Вот код во время выполнения, показывающий, что спрайту Image действительно назначается

Code at execution

, а вот мой инспектор:

Inspector

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

Поскольку вы говорите, что сам объект Panel также имеет компонент Image, вы не хотите использовать GetComponentInChildren, поскольку он также возвращает любой Image, присоединенный к самому newObj !

Ваш код не выдает исключение, а присваивает mySprite компоненту Image объекта Panel, а не его дочерним элементам с именем Image.


Вы должны будете использовать, например,

newObj.transform.GetChild(0).GetComponent<Image>()

или, как уже упоминалось, создать свой собственный класс и присоединить его к префабу, например,

public class TileController : Monobehaviour 
{   
    // Reference these via the Inspector in the prefab
    [SerializeField] private Text _text;
    [SerializeField] private Image _image;

    public void Initialize(Sprite sprite, String text)
    {
        _image.sprite = sprite;
        _text.text = text;
    }
}

, а затем выполнить

// using the correct type here makes sure you can only reference a GameObject
// that actually HAS the required component attached
[SerializeField] private TileController _prefab;

public void Populate()
{
    TileController newObj;

    for (int i = 0; i < 20; i++)
    {
        // no cast needed since Instantiate returns the type of the prefab anyway
        newObj = Instantiate(_prefab, transform);
        newObj.Initialize(mySprite, "test" + i);
    }
}
1 голос
/ 20 апреля 2020

Вы уверены, что GetComponentInChildren указывает на правильный компонент Image? Я хотел бы создать собственный класс MonoBehaviour для вашего префаба и создать метод SetImage (), который указывает на правильное изображение. При использовании GetComponentInChildren он вернет первый найденный компонент, и это может привести к неожиданному поведению.

Вы можете выполнить отладку на newObj.GetComponentInChildren<Image>(), чтобы убедиться, что это правильный компонент. Ваш код, кажется, в порядке.

...