Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.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
Unity3d 参考游戏对象';从下载的资产包实例化后的渲染器材质不工作_Unity3d_Assetbundle - Fatal编程技术网

Unity3d 参考游戏对象';从下载的资产包实例化后的渲染器材质不工作

Unity3d 参考游戏对象';从下载的资产包实例化后的渲染器材质不工作,unity3d,assetbundle,Unity3d,Assetbundle,你好!如果你想节省时间并且仍然提供帮助,请阅读本节和最后一节来了解我的问题(第1部分和第6部分)。需要太多的代码才能完全呈现问题 使用Unity 2019.3.0b2 一, 我正在创建WebGL应用程序,允许您通过下载的资产包中的资产自定义角色。到目前为止,我已经完成了下载和实例化工作,但是我还想将下载的游戏对象材质从颜色选择器更改为自定义颜色。在这种情况下,我需要参考适当的渲染器。我有一个发送请求的函数,它是这样的: private IEnumerator SendRequestCorouti

你好!如果你想节省时间并且仍然提供帮助,请阅读本节和最后一节来了解我的问题(第1部分和第6部分)。需要太多的代码才能完全呈现问题

使用Unity 2019.3.0b2

一,

我正在创建WebGL应用程序,允许您通过下载的资产包中的资产自定义角色。到目前为止,我已经完成了下载和实例化工作,但是我还想将下载的游戏对象材质从颜色选择器更改为自定义颜色。在这种情况下,我需要参考适当的渲染器。我有一个发送请求的函数,它是这样的:

private IEnumerator SendRequestCoroutine(UnityWebRequest request, UnityAction<UnityWebRequest> OnDownloadCompleteHandler, UnityAction<float> OnDownloadProgressHandler = null)
    {
        request.SendWebRequest();
        while(!request.isDone)
        {
            if(OnDownloadProgressHandler != null)
                OnDownloadProgressHandler.Invoke(request.downloadProgress);
            yield return null;
        }
        // Has to fire once more because progress stops at around 0.87,
        // never returning 1 unless download is finished.
        if (OnDownloadProgressHandler != null)
            OnDownloadProgressHandler.Invoke(1);
        OnDownloadCompleteHandler.Invoke(request);
    }
using Assets.Scripts.Models.Enums;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ColorSetter : MonoBehaviour
{
public Renderer rend;
public ColorPicker picker;
public static ColorSetter Instance;

private void Awake()
{
    if(Instance != null)
    {
        Destroy(this);
    }
    else
    {
        Instance = this;
        DontDestroyOnLoad(this);
    }
}

// Start is called before the first frame update
void Start()
{
    picker.onValueChanged.AddListener(color => 
    {
        if (rend == null)
            return;
        rend.material.SetColor("_BaseColor", color);
    }
    );
}

public void ChangeSelectedBodyPart(AvatarPartType p)
{
    switch(p)
    {
        case AvatarPartType.ClothesUpper:
            SetActiveMaterial(Sticher.Instance.Clothes_Upper);
            break;
        case AvatarPartType.ClothesLower:
            SetActiveMaterial(Sticher.Instance.Clothes_Lower);
            break;
        case AvatarPartType.Shoes:
            SetActiveMaterial(Sticher.Instance.Shoes);
            break;
        case AvatarPartType.Hair:
            SetActiveMaterial(Sticher.Instance.Hair);
            break;
        case AvatarPartType.Skin:
            SetActiveMaterial(Sticher.Instance.Skin);
            break;
    }
}

private void SetActiveMaterial(Transform parent)
{
    rend = parent.GetComponentInChildren<Renderer>();
}
}
三,。 OnDownloadAssetBundleCompleteHandler如下所示:

//Function that will handle asset bundle when completed.
private void OnDownloadAssetBundleCompleteHandler(UnityWebRequest request)
{
    isRequestSend = false;
    if(request.isHttpError || request.isNetworkError)
    {
        //Handle downloading error
        Alerter.ShowMessage("Seems like there was a problem with downloading, try again.");
    }
    else
    {
        AssetBundle bundle;
        //Handle content update
        bundle = DownloadHandlerAssetBundle.GetContent(request);
        AssetBundleInfo assetBundleInfo = bundle.LoadAllAssets<AssetBundleInfo>().FirstOrDefault();

        if (assetBundleInfo == null)
        {
            //Handle error
            Alerter.ShowMessage("Couldn't read information about this Character Part. AssetBundleInfo null exception.");
            bundle.Unload(false);
            return;
        }
        GameObject goToLoad = null;

        goToLoad = bundle.LoadAsset<GameObject>(assetBundleInfo.ObjectName);

        if (goToLoad == null)
        {
            Alerter.ShowMessage("Couldn't read information about this Character Part. Downloaded asset's gameobject null exception.");
            bundle.Unload(false);
            return;
        }
        Sticher.ConnectComponent(goToLoad, assetBundleInfo.PartType);
        ColorSetter.Instance.ChangeSelectedBodyPart(assetBundleInfo.PartType);
        bundle.Unload(false);
    }
}
六,。 因此,总之,当我按下代表某个化身身体/服装部分的“切换按钮”时,它会通过功能正确设置其父项和材质,即使在下载了资产包之后(但我必须再次单击相同的切换按钮才能使其工作),但是,当我在下载完资产后在OnDownloadAssetBundleCompleteHandler中启动相同的函数时,它就不起作用了:这是为什么?是否与资产卸载速度有关?有关于修复这个的提示吗

在游戏视图中,它的行为如下:
我把它修好了。因为你不能像@derHugo所说的那样使用DestoyImmediate,因为它可能会导致引用错误,甚至可能永久性地破坏资产,所以在从assetbundle实例化新游戏对象之前,我不得不使用destroy(),然而destroy()当我尝试在同一帧访问新实例化的游戏对象上的渲染器组件时,将在帧的末尾删除给定的对象,而旧的渲染器组件将被彻底销毁。我使用
yield return new WaitForEndOfFrame()修复了它产生一帧的问题在尝试访问新游戏对象之前销毁旧游戏对象的紧跟功能。

TL;但是,当你点击按钮的时候,到底叫什么,如果你只点击一次然后等待,调试会显示什么,你确定这不仅仅是一个简单的逻辑问题吗。。你是一次性下载还是单独下载?我们还没有实现端点,所以我目前使用DropBox直接下载链接,这些按钮是根据resources文件夹中可编写脚本的对象资源量生成的,每个按钮都有一个名为partType的枚举,告诉你它是什么类型的部件,它还包含要显示的URL和精灵。所以,当我按下其中一个“按钮”时,下载过程就开始了。当我按下“tops”时,第5部分中的切换脚本被调用,而我按下单个top,它就完成了下载,第4部分中的“ColorSetter.Instance.ChangeSelectedBodyPart(PartType);”被调用。两者都使用相同的功能。如果在每个阶段添加调试消息,它会在哪里卡住?它不会卡住也不会显示错误,问题是下载完成后,它会跳转到第3部分中的OnDownloadAssetBundleCompleteHandler函数,重要的是最后3行代码中的前2行,其中前一行实例化gameobject并在partType上设置其父基d,然后尝试获取其材质,删除行rend=parent.GetComponentChildren();第四部分以某种方式展示了旧的实例化游戏对象。。。写上面的评论给了我一个想法。我用过Destroy();在加载新游戏对象之前删除旧游戏对象。我假设垃圾收集器负责通过Destroy()方法销毁对象,并且我一直在接收旧引用,但是使用destroimmidate修复了我的问题。
using Assets.Scripts.Models.Enums;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ColorSetter : MonoBehaviour
{
public Renderer rend;
public ColorPicker picker;
public static ColorSetter Instance;

private void Awake()
{
    if(Instance != null)
    {
        Destroy(this);
    }
    else
    {
        Instance = this;
        DontDestroyOnLoad(this);
    }
}

// Start is called before the first frame update
void Start()
{
    picker.onValueChanged.AddListener(color => 
    {
        if (rend == null)
            return;
        rend.material.SetColor("_BaseColor", color);
    }
    );
}

public void ChangeSelectedBodyPart(AvatarPartType p)
{
    switch(p)
    {
        case AvatarPartType.ClothesUpper:
            SetActiveMaterial(Sticher.Instance.Clothes_Upper);
            break;
        case AvatarPartType.ClothesLower:
            SetActiveMaterial(Sticher.Instance.Clothes_Lower);
            break;
        case AvatarPartType.Shoes:
            SetActiveMaterial(Sticher.Instance.Shoes);
            break;
        case AvatarPartType.Hair:
            SetActiveMaterial(Sticher.Instance.Hair);
            break;
        case AvatarPartType.Skin:
            SetActiveMaterial(Sticher.Instance.Skin);
            break;
    }
}

private void SetActiveMaterial(Transform parent)
{
    rend = parent.GetComponentInChildren<Renderer>();
}
}
    public void OnValueChanged(bool value)
{
    if(value)
    {
        ColorSetter.Instance.ChangeSelectedBodyPart(PartType);
        ButtonManager.Instance.RemoveAllButtonsFromPartsWindow();
        ButtonManager.Instance.PopulatePartsPanelWithAvatarPartsOfType(PartType);
    }
}