dałem swoje pytanie trochę więcej myśli i tutaj jest moja propozycja, to hacky i żałuję, że nie trzeba było skojarzyć ten kod z moim nazwiskiem:
public bool TextureCached = false;
public bool TextureLoaded = false;
public bool TextureLoadReady = false;
public string TexturePath = "";
public int MaxPixelConvert = 1000;
Texture2D cached_texture = null;
public Vector2 last_pixel = new Vector2(0,0);
// Use this for initialization
void Start() {
SwapMainTexture();
StartWorker();
}
void StartWorker(){
Thread t1 = new Thread (new ThreadStart (this.ListenForUpdate));
t1.Start();
}
/// <summary>
/// Reads new texture from TexturePath
/// </summary>
IEnumerator ReadNewTexture(){
UnityEngine.WWW urltexture = new WWW(TexturePath);
yield return urltexture;
cached_texture = urltexture.texture;
TextureLoadReady = false;
TextureCached = true;
}
void ListenForUpdate(){
// Simulate waiting for an asynchronous update notifying us of the updated texture.
Thread.Sleep(1000);
// ...Receive some notification image is ready load.
// In my case, I'm just loading a local file for testing.
TexturePath = @"file://C:\Users\Public\Pictures\LargeAssPicture.jpg";
TextureLoadReady = true;
}
/// <summary>
/// Create a temporary copy of maintexture so that SetPixel doesn't overwrite the original
/// </summary>
void SwapMainTexture(){
Texture2D texture = (Texture2D)Instantiate(renderer.material.mainTexture);
renderer.material.mainTexture = texture;
}
/// <summary>
/// Update the main texture in small chunks (<MaxPixelConvert)
/// </summary>
void ImABadIdea(){
int count = 0;
Texture2D main_texture = (Texture2D)renderer.sharedMaterial.mainTexture;
for(int x = (int)last_pixel.x; x <= cached_texture.width; x++){
for(int y = (int)last_pixel.y; y <= cached_texture.height; y++){
main_texture.SetPixel(x,y,cached_texture.GetPixel(x,y));
last_pixel = new Vector2(x,y);
if(y+1>=cached_texture.height)last_pixel.y = 0;
count += 1;
if(count >= MaxPixelConvert)break;
}
if(count >= MaxPixelConvert)break;
}
main_texture.Apply();
if(last_pixel.x == cached_texture.width && last_pixel.y == cached_texture.height){
TextureLoaded = true;
}
}
void Update() {
if(TextureLoadReady){ //trigger when new texture ready to load
TextureLoadReady = false;
StartCoroutine(ReadNewTexture());
}
if(TextureCached && !TextureLoaded){ //trigger when new texture is loaded and start streaming it
ImABadIdea();
}
}
Obciążenie tekstura jest wyzwalane przez prosty wątek roboczy. Kiedy wątek "odbiera" powiadomienie o nowej fakturze do załadowania, ustawia odpowiednią flagę (wiem, że nie blokuję wspólnych zasobów, ale mój przykład jest wystarczająco prosty). Następnie tekstura jest przesyłana do pamięci podręcznej, a następnie stopniowo nakładana na strukturę obiektu w małych kawałkach o wielkości 1000 pikseli, każda klatka zaznacza się wewnątrz głównego wątku.
Na mojej scenie testowej miałem mój główny obiekt, a następnie klon tego obiektu, który pozostał ukryty poza ekranem. Klon miał skrypt i ładował nową teksturę. Po załadowaniu tekstury zamieniłem ją na główny obiekt.
Kod został przetestowany na obrazie o wymiarach 3000x3000 pikseli.
ten jest bardzo podobny do swojego postu [inny] (http://stackoverflow.com/questions/13974108/load-materials-on-objects-in-async- metody). – Jerdak
@Jerdak nie, nie, w tym poście byłem zainteresowany załadowaniem zdjęć w asynchronizacji. W tym interesuję się wstępnym ładowaniem obrazów. – Alex