Search Unity

  1. Full schedule for #UniteBerlin is now available! Featuring talks on our roadmap, hands-on labs and much more! Check it out!
    Dismiss Notice
  2. Unity 2018.1 has arrived! Read about it here
    Dismiss Notice
  3. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  4. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

How do I let the user load an image from their harddrive into a WebGL app?

Discussion in 'WebGL' started by Mikael-H, Jan 21, 2016.

  1. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    TL;DR;
    I need to let the user load a photo of herself into a WebGL app, preferably directly from her harddrive.



    I am creating a system that makes a complete UMA avatar from one front view photo and one side view photo of a user. For anyone interested this system is further described in this thread: http://forum.unity3d.com/threads/wip-uma-master-thesis-player-avatar-creator.343331/#post-2422671
    And demonstrated in this youtube clip:


    What I want to do is create a WebGL client that performs the photo segmentation and all of that image analysis magic and then stores the user avatar and data in a database. My plan is then to create a client package other developers can use to import the finished user avatar into their apps/games.

    I just can't figure out how to actually load an image from the harddrive in WebGL, given the security limitations of the platform. I tried to use dropbox/onedrive/gdrive publicly shared file urls but I run into issues with CORS and since this was a workaround in the first place I think this is the wrong way to go other than as a last resort.

    I suspect one could create a popup window using jslib and upload an image to it, create a texture and send backa texture pointer to the webgl app but my javascript skills are simply not up to the task.

    If anyone could help me get this to work or point me to the correct resources/tutorials I would be very grateful!
     
    Muteking likes this.
  2. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Hello Mikael H.

    It is very much possible to load an image (or any file) from the user hard drive into your WebGL application.
    You can not do this directly from your application, but you can implement a JavaScript plugin that will do the job. Normally I would suggest to transfer data between JavaScript and WebGL using module heap, but for people not familiar with the asm.js infrastructure it might be more convenient to use blobs. The whole process can be split into two separate tasks:

    1) Uploading an image using html button

    First, you need to implement a JavaScript plugin that will handle the browser file dialog, create a blob for the selected file and transfer the blob address to the WebGL application. You can create the following Assets/Plugins/ImageUploader.jslib file for that:
    Code (JavaScript):
    1. var ImageUploaderPlugin = {
    2.   ImageUploaderInit: function() {
    3.     var fileInput = document.createElement('input');
    4.     fileInput.setAttribute('type', 'file');
    5.     fileInput.onclick = function (event) {
    6.       this.value = null;
    7.     };
    8.     fileInput.onchange = function (event) {
    9.       SendMessage('Canvas', 'FileSelected', URL.createObjectURL(event.target.files[0]));
    10.     }
    11.     document.body.appendChild(fileInput);
    12.   }
    13. };
    14. mergeInto(LibraryManager.library, ImageUploaderPlugin);
    Now you can attach the following script to your Canvas, that will initialize the plugin and load the texture from the generated blob address:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Runtime.InteropServices;
    4.  
    5. public class CanvasScript : MonoBehaviour {
    6.     [DllImport("__Internal")]
    7.     private static extern void ImageUploaderInit();
    8.  
    9.     IEnumerator LoadTexture (string url) {
    10.         WWW image = new WWW (url);
    11.         yield return image;
    12.         Texture2D texture = new Texture2D (1, 1);
    13.         image.LoadImageIntoTexture (texture);
    14.         Debug.Log ("Loaded image size: " + texture.width + "x" + texture.height);
    15.     }
    16.  
    17.     void FileSelected (string url) {
    18.         StartCoroutine(LoadTexture (url));
    19.     }
    20.  
    21.     void Start () {
    22.         ImageUploaderInit ();
    23.     }
    24. }

    2) Uploading an image using UI button

    This one is quite tricky. The idea would be of course to make the html browse button hidden, and simulate its click programmatically. We are however facing a security restriction here, specifically, it is not possible to launch the <input type="file"> onclick event handler programmatically, unless you make the click() call from another event handler initiated by the user. And as in most complex systems, in Unity WebGL input events are not processed directly but instead are passed through an intermediate queue. This means that the initial JavaScript event handler initiated by the user has been already processed by the time when you receive the OnClick event in the managed code.
    Nevertheless, there is a trick that we can perform to make it work: as soon as the user pushes the UI button down, we can register onclick JavaScript event for the whole WebGL canvas, so that when the user releases the button, we will get a user-initiated onclick JavaScript event, and perform the input click simulation in the handler.

    You will need the following Assets/Plugins/ImageUploader.jslib plugin:
    Code (JavaScript):
    1. var ImageUploaderPlugin = {
    2.   ImageUploaderCaptureClick: function() {
    3.     if (!document.getElementById('ImageUploaderInput')) {
    4.       var fileInput = document.createElement('input');
    5.       fileInput.setAttribute('type', 'file');
    6.       fileInput.setAttribute('id', 'ImageUploaderInput');
    7.       fileInput.style.visibility = 'hidden';
    8.       fileInput.onclick = function (event) {
    9.         this.value = null;
    10.       };
    11.       fileInput.onchange = function (event) {
    12.         SendMessage('Canvas', 'FileSelected', URL.createObjectURL(event.target.files[0]));
    13.       }
    14.       document.body.appendChild(fileInput);
    15.     }
    16.     var OpenFileDialog = function() {
    17.       document.getElementById('ImageUploaderInput').click();
    18.       document.getElementById('canvas').removeEventListener('click', OpenFileDialog);
    19.     };
    20.     document.getElementById('canvas').addEventListener('click', OpenFileDialog, false);
    21.   }
    22. };
    23. mergeInto(LibraryManager.library, ImageUploaderPlugin);
    And the following script to interact with it:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Runtime.InteropServices;
    4.  
    5. public class CanvasScript : MonoBehaviour {
    6.     [DllImport("__Internal")]
    7.     private static extern void ImageUploaderCaptureClick();
    8.  
    9.     IEnumerator LoadTexture (string url) {
    10.         WWW image = new WWW (url);
    11.         yield return image;
    12.         Texture2D texture = new Texture2D (1, 1);
    13.         image.LoadImageIntoTexture (texture);
    14.         Debug.Log ("Loaded image size: " + texture.width + "x" + texture.height);
    15.     }
    16.  
    17.     void FileSelected (string url) {
    18.         StartCoroutine(LoadTexture (url));
    19.     }
    20.  
    21.     public void OnButtonPointerDown () {
    22.         ImageUploaderCaptureClick ();
    23.     }
    24. }
    The OnButtonPointerDown should be triggered by the Pointer Down event (available through the Event Trigger component, that you can attach to your UI button)

    The second method is of course not 100% reliable (for example, user can push the button, move the mouse outside the canvas, then release the button, so that the attached onclick event handler remains unprocessed), but for most use cases it should be quite appropriate.
     
    Last edited: Jan 21, 2016
  3. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    Thank you so much for your detailed explanation! I'll try this out and see if even I can get it to work :)
     
  4. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    I just tried version 1 and it works great, thanks!
     
  5. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Great news!
    You may also want to try method 2. Not only you will get a native Unity button for opening a file, but you will also be able to make it cross-platform, so that your open file dialog will work both in the editor and in the browser:
    Code (CSharp):
    1.     public void OnButtonPointerDown () {
    2. #if UNITY_EDITOR
    3.         string path = UnityEditor.EditorUtility.OpenFilePanel("Open image","","jpg,png,bmp");
    4.         if (!System.String.IsNullOrEmpty (path))
    5.             FileSelected ("file:///" + path);
    6. #else
    7.         ImageUploaderCaptureClick ();
    8. #endif
    9.     }
     
    Mikael-H likes this.
  6. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    Ha you read my mind, I was just scratching my head, thinking: Damn how do I make this work cross-platform :) Thanks!

    So if I understand this correctly, if WWW-class just has a url (or filepath in this case) then it CAN load from the user's HD even with WebGL? I was under the impression that it would not work due to security reasons but obviously I was wrong because it DOES load :)
     
  7. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Yes, it does load, but only if the requesting page has also been loaded from the local hard drive. You may think of local filesystem (i.e. file://) as of a separate domain (while in fact it is a different protocol). As soon as you upload the requesting WebGL page to the server, the file:// WWW request becomes cross-origin and therefore can not be performed (otherwise you would be able to scan local file system of any user visiting your website :))
     
    Last edited: Jan 23, 2016
    Mikael-H likes this.
  8. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    Thanks, it is all becoming more clear now.

    Some further research suggests that both onedrive and dropbox have CORS enabled but you need to make some url modifications first:
    http://stackoverflow.com/questions/...-image-load-from-cross-enabled-site-is-denied
    https://social.msdn.microsoft.com/F...ort-cors-for-webaplication-?forum=onedriveapi

    So with all the help from you @alexsuvorov and the info provided in those links I think even I can produce a system with the ability to load images from anywhere. Nice! :)
     
  9. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    I would just like to mention that setting up a simple proxy server will give you even more freedom, as you will be able to upload an image from almost any location on the web (with or without proper CORS). So that the user will be able to both paste an url of an image from the web, or upload an image from the local hard drive (like in google image search for example), all implemented using native Unity UI.
     
  10. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    Thanks I'll have to look into that!

    Thank you for all the help, that's what I call above and beyond! :)
     
  11. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    So, thanks a lot for the help earlier with this. My project is progressing. I am experiencing huge memory problems though,

    Loading any image that is too large (I am talking about maybe 3MB here) crashes the web gl app. This seems very strange to me, I have tried increasing the memory by very large amounts and still this issue occurs.

    I mean regardless of how the image is stored, DXT or whatever, it should never take up that much memory?? Am I missing something here?

    You can try the app here if you want:
    http://vikingcrew.net/Selfie_to_Avatar/index.html
     
  12. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Hello Mikael H.

    Yes, this is indeed weird. Do you think it would be possible to reproduce the same issue using an empty project with just an image loader and nothing else? If this is the case, could you share the exact code you are using to load the texture, so that the issue can be analyzed?
     
    Mikael-H likes this.
  13. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    I'll try reproducing it in a simpler project! Thanks for not giving up on me :D
     
  14. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    So... I have been trying to do some experiments... I have constructed a simple webgl app where all you do is upload a set of images. I then tried to crash it. It required loading a handful of images, <10. Since I didn't set memory size to more than 256 MB this isn't terrible, but not great either. I decided to do some profiling to measure how much memory is consumed by loading an image.

    When loading one image of a moderately ugly face (~1MB jpg file) the total memory usage goes from 16.5MB to 61.7MB. Looking at the individual memories it seems that the memory is changed for both unity memory (RAM I guess?) and gfx memory. As the memory increases by this much for a single image it isn't vere surprising I run out pretty fast.

    Is this working as intended or may there be a bug somewhere? Or maybe there's something I could do to reduce memory load? I guess I could resize the image to a smaller size if needed as long as I know what limits I have to live with.

    I tried to attach the zip of the project but the 3.05MB size is apparently too large for the max 4MB limit on the site :p

    Instead I attached an image of the moderately ugly face causing this whole mess and supply a download link: https://onedrive.live.com/redir?res...4319&authkey=!AFSn42mOEJWi53U&ithint=file,zip
     

    Attached Files:

  15. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Actually, the size is not that big, considering that even 24-bit uncompressed is 2271 * 3452 * 3 = 23518476. The real question here, I suppose, is why the memory does not get deallocated, right?
     
    Mikael-H likes this.
  16. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    Good point... I would've thought it should get compressed to DXT on the gpu and take take no room in RAM once it was loaded though. One stupid question... Does texture memory count towards the memory allocated for the web gl app?

    I just tried running in editor and I get the same results. That should indicate it is all my fault I suppose :D I think I should probably resize the image after loading it at least and save some memory that way. I don't think my algorithm for face segmentation or final texture building needs much more than 1024x1024 anyway...

    Also, in my main project, I search the image structure of several scale spaces to find faces, so an image will take up about twice as much memory due to that. So the memory allocation for the webgl app starts filling up fast I guess.
     
  17. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Hello Mikael H.

    I believe dynamically created Texture2D would retain a shadow copy of the texture data on the heap (I can double check on that). Nevertheless, lets try one experiment. Could you crash the following image uploader and let me know which image sizes / number of images can crash it (it has default 256 MB heap and updates the texture in its original resolution, so the size of the image does matter):
    http://files.unity3d.com/alexsuvorov/test/uploadimage/
     
    Mikael-H likes this.
  18. Mikael-H

    Mikael-H

    Joined:
    Apr 26, 2013
    Posts:
    246
    Sorry, missed that you had replied.

    Umh it crashes when uploading just one image if I use one that is approx. 3MB. If I use one that is approx. 1 MB then I can upload it >10 times.

    I actually managed to solve the problem with my own app by resizing any uploaded image to be at the most 1k pixels on either side. I can then segment both images and create a resulting texture wihtout breaking the max memory limit. So I'm pretty happy for now :)

    I need to do a lot of work on user interaction and stuff but at least it is possible to do segmentation and start storing avatars! :D If anyone want to check it out here's a link (warning, very very very early alpha!) http://vikingcrew.net/Selfie_to_Avatar/index.html
     
  19. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Hello Mikael H.

    Yes, resizing the image should reduce the memory usage, however it does not resolve the actual problem. The reason why you run out of memory is because the texture in the following code does not get destroyed between uploads:
    Code (CSharp):
    1.     IEnumerator LoadTexture(string url) {
    2.         WWW image = new WWW(url);
    3.         //yields until loading is done
    4.         yield return image;
    5.         Texture2D texture = new Texture2D(1, 1);
    6.         image.LoadImageIntoTexture(texture);
    7.         Debug.Log("Loaded image size: " + texture.width + "x" + texture.height + " from " + url);
    8.         OnFinishedLoadingTexture.Invoke(texture);
    9.     }
    Assets are not garbage collected, therefore you should take care of this yourself using one of the following ways:

    1) Call Destroy() on the created texture when it is no longer used.
    2) Call Resources.UnloadUnusedAssets() to unload assets that are no longer referenced, including your texture.
    3) Reuse the same Texture2D object (probably the most convenient way to deal with this), consider the following code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Runtime.InteropServices;
    4.  
    5. public class upload : MonoBehaviour {
    6.     [DllImport("__Internal")]
    7.     private static extern void ImageUploaderCaptureClick();
    8.     private Texture2D displayedTexture;
    9.  
    10.     IEnumerator LoadTexture (string url) {
    11.         WWW image = new WWW (url);
    12.         yield return image;
    13.         image.LoadImageIntoTexture (displayedTexture);
    14.     }
    15.  
    16.     void FileSelected (string url) {
    17.         StartCoroutine(LoadTexture (url));
    18.     }
    19.  
    20.     public void OnButtonPointerDown () {
    21. #if UNITY_EDITOR
    22.         string path = UnityEditor.EditorUtility.OpenFilePanel("Open image","","jpg,png,bmp");
    23.         if (!System.String.IsNullOrEmpty (path))
    24.             FileSelected ("file:///" + path);
    25. #else
    26.         ImageUploaderCaptureClick ();
    27. #endif
    28.     }
    29.  
    30.     void Start () {
    31.         displayedTexture = new Texture2D (1, 1);
    32.         GameObject.Find ("Quad").GetComponent<MeshRenderer> ().material.mainTexture = displayedTexture;
    33.     }
    34. }
    Note that once associated with the mesh material, the texture will be automatically uploaded to the GPU each time you modify it (i.e. using LoadImageIntoTexture), and as it is the very same object being reused, the memory should no longer grow.

    I should have taken care of this in my initial code example, of course.

    P.S. A small note. When using blobs to transfer data from JavaScript to WebGL, make sure to call URL.revokeObjectURL() on no longer used blob url to get it garbage collected from the JavaScript memory (for example, you can do this by calling an additional jslib callback from the LoadTexture coroutine after the blob has been downloaded). You can monitor currently allocated blobs in the Firefox memory profiler. If you don't explicitly revoke them, they will remain allocated for the whole lifetime of the page.
     
    Last edited: May 25, 2016
    Muteking and Mikael-H like this.
  20. nsmith1024

    nsmith1024

    Joined:
    Mar 18, 2014
    Posts:
    297
    If i use my way....

    IEnumerator GetPic(string url, GameObject go)
    {
    WWW loader;
    loader= new WWW(url);
    yield return loader;
    go.GetComponent<Renderer>().material.mainTexture = loader.texture;
    }

    it runs out of memory in WebGL in the browser, but works in the editor.


    I tried your way....

    IEnumerator GetPic(string url, GameObject go)
    {
    WWW loader;
    loader= new WWW(url);
    yield return loader;
    loader.LoadImageIntoTexture((Texture2D)go.GetComponent<Renderer>().material.mainTexture);
    }

    but it doesnt seem to work all the time, it sets the texture for some but not all, and the ones that gets the texture ends up setting the same texture for all the gameObjects using that script to the same texture when they should all be different.

    Im stuck because it runs out of memory when loading the scene in the browser. It first loads the scene, then goes around loading all the textures from different urls then it runs out of memory.

    Any ideas?

    I will repost this in a new thread to see if anybody has any ideas
     
  21. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    Hello nsmith1024.

    Are you sure you create a separate texture for each object? I.e.:
    anotherGameObject.GetComponent<MeshRenderer>().material.mainTexture = new Texture2D(1, 1);
    Feel free to share your complete code here.
     
  22. nsmith1024

    nsmith1024

    Joined:
    Mar 18, 2014
    Posts:
    297
    Im new to all this and not sure the difference between texture and picture.... but anyways....

    There is a picture that is placed on the surface of the prefab of the game object as the default.

    When the game starts it creates a bunch of those prefabs all over the place, then loads new pictures from a URL using WWW and applies that picture to the prefabs to replace the default picture, so the result supposed to be each prefab in the scene has a different picture on it.

    But seems sometimes it applies the same picture to multiple prefabs for some reason when I used your code, but when I use my code, it works correctly but then runs out of memory.
     
  23. alexsuvorov

    alexsuvorov

    Unity Technologies

    Joined:
    Nov 15, 2015
    Posts:
    317
    It seems that all your game objects have the same texture object assigned to their material.mainTexture.

    The difference is the following:
    Code (CSharp):
    1. go.GetComponent<Renderer>().material.mainTexture = loader.texture;
    assigns a new managed texture object to the material texture

    while
    Code (CSharp):
    1. loader.LoadImageIntoTexture((Texture2D)go.GetComponent<Renderer>().material.mainTexture);
    modifies the managed texture object, which has been previously assigned to the material texture.

    Each time you modify a managed texture which has been assigned to some material texture, the associated texture on gpu is automatically updated. You are able to assign the same managed texture to different materials (or different objects), in which case all the associated material textures will simultaneously change as soon as you modify this managed texture. Feel free to share your code fragments here to check if that is the case.
     
  24. nsmith1024

    nsmith1024

    Joined:
    Mar 18, 2014
    Posts:
    297
    OK, now I understand, a texture is like a container/prefab that stores a picture, any gameObject using that texture gets automatically updated when the picture of that texture changes.

    So all my instantiated prefabs had the same texture so then any changes to any of the pictures would assign it to all the prefabs in the scene.

    So to have them all use a different picture I guess I could have to instantiate the prefab, and assign a new texture for each of them, then assign that a new picture.

    But it seems like thats what im accidentally doing, heres my actual code...

    IEnumerator GetPic(string url, GameObject go)
    {
    WWW loader;
    loader= new WWW(url);
    yield return loader;
    DestroyImmediate(go.GetComponent<Renderer>().material.mainTexture, true);
    go.GetComponent<Renderer>().material.mainTexture = loader.texture;
    DestroyImmediate(loader.texture);
    }

    Where loader is a new variable containing a new texture that gets assigned to that prefab after the image is loaded.

    Here you can see I destroy the previous texture before assigning it the one from the loader, then destroying the loader one too finally.
     
  25. pl_ayground

    pl_ayground

    Joined:
    Dec 17, 2015
    Posts:
    56
    @alexsuvorov - any chance your #2 approach could be improved to work on an item in a ScrollRect?

    I either make the ScrollRect stop scrolling (due to: "NOTE: Attaching this component to a GameObject will make that object intercept ALL events, and no events will propagate to parent objects.") or the event kicks when I start scrolling rather than on mouse up.
     
  26. nsmith1024

    nsmith1024

    Joined:
    Mar 18, 2014
    Posts:
    297
    Anybody knows how to check the type of file (png, jpg, bmp, text) that the user clicked on? For exampe if you want him to click on an image but he selected a text file by accident, you want to warn him, but the link that the javascript returns to the c# function is just a bunch of random characters with no indication of the file type. Would also need to know the file size so that you dont try to load a 100 meg photo into the browser for example.
     
    Last edited: Dec 15, 2016
  27. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    391
    That is simple.
    Code (CSharp):
    1.   function checkExtention(fname){
    2.      var extentions = ["jpg", "JPG", "png", "PNG"];
    3.      ext = fname.split(".")[1];
    4.      if(extentions.indexOf(ext) > -1){
    5.        //alert("true");
    6.        return true;
    7.        }else{
    8.        alert("only .jpg and .png files allowed");
    9.        return false;
    10.      }
    11.    }
    12. .....
    13. input.onchange = function (event) {
    14.      var tmppath = URL.createObjectURL(event.target.files[0]);
    15.      if(checkExtention(event.target.files[0].name)) SendMessage(g, "_GetTexture", tmppath);
    16.   }
    You coud also check extension in the path returned to Unity.

    BTW I could be also a good idea to check the image size before upload.
    Images of size above 4096 px seem to cause out of memory error and break the webgl player.
    I found some info how to check size or downsample the image prior to uploading it into unity here:http://stackoverflow.com/questions/...ile-size-image-height-and-width-before-upload
     
    Last edited: Dec 22, 2016
  28. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    391
    BTW.
    How to get the original filename into Unity?
    Is there a way to retrieve it from downloaded blob or www inside Unity WebGL?
     
  29. fwalkerCirca

    fwalkerCirca

    Joined:
    Apr 10, 2017
    Posts:
    38
    In
    Code (CSharp):
    1.  document.getElementById('canvas').removeEventListener('click', OpenFileDialog);
    What canvas does the code refer too? Where those the element come from. I am getting a "Cannot read property "addEventListener" of null.
    Which seems to indicate that it did not find the canvas element?
     
  30. sumpfkraut

    sumpfkraut

    Joined:
    Jan 18, 2013
    Posts:
    97
  31. fwalkerCirca

    fwalkerCirca

    Joined:
    Apr 10, 2017
    Posts:
    38
    Thank you sumpfkraut! I found that the problem was the that id of the canvas element was actually #canvas and not just canvas. I mistakenly thought the # was a special character!
     
  32. fwalkerCirca

    fwalkerCirca

    Joined:
    Apr 10, 2017
    Posts:
    38
    But I still can't get this to work. I am so frustrated. I am running Chrome.
    Everything is firing well. However, when I try to create a new WWW( withTheURL ) I get a Request aborted. And I am now stuck.
    The url returned looked like this:
    blob:http://localhost:5799/c1a00c6-106c-4994-b2d-68eb3ef99a7b

    From what I can tell the code looks the same as what Alex posted for Option 2 :( ....
     
    Last edited: Dec 17, 2017
    Aiursrage2k likes this.
  33. sumpfkraut

    sumpfkraut

    Joined:
    Jan 18, 2013
    Posts:
    97
  34. fwalkerCirca

    fwalkerCirca

    Joined:
    Apr 10, 2017
    Posts:
    38
    Yep, I eventually found this out :(
    "They removed javascript so i dont even know if this works anymore"

    Who removed javascript?
     
  35. Marco-Trivellato

    Marco-Trivellato

    Unity Technologies

    Joined:
    Jul 9, 2013
    Posts:
    1,415
    I just want to point out that the deprecation of Unityscript is not specific to our web export (Unity WebGL).