Search Unity

How to display data from API to text

Discussion in 'Project Tiny' started by gattzack, Jun 12, 2019.

  1. gattzack

    gattzack

    Joined:
    May 21, 2017
    Posts:
    13
    Hi, I'm trying to display data received from API to Tiny text but I am not able to do so.
    Code (JavaScript):
    1.         static dataReady: boolean;
    2.         static username: string;
    3.         static username2: string;
    4.  
    5.         OnUpdate():void {
    6.           this.world.forEach([ut.Entity],
    7.             (entity) =>{
    8.               APICaller.dataReady = false;
    9.               var APIrequest = new XMLHttpRequest();
    10.            
    11.               APIrequest.open('GET','https://jsonplaceholder.typicode.com/users', true);
    12.  
    13.               APIrequest.onload = function(){
    14.                   var data = JSON.parse(this.response);
    15.  
    16.                   if (APIrequest.status >= 200 && APIrequest.status < 400) {
    17.                     data.forEach(user => {
    18.                       if(user.id == 1){
    19.                         APICaller.username = user.name;
    20.                       }
    21.                       if(user.id == 2){
    22.                         APICaller.username2 = user.name;
    23.                       }
    24.                     })
    25.                   } else {
    26.                     console.log('error');
    27.                   }
    28.               }
    29.               APICaller.DisplayNames(this.world);
    30.               APIrequest.send();
    31.             });
    32.         }
    33.  
    34.  
    35. static DisplayNames(world: ut.World):void{
    36. let ln1 = world.getComponentData(world.getEntityByName('UserName1'), ut.Text.Text2DRenderer);
    37. let ln2 = world.getComponentData(world.getEntityByName('UserName2'), ut.Text.Text2DRenderer);
    38.  
    39. ln1.text = "APICaller.username";
    40. ln2.text = "APICaller.username2";
    41. }
    42.  
    Can someone please help?
     
    Last edited: Jun 13, 2019
  2. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    I can't see the rest of the DisplayNames function, but you might have forgotten to do a world.setComponentData(), is this correct?
     
  3. gattzack

    gattzack

    Joined:
    May 21, 2017
    Posts:
    13
    that is the entirety of the DisplayNames function. Yes you are correct I did not do a world.setComponentData()a world.setComponentData()!
    Can you please advise how I can properly implement it?
     
  4. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    You can simply add these lines at the end of your function.
    Also, you do not need to pass the world into your function. this.world is accessible anywhere in the class, as long as it extends from ut.ComponentSystem.

    Your function would then look like this:
    Code (CSharp):
    1. static DisplayNames():void {
    2.     let userName1Entity = this.world.getEntityByName('UserName1');
    3.     let userName2Entity = this.world.getEntityByName('UserName2');
    4.  
    5.     let ln1 = this.world.getComponentData(userName1Entity, ut.Text.Text2DRenderer);
    6.     let ln2 = this.world.getComponentData(userName2Entity, ut.Text.Text2DRenderer);
    7.  
    8.     ln1.text = "APICaller.username";
    9.     ln2.text = "APICaller.username2";
    10.  
    11.     this.world.setComponentData(userName1Entity, ln1);
    12.     this.world.setComponentData(userName2Entity, ln2);
    13. }
     
  5. gattzack

    gattzack

    Joined:
    May 21, 2017
    Posts:
    13
    I did as you have advise but I keep getting this error in the console:
    runtime.js:990 ut.World.getComponentData(): Invalid entity NONE when attempting to get component ut.Text.Text2DRenderer (Component ID 8)
     
  6. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    That probably means that you have no entity with the name "UserName1" or "UserName2". You could place a console.log(userName1Entity); after the lines where you set those variables, and see in the console if the entity indeed has an index and version of 0.
     
  7. gattzack

    gattzack

    Joined:
    May 21, 2017
    Posts:
    13
  8. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    Hmm, this is indeed a bit odd. It seems like there is not much which can go wrong anymore. Can you please provide a codesample of the whole improved version of that class?
     
  9. gattzack

    gattzack

    Joined:
    May 21, 2017
    Posts:
    13
    Code (JavaScript):
    1.         OnUpdate():void {
    2.           this.world.forEach([ut.Entity],
    3.             (entity) =>{        
    4.               APICaller.dataReady = false;
    5.               var APIrequest = new XMLHttpRequest();
    6.              
    7.               APIrequest.open('GET','https://jsonplaceholder.typicode.com/users', true);
    8.  
    9.               APIrequest.onload = function(){
    10.                   var data = JSON.parse(this.response);
    11.  
    12.                   if (APIrequest.status >= 200 && APIrequest.status < 400) {
    13.                     data.forEach(user => {
    14.                       if(user.id == 1){
    15.                         APICaller.username = user.name;  
    16.                       }
    17.                       if(user.id == 2){
    18.                         APICaller.username2 = user.name;  
    19.                       }
    20.                     })
    21.                   } else {
    22.                     console.log('error');
    23.                   }
    24.               }
    25.               APICaller.DisplayNames(this.world);
    26.               APIrequest.send();
    27.             });
    28.         }
    29.  
    30.         static DisplayNames(world: ut.World):void{
    31.           let userName1Entity = world.getEntityByName('UserName1');
    32.           let userName2Entity = world.getEntityByName('UserName2');
    33.      
    34.           let ln1 = world.getComponentData(userName1Entity, ut.Text.Text2DRenderer);
    35.           let ln2 = world.getComponentData(userName2Entity, ut.Text.Text2DRenderer);
    36.      
    37.           ln1.text = "APICaller.username";
    38.           ln2.text = "APICaller.username2";
    39.      
    40.           world.setComponentData(userName1Entity, ln1);
    41.           world.setComponentData(userName2Entity, ln2);
    42.         }
    this is the updated code
     
  10. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    Which line throws the error, the first .getComponentData in the DisplayNames function or the second? Or might there be an other location which throws the error, not within this script?
     
  11. gattzack

    gattzack

    Joined:
    May 21, 2017
    Posts:
    13
  12. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    Okay, so you are getting the "ut.World.getComponentData(): Invalid entity NONE when attempting to get component ut.Text.Text2DRenderer (Component ID 8)" error on the setComponentData line? This would be rather odd, as you are using the same entity in the lines before in the world.getComponentData(), and it should be crashing there if the entity really would be NONE. Also, judging by your screenshots, the entities are valid, so I'm not sure why even you would get this error.

    Normally in the console you can click open the stacktrace of the error, if you do this, and you click on the first system name that belongs to a system you made, where does it take you in code?
    upload_2019-6-14_9-56-36.png
     
  13. gattzack

    gattzack

    Joined:
    May 21, 2017
    Posts:
    13
    The console shows me these two errors:

    Screenshot 2019-06-14 at 10.32.56.png

    and when i press the link it takes me here on the runtime.js file
    Screenshot 2019-06-14 at 10.32.30.png
     
  14. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    Okay, even though the file is minified, this still tells me enough to guess what probably happens.

    As you can see in the red error message, it says: Callstack: > World.getComponentData > Function.APICaller.DisplayNames. This confirms my suspicion that the the .getComponentData is causing the error in your DisplayNames function.

    Using world.getEntityByName() is not really recommended by Unity Tiny. It is a fairly heavy operation, especially when executing it every frame, like you are doing in this system. Also I have encountered that the world.getEntityByName()-function does very rarely not find the correct entity. If this would happen in only a single frame, you would get this error. The best thing to do is locate the entities you need via a reference in a component. This would very probably solve your issue.

    You could simply make a component with 2 EntityReference fields, one for UserName1-entity and one for the UserName2-entity. You can then put this component on an entity in the scene, and drag in the references with the entities. Next include the component into your filter in your .forEach(), so you can read out the entities you have just set into the component. If done correctly, your code would look something like this:
    Code (CSharp):
    1.         OnUpdate (): void {
    2.             this.world.forEach([ut.Entity, UserNamesComponent],
    3.                 (entity, userNamesComponent) => {
    4.                     APICaller.dataReady = false;
    5.                     var APIrequest = new XMLHttpRequest();
    6.  
    7.                     APIrequest.open('GET', 'https://jsonplaceholder.typicode.com/users', true);
    8.  
    9.                     APIrequest.onload = function () {
    10.                         var data = JSON.parse(this.response);
    11.  
    12.                         if (APIrequest.status >= 200 && APIrequest.status < 400) {
    13.                             data.forEach(user => {
    14.                                 if (user.id == 1) {
    15.                                     APICaller.username = user.name;
    16.                                 }
    17.                                 if (user.id == 2) {
    18.                                     APICaller.username2 = user.name;
    19.                                 }
    20.                             })
    21.                         } else {
    22.                             console.log('error');
    23.                         }
    24.                     }
    25.                     APICaller.DisplayNames(this.world, userNamesComponent.UserName1Entity, userNamesComponent.UserName2Entity);
    26.                     APIrequest.send();
    27.                 });
    28.         }
    29.  
    30.         static DisplayNames (world: ut.World, userName1Entity, userName2Entity): void {
    31.             let ln1 = world.getComponentData(userName1Entity, ut.Text.Text2DRenderer);
    32.             let ln2 = world.getComponentData(userName2Entity, ut.Text.Text2DRenderer);
    33.  
    34.             ln1.text = "APICaller.username";
    35.             ln2.text = "APICaller.username2";
    36.  
    37.             world.setComponentData(userName1Entity, ln1);
    38.             world.setComponentData(userName2Entity, ln2);
    39.         }
     
  15. gattzack

    gattzack

    Joined:
    May 21, 2017
    Posts:
    13
    It Worked!!! Thank you very much for taking the time to help and explain everything!
     
    Zionisias likes this.
  16. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    No problem! Good to hear it works now :)
     
    gattzack likes this.