I need to send 2D screenshots of the Unity frame buffer over the network, from the Unity Web player. It’s probably very easy to do in a standalone app, but I have to do it in a web applet for the reason not related to this topic.
Since Unity scripts can’t use blocking network calls (we don’t want unity frame loop to freeze) I have to use asynchronous UDP sockets or asynchronous .NET HttpListener.
Using asynchronous networking means using .NET thread pool. Threading in .NET automatically means that sooner or later one is going to need thread synchronization functionality.
In my case I need two threads to synchronize on something, I don’t care what, be it semaphote or wait handle or something else. One of the threads is waiting on a socket and is dealing with network transfers, sending PNG encoded screenshots over the net, while the second thread (main Unity rendering loop thread) is the thread that takes care of the Texture2D creation, framebuffer pixel reading and PNG encoding.
So the idea is this: network socket callback residing on its own thread is waiting for connection, after connection has come - the network thread invokes PNG screen capture method that is executed on the Unity main thread. This screen capturing method yields WaitForEndOfFrame object since it can’t capture framebuffer before the rendering’s done. Yielding makes this framebuffer capture method asynchronous, and forces me to try and sync network thread and the main thread on a semaphore or something. I tried to use .NET Semaphore and EventWaitHandle and I can’t use them because for some reason Unity Web player throws security exceptions. These are exception messages I got from the console:
Exception for EventWaitHandle:
UNSECURED:
System.Threading.NativeEventCalls::CreateEvent_internal(bool,bool,string,bool)
unity security internal call - throwing exception
DETAILED EXCEPTION
System.Security.SecurityException: This method is not supported in the unity web player for security reasons.
at (wrapper managed-to-native) System.Threading.NativeEventCalls:CreateEvent_internal (bool,bool,string,bool)
at System.Threading.EventWaitHandle…ctor (Boolean initialState, EventResetMode mode) [0x00000]
at System.Threading.ManualResetEvent…ctor (Boolean initialState) [0x00000]
at (wrapper remoting-invoke-with-check) System.Threading.ManualResetEvent:.ctor (bool)
at UploadShot.initializer () [0x00000]
at UploadShot…ctor () [0x00000]
DETAILED EXCEPTION END
SecurityException: This method is not supported in the unity web player for security reasons.
System.Threading.ManualResetEvent…ctor (Boolean initialState)
(wrapper remoting-invoke-with-check) System.Threading.ManualResetEvent:.ctor (bool)
UploadShot.initializer ()
UploadShot…ctor ()
(Filename: Line: 389866080)
Exception for Semaphore:
UNSECURED:
System.Threading.WaitHandle::WaitOne_internal(intptr,int,bool)
unity security internal call - throwing exception
----UnityEngine.Debug:Log(Object)
----UnityEngine.MonoBehaviour:print(Object)
----:MoveNext()
UnityEngine.Texture2D
UnityEngine.MonoBehaviour:print(Object)
:MoveNext()
(Filename: BaseClass.cpp Line: 1567)
I noticed that in this thread http://forum.unity3d.com/viewtopic.php?t=7730 Joachim tried to answer but very briefly, didn’t help me much.
I have two questions here: 1) why thread synchronization code throws security exceptions in Unity Web player? what is the reasoning behind this? probably only someone like Joachim can answer this 2) does it mean it is physically impossible to write asynchronous networking code that uses thread synchronization in Unity Web player? I’d like to send tech report to my senior engineer soon about this, so I just wanted to double check here if I miss something?
Thanks