Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在运行时更改Unity3D预设图像_C#_Unity3d_Sprite - Fatal编程技术网

C# 在运行时更改Unity3D预设图像

C# 在运行时更改Unity3D预设图像,c#,unity3d,sprite,C#,Unity3d,Sprite,我有一个游戏中物品的清单,有图像和描述 为了表示它,我需要一个带有网格的可滚动列表(由内部带有滚动视图的UI画布构成),网格的每个元素都是一个预置,由一个带有图像和文本的UI面板组成 我尝试在脚本中以编程方式指定图像和文本的值: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class PopulateGrid : Mon

我有一个游戏中物品的清单,有图像和描述

为了表示它,我需要一个带有网格的可滚动列表(由内部带有滚动视图的UI画布构成),网格的每个元素都是一个预置,由一个带有图像和文本的UI面板组成

我尝试在脚本中以编程方式指定图像和文本的值:

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
        }
    }
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
使用UnityEngine.UI;
公共类PopulateGrid:单一行为
{
公共游戏对象预制;
公共精灵;
私有void Start()
{
填充();
}
公共空白填充()
{
游戏对象newObj;
对于(int i=0;i<20;i++)
{
newObj=(游戏对象)实例化(预置,转换);//预置有图像+文本
newObj.getComponentChildren().text=“test”+i;
newObj.getComponentChildren().sprite=mySprite;//我也试过了。overrideSprite
}
}
}
有趣的是,文本得到了正确更新,而图像没有得到正确更新。我以同样的方式访问它们,但其中一个表现得像我想要的那样,而另一个则做他的事情

这就是最终结果:

更新:更多详细信息!下面是运行时显示图像精灵确实被分配的代码

这是我的检查员:


您确定GetComponentChildren指向了正确的图像组件吗?我将为您的预置创建一个定制的MonoBehavior类,并创建一个指向正确图像的SetImage()方法。使用GetComponentChildren时,它将返回找到的第一个组件,这可能导致意外行为


您可以在
newObj.getComponentChildren()
上进行调试,以验证它是否是正确的组件。您的代码似乎正常。

因为您说
面板
对象本身也有一个
图像
组件,您不想使用,因为它还返回附加到
newObj
本身的任何
图像

您的代码不会引发异常,而是将
mySprite
分配给
Panel
对象的
Image
组件,而不是其名为
Image
的子对象


你要么使用

newObj.transform.GetChild(0).GetComponent<Image>()
然后呢

// 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);
    }
}
//在此处使用正确的类型可确保您只能引用游戏对象
//实际上已经附加了所需的组件
[SerializeField]专用TileController\u预置;
公共空白填充()
{
TileController newObj;
对于(int i=0;i<20;i++)
{
//不需要强制转换,因为实例化无论如何都会返回预置的类型
newObj=实例化(_预置,转换);
初始化(mySprite,“test”+i);
}
}

它看起来像是在做它应该做的事情。您正在实例化一个预置,您正在分配一个新文本,但是mySprite的值似乎永远不会改变。您已将其设置为要在Inspector中分配的属性,但此后它将不会更改。请注意您的措辞:
prefable
指的是模板资产。一旦这个预设被实例化,或者在一般情况下谈论场景中的对象时,它不再被称为“预设”,而仅仅是一个
GameObject
,在代码执行的那一刻,你的
mySprite
似乎就是
null
。。在inspector中,我给mySprite变量分配了一个精灵,我把它分配给预置图像。我以为它应该是这样工作的?我能用另一种方式来表达它吗?你能a)给我们看你的设置的屏幕截图,b)设置断点并在
newObj.getComponentChildren().sprite=mySprite处调试你的代码吗。。我打赌
mySprite
此时将
null
,否则您将在控制台中看到异常,指出问题所在。另请注意:
面板
本身默认情况下通常包含一个
图像
组件。。。。你有没有可能把精灵放在那里?面板上只有一张图片,我想这张图片会被修改的,对吧?或者它有没有可能找不到它?我很困惑,因为文本已经被找到了,但我不知道在引擎盖下他们的行为是否有所不同。无论如何,我会尝试为预制创建一个单行为类,我会看看它是如何运行的,谢谢!我检查了你的代码和我的旧代码,你正确地分配了精灵。因此,在映像组件上执行Debug.Log可以用来检查它是否正确。根据我的经验,总有可能会发现一些隐藏的图像组件。试试看它是否管用^^;我在执行过程中进行了检查,精灵确实被分配了!i、 imgur.com/RHhBHpZ.png这很奇怪,因为它似乎“忘记”了自己的任务!它起作用了!我仍然习惯于团结,我没有意识到我的错误。我非常感激,谢谢!我将使用您和cesartalves的建议,在将来创建一个特定的预制类,以避免歧义。
// 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);
    }
}