Hi! Если вы хотите сэкономить время и по-прежнему помогать, прочитайте этот раздел и последний, чтобы понять мою проблему (часть 1 и 6). Так много кода было необходимо, чтобы полностью представить проблему
Использование Unity 2019.3.0b2
1.
Я создаю приложение WebGL, которое позволяет вам настроить своего персонажа с помощью ресурсовиз загруженных пакетов активов. Пока что у меня есть загрузка и создание экземпляра работы, но Я также хочу изменить загруженный материал игрового объекта на собственный цвет из средства выбора цвета . В этом случае мне нужно обратиться к адекватному Renderer . У меня есть функция, которая отправляет запрос, и это выглядит так:
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);
}
2. Я запускаю эту сопрограмму вот так:
public void DownloadAssetBundle(string url, ProgressBar bar = null)
{
if (isRequestSend)
{
Alerter.ShowMessage("Request has been already send, please wait untill complete.");
return;
}
UnityWebRequest request = HttpService.Instance.GetAssetBundleRequest(url);
if(bar != null)
{
HttpService.Instance.SendDownloadRequest
(
request,
(rq) => { OnDownloadAssetBundleCompleteHandler(rq); },
(rq) => OnDownloadProgressHandler(rq, bar)
);
isRequestSend = true;
}
else
{
HttpService.Instance.SendDownloadRequest
(
request,
(rq) => { OnDownloadAssetBundleCompleteHandler(rq); }
);
isRequestSend = true;
}
}
3. 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);
}
}
4. Теперь последний шаг - установить адекватное преобразование, чтобы мой сценарий искал компонент типа Renderer, получил его материал индекса 0 в качестве текущего материала для модификации, класс, содержащий ChangeSelectedBodyPart функция выглядит так:
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>();
}
}
5. PS. у parent есть только один дочерний элемент, содержащий компонент Renderer Теперь, наконец, проблема в том, что я не получаю правильную ссылку на материал, я получил старый, который устанавливается с помощью кнопки переключения, просто так:
public void OnValueChanged(bool value)
{
if(value)
{
ColorSetter.Instance.ChangeSelectedBodyPart(PartType);
ButtonManager.Instance.RemoveAllButtonsFromPartsWindow();
ButtonManager.Instance.PopulatePartsPanelWithAvatarPartsOfType(PartType);
}
}
6. Таким образом, в заключение, когда я нажимаю на «кнопку переключения», которая представляет некоторую часть тела / одежды аватара, она правильно устанавливает своего родителя и материал через функцию, даже после того, как пакет ресурсов был загружен (но я должен нажать на тот же переключатель снова, чтобы заставить его работать), но когда я запускаю ту же функцию в OnDownloadAssetBundleCompleteHandler сразу после загрузки ресурса, он не работает: S Почему? Это связано со скоростью выгрузки активов? Любые советы по исправлению этого?
В Game View это ведет себя так: ![enter image description here](https://i.stack.imgur.com/aJkXd.gif)