Search Unity

Flash build with Browsercomm fails at StartCoroutine

Discussion in 'Flash' started by GabrielPH, Mar 17, 2014.

  1. GabrielPH

    GabrielPH

    Joined:
    Mar 5, 2014
    Posts:
    6
    We are working on a kind of special project for a virtual mascot, we need to tie up the reactions of our character to some html/java web.
    Let me just add that i know this is 100% possible with unity web player but the client has made up his mind he wants it in flash. :|

    Am having problems trying to control the unity SWF from the html. I can successfully access all functions from my c# character controller scripts but get RaiseNullExceptionObject errors when that function calls a ienumerator StartCoroutine or StopCoroutine.

    We are using some piece of code posted by v16 Studios that works wonderful until we need to use timed actions.

    Code (csharp):
    1.  
    2. // Browser Communication Class
    3. // All-in-one class for replicating ExternalCall and SendMessage for simultaneous Flash and Webplayer Builds.
    4. //
    5. // History
    6. // v1.00 - 01/03/2013 - Initial Release.
    7. //
    8.  
    9. using UnityEngine;
    10. using System.Collections;
    11. using UnityEngine.Flash;
    12.  
    13. public class BrowserComms : MonoBehaviour {
    14.  
    15.     public chibicontroller chivi;
    16.  
    17.     public static bool available = false;
    18.    
    19.     public static void ExternalCall(string method, params object[] args)
    20.     {
    21.         #if UNITY_FLASH  !UNITY_EDITOR
    22.         available = ActionScript.Expression<bool>("ExternalInterface.available");
    23.         if(available){
    24.             ActionScript.Statement("var argArr:Array = new Array({0});", method);
    25.             for(int i = 0; i < args.Length; i++)
    26.             {
    27.                 ActionScript.Statement("argArr.push({0});", args[i]);
    28.             }
    29.             ActionScript.Statement("ExternalInterface.call.apply(null, argArr);");
    30.         }
    31.         else{
    32.             Debug.Log("No External Interface available.");
    33.         }
    34.         #else
    35.         Application.ExternalCall(method, args);
    36.         #endif
    37.     }
    38.    
    39.     #if UNITY_FLASH  !UNITY_EDITOR
    40.     [NotRenamed]
    41.     public static void SendMessage( string _class, string _method, string _args)
    42.     {
    43.         ActionScript.Import("flash.utils.getDefinitionByName");
    44.         ActionScript.Statement("var classRef:Class = getDefinitionByName(\"global.\"+{0}) as Class;", _class);
    45.         ActionScript.Statement("var classInstance:* = new classRef();");
    46.         if(_args != "") {
    47.             ActionScript.Statement("classInstance[{0}+'_'+{1}+'_String']({2});", _class, _method, _args);
    48.         }
    49.         else {
    50.             ActionScript.Statement("classInstance[{0}+'_'+{1}]();", _class, _method);
    51.         }
    52.     }
    53.     #endif
    54.    
    55.     void Start () {
    56.         #if UNITY_FLASH  !UNITY_EDITOR
    57.         ActionScript.Import("flash.external.ExternalInterface");
    58.         available = ActionScript.Expression<bool>("ExternalInterface.available");
    59.         if(available){
    60.             ActionScript.Statement("ExternalInterface.addCallback('SendMessage', SendMessage);");
    61.         }
    62.         else{
    63.             Debug.Log("No External Interface available.");
    64.         }
    65.         #endif
    66.     }
    67. }
    68.  
    I know that the error must be somewhere around the fact that Ienumerators don't translate very good to AS3 and tons of libraries are imported in the .AS to cope with this exception.

    So, is there a way to make timed code on C# other that Coroutines or is there a way to make the browserComm be able to call StartCoroutine / StopCoroutine exception codes on AS3?

    Ill be glad to hear from you gurus because am hanging on a thread on this side with this project.

    Some more attachs:

    Sample code of our Coroutines:
    Code (csharp):
    1.  
    2.     public void startParticles(){
    3.         StartCoroutine("particles");
    4.     }
    5.     public IEnumerator particles() {
    6.         int waitTime;
    7.         GameObject particleSystemGameObj = GameObject.FindGameObjectWithTag("ParticleSystem");
    8.         particleSystemGameObj.particleSystem.emissionRate = 50000;
    9.         waitTime = 1;
    10.         yield return new WaitForSeconds(waitTime);
    11.         particleSystemGameObj.particleSystem.emissionRate = 0;
    12.         stopParticles();
    13.  
    Which translate to AS3 like:
    Code (csharp):
    1.  
    2.         public function chibicontroller_startParticles(): void {
    3.             super.MonoBehaviour_StartCoroutine_String("particles");
    4.         }
    5.  
    6.         public function chibicontroller_particles(): IEnumerator {
    7.             var $_particles_c__Iterator: chibicontroller__particles_c__Iterator16 = new  chibicontroller__particles_c__Iterator16()._particles_c__Iterator16_Constructor();
    8.             $_particles_c__Iterator.__f__this = this;
    9.             return $_particles_c__Iterator;
    10.         }
    11.  
    Which calls another AS3 script with the WaitForSeconds as3 code named chibicontroller__particles_c__Iterator16.as

    And the flashdebuger looks like this:

    Error: RaiseNullExceptionObject
    at com.unity::UnityNative$/Ext_Flash_ThrowError()
    at com.unity::UnityNative$/_ZN9Scripting24RaiseNullExceptionObjectEP15ScriptingObject()
    at com.unity::UnityNative$/MonoBehaviour_CUSTOM_StartCoroutine()
    at UnityEngine::MonoBehaviour/MonoBehaviour_StartCoroutine_String_Object()
    at UnityEngine::MonoBehaviour/MonoBehaviour_StartCoroutine_String()
    at global::chibicontroller/chibicontroller_startParticles()[C:\Users\Gabriel\Desktop\Chibi\Unity\Temp\StagingArea\Data\ConvertedDotNetCode\global\chibicontroller.as:344]
    at global::BrowserComms$/SendMessage()[C:\Users\Gabriel\Desktop\Chibi\Unity\Temp\StagingArea\Data\ConvertedDotNetCode\global\BrowserComms.as:47]
    at Function/http://adobe.com/AS3/2006/builtin::apply()
    at flash.external::ExternalInterface$/_callIn()
    at Function/<anonymous>()

    Many thanks in advance for whatever head me in the right way.
     
  2. GabrielPH

    GabrielPH

    Joined:
    Mar 5, 2014
    Posts:
    6
    Hello again, sorry to double post but maybe i can put my predicament in a more simple way.

    This is an extract of the AS3 converted code i get after i build to flash:

    Code (csharp):
    1.  
    2.         public function chibicontroller_noIEparticles(): void {
    3.  
    4.             var $gameObject: GameObject = GameObject.GameObject_FindGameObjectWithTag_String("ParticleSystem");
    5.  
    6.             $gameObject.particleSystem.emissionRate = 50000;
    7.  
    8.         }
    9.  
    10.         public function chibicontroller_particles(): IEnumerator {
    11.  
    12.             var $_particles_c__Iterator: chibicontroller__particles_c__Iterator16 = new chibicontroller__particles_c__Iterator16()._particles_c__Iterator16_Constructor();
    13.  
    14.             $_particles_c__Iterator.__f__this = this;
    15.  
    16.             return $_particles_c__Iterator;
    17.  
    18.         }
    19.  
    20.         public function chibicontroller_startParticles(): void {
    21.  
    22.             super.MonoBehaviour_StartCoroutine_String("particles");
    23.  
    24.         }
    25.  
    Ok, the question. Why i can call noIEparticles from the html correctly and startParticles dies at invoking the Coroutine??

    The error in the flash debug shows that startParticles is being called but whatever it is trying to call causes an Error: RaiseNullExceptionObject.

    Please am pretty desperate, any help would be greatly appreciated. Just take a guess, a shot in the dark, even if its wrong i don´t care. Anything that at least throws me a different error would be a change.

    Thanks in advance and again am sorry about the double post.
     
  3. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Did you try to use
    Code (csharp):
    1. StartCoroutine(particles());
    No idea if it works.
     
  4. GabrielPH

    GabrielPH

    Joined:
    Mar 5, 2014
    Posts:
    6
    Thanks Dantus for your reply.

    Yes, if i try to call the StartCoroutine(particles()); or StartCoroutine("particles"); makes the same error. But in a curious way if i try to access the StartCorutine directly from the html i get no response but at least no error.

    I will keep trying.
     
  5. GabrielPH

    GabrielPH

    Joined:
    Mar 5, 2014
    Posts:
    6
    I want to thank everyone that took the time to read this post. I finally got the hang of the problem with this script. Reading carefully the posts from Catburton i learned that the problem was a scope problem. The way the script from v16 Studios is a very clever one but locks the scope of the function you are accessing on a different context from the rest of the functions of the script.

    The only way to guarantee full access to the rest of functions is to first expose the function out of the unity swf and then they can be accessed back in from the javascript.

    I finally got it to work, but am looking forward to Unity 5 and webGL to finally get rig of flash and as for good.

    Ty all happy coding, Gabriel.