Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by laurentos · Oct 08, 2018 at 11:53 AM · texture2druntimeloadmain thread

Loadimage Texture at runtime

Hi,

I want to update an image of a texture at runtime, but not in start(). I receive some image by socket, and I want to load this image in a texture. How can I do ? There is an error, Unity want I call this function in stat() or MainThread. WebCamTexture do this, so I hope I can.

Laurent

 private void ReceiveCallback(IAsyncResult AR)
 {
     //Check how much bytes are recieved and call EndRecieve to finalize handshake
     int recieved = _clientSocket.EndReceive(AR);
 
     if (recieved <= 0)
         return;
 
     //Copy the recieved data into new buffer , to avoid null bytes
     byte[] recData = new byte[recieved];
     Buffer.BlockCopy(_recieveBuffer, 0, recData, 0, recieved);
 
     try
     {
         var base64EncodedBytes = System.Convert.FromBase64String(Encoding.ASCII.GetString(recData, 0, recieved));
         Stream str = new MemoryStream(base64EncodedBytes);//, 0, bytesRec);
 
         StartCoroutine("Test", text);
 
         text.LoadImage(base64EncodedBytes);
         Mg.mainTexture = text;
 
         //Image img = System.Drawing.Image.FromStream(str);
         //pictureBox2.Image = img;
     }
     catch (Exception ex)
     {
         //label3.Text = ex.ToString();
     }
 
     //Process data here the way you want , all your bytes will be stored in recData
 
     //Start receiving again
     _clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);
     byte[] msg = Encoding.ASCII.GetBytes("30");
     SendData(msg);
 }


Error message :

IsObjectMonoBehaviour can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function. UnityEngine.MonoBehaviour:StartCoroutine(String, Object) socket:ReceiveCallback(IAsyncResult) (at Assets/socket.cs:59) System.Net.Sockets.Worker:Receive()

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image SkaredCreations · Oct 08, 2018 at 12:28 PM 0
Share

You should add more informations in the topic, that is what's your current code and what's exactly not working (including eventually the exception message). You're not forced to change the texture of a material in Start, so I suppose you're misunderstanding the exception raised.

avatar image toddisarockstar · Oct 11, 2018 at 01:07 AM 0
Share

in the unity examples i have seen that before using loadtexture they usually make a new small texture first.

before loading the texture try adding:

 text = new Texture2D(2,2);
 text.LoadImage(your data);


1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by SkaredCreations · Oct 09, 2018 at 02:44 PM

The exception is raised because you can call LoadImage only in the main thread but your code is running asynchronously through BeginReceive/EndReceive that run in a new thread.

There's a dispatcher on Github posted by a user that can fit your case: click here. Import the file UnityMainThreadDispatcher.cs in your project and attach it to one of your game objects (i.e. the one that contains also your socket script, there should be only one in a scene).

Then pass the local component instance as state object to BeginReceive (last parameter this instead of null):

 _clientSocket.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), this);

Finally you will have to cast AR.AsyncState back to your script type and enqueue the logic in UnityMainThreadDispatcher:

 YourScriptName me = (YourScriptName)AR.AsyncState;
 UnityMainThreadDispatcher.Instance().Enqueue(() =>
 {
     me.text.LoadImage(base64EncodedBytes);
     me.Mg.mainTexture = me.text;
 });

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image laurentos · Oct 10, 2018 at 11:15 AM 0
Share

Same problem

In fact, I want to call loadimage in a function like update(), not in start() or awake(). How can I do ?

private void ReceiveCallback(IAsyncResult AR) { //Check how much bytes are recieved and call EndRecieve to finalize handshake int recieved = _clientSocket.EndReceive(AR);

     if(recieved <= 0)
         return;

     //Copy the recieved data into new buffer , to avoid null bytes
     byte[] recData = new byte[recieved];
     Buffer.BlockCopy(_recieveBuffer,0,recData,0,recieved);

     try
     {
         var base64EncodedBytes = System.Convert.FromBase64String(Encoding.ASCII.GetString(recData, 0, recieved));
         Stream str = new $$anonymous$$emoryStream(base64EncodedBytes);//, 0, bytesRec);

         socket me = (socket)AR.AsyncState;
         me.text.LoadImage(base64EncodedBytes);
         me.$$anonymous$$g.mainTexture = text;
     }
     catch(Exception ex)
     {
         //label3.Text = ex.ToString();
     }

     _clientSocket.BeginReceive(_recieveBuffer,0,_recieveBuffer.Length,SocketFlags.None,new AsyncCallback(ReceiveCallback),this);
     byte[] msg = Encoding.ASCII.GetBytes ("30");
     SendData (msg);
 }

Same error :

LoadImage can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, ins$$anonymous$$d move initialization code to the Awake or Start function. UnityEngine.ImageConversion:LoadImage(Texture2D, Byte[]) socket:ReceiveCallback(IAsyncResult) (at Assets/socket.cs:59) System.Net.Sockets.Worker:Receive()

avatar image SkaredCreations laurentos · Oct 10, 2018 at 06:46 PM 0
Share

Ok so the thing is that the method LoadImage (as the exception says) needs to be called on the main thread of Unity, which is not possible for your current code because you're working asynchronously through BeginReceive/EndReceive.

On Github there's a dispatcher that (if it still works, as it was released by a user for Unity 5.x) could be useful for you.

If that dispatcher works then you just need to move the logic into an inline function:

 socket me = (socket)AR.AsyncState;
 Unity$$anonymous$$ainThreadDispatcher.Instance().Enqueue(() =>
 {
    me.text.LoadImage(base64EncodedBytes);
    me.$$anonymous$$g.mainTexture = text;
 });

EDIT Ok I've tested the above dispatcher and it works in 2017.* (and hopefully also in later), here is a small script that I've used to test (pressing 'S' loads the image with the dispatcher from a new thread):

 using System.Threading;
 using UnityEngine;
 
 public class TestLoadImage : $$anonymous$$onoBehaviour {
 
     public string textureUri;
     public Renderer target;
 
     Texture2D tex;
 
     void Start()
     {
         tex = new Texture2D(2, 2);
         target.material.mainTexture = tex;
     }
 
     void Update ()
     {
         if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.A))
         {
             LoadNewImage();
         }
         if (Input.Get$$anonymous$$eyDown($$anonymous$$eyCode.S))
         {
             LoadInNewThread();
         }
     }
 
     void LoadInNewThread()
     {
         object source = this;
         new Thread(() =>
         {
             Unity$$anonymous$$ainThreadDispatcher.Instance().Enqueue(() => 
             {
                 TestLoadImage me = (TestLoadImage)source;
                 me.LoadNewImage();
             });
         }).Start();
     }
 
     void LoadNewImage()
     {
         try
         {
             var content = System.IO.File.ReadAllBytes(textureUri);
             tex.LoadImage(content);
         }
         catch (System.Exception e)
         {
             Debug.LogError(e.$$anonymous$$essage);
         }
     }
 }

I have edited my answer with complete explanation.

avatar image laurentos SkaredCreations · Oct 11, 2018 at 07:35 AM 0
Share

Thnak you very much ! That works !!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

96 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How to set a texture resource to texture type "GUI" by script? 1 Answer

Unity3D error: Assets/Scripts/Item.cs(25,38): error CS0308: The non-generic method `UnityEngine.Resources.Load(string)' cannot be used with the type arguments 1 Answer

Inverse of a texture for masking? 1 Answer

Resources.LoadAll not working 0 Answers

White Edges on Sprites Loaded from PNG at Run-time 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges