Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Restarting after Game Over - Player Error

Discussion in 'Project Tiny' started by ben4d85, May 14, 2019.

  1. ben4d85

    ben4d85

    Joined:
    Dec 26, 2018
    Posts:
    47
    I am trying to restart my game after the player has died for the first time. The flow is:

    Bootstrap >> Main Menu >> Game Level >>
    Player Dies >> Game Over Menu >> Main Menu >> Game Level

    The following error is thrown in the last step, going from the Main Menu back to the Game Level (after the player has died for the first time):

    Code (JavaScript):
    1.  
    2. ut.World.hasComponent(): Invalid entity [31:1] (DELETED) when attempting to query existence of component game.PlayerTag (Component ID 61)
    3. Callstack:
    4.   World.hasComponentRaw (http://localhost:19050/runtime.js:127248:19)
    5.   World.hasComponent (http://localhost:19050/runtime.js:127602:16)
    6.   World.getOrAddComponentData (http://localhost:19050/runtime.js:127835:13)
    7.  
    This sounds like there is a problem with the player entity or the player tag component.

    What I do not understand is that this only happens after the game has been played once. It works fine when going from Bootstrap to Main Menu to Game Level. The error only arises after the player has died for the first time.

    What can I do to solve this?

    ---

    Here is the code I think may be relevant:

    Code (JavaScript):
    1. // GameService
    2. static launchGameOver( world: ut.World, gameConfig: game.GameConfig ) {
    3.          
    4.     // instantiate the game-over menu
    5.     ut.EntityGroup.instantiate( world, this.gameOverGroupName );
    6.  
    7.     // stop all game-level entities
    8.     this.stopGameLevel( world );
    9.  
    10.     // set the game-state to game-over
    11.     gameConfig.gameState = game.GameState.GameOver;
    12. };
    13.  
    14. // GameManagerSystem
    15. case game.GameState.GameOver:
    16. {
    17.     // if the player pressed the primary mouse-button
    18.     if( ut.Runtime.Input.getMouseButtonDown( 0 ) ) {
    19.      
    20.         // reinitialises the app and return to the main-menu
    21.         game.GameService.reinitialiseApp( this.world, gameConfig );
    22.     }
    23. }
    24.  
    25. // GameService
    26. static reinitialiseApp( world: ut.World, gameConfig: game.GameConfig ) {
    27.  
    28.     // set the game-state to initialise
    29.     gameConfig.gameState = game.GameState.Initialise;
    30. }
    31.  
    32. // GameManagerSystem
    33. case game.GameState.Initialise:
    34. {
    35.     // initialise the app and launch the main-menu
    36.     game.GameService.initialiseAppAndLaunchMainMenu( this.world, gameConfig );
    37. }
    38. break;
    39.  
    40. // GameService
    41. static initialiseAppAndLaunchMainMenu( world: ut.World, gameConfig: game.GameConfig ) {
    42.  
    43.     // reset the app back to its original state
    44.     this.resetApp( world, gameConfig );
    45.  
    46.     // instantiate the main-menu-group
    47.     ut.EntityGroup.instantiate( world, this.mainMenuGroupName );
    48.  
    49.     // set the game-state to main-menu
    50.     gameConfig.gameState = game.GameState.MainMenu;
    51. }
    52.  
    53. // GameService
    54. static resetApp( world: ut.World, gameConfig: game.GameConfig ) {
    55.  
    56.     // clear all entities from the game that was just played (player died)
    57.     ut.EntityGroup.destroyAll( world, this.gameLevelGroupName );
    58.     ut.EntityGroup.destroyAll( world, this.gameOverGroupName );
    59.     ut.EntityGroup.destroyAll( world, this.enemyGroupName );
    60.     ut.EntityGroup.destroyAll( world, this.enemyLaserGroupName );
    61.     ut.EntityGroup.destroyAll( world, this.explosionGroupName );
    62.     ut.EntityGroup.destroyAll( world, this.playerLaserGroupName );
    63. }
    64.  
    65. // GameManagerSystem
    66. case game.GameState.MainMenu:
    67. {
    68.     // if the player pressed the primary mouse-button
    69.     if( ut.Runtime.Input.getMouseButtonDown( 0 ) ) {
    70.      
    71.         // launch the game-level
    72.         game.GameService.launchGameLevel( this.world, gameConfig );
    73.     }
    74. }
    75.  
    76. // GameService
    77. static launchGameLevel( world: ut.World, gameConfig: game.GameConfig ) {
    78.  
    79.     // clear the main-menu entity
    80.     ut.EntityGroup.destroyAll( world, this.mainMenuGroupName );
    81.  
    82.     // instantiate the game-level-group
    83.     // NOTE: the player is part of this group
    84.     ut.EntityGroup.instantiate( world, this.gameLevelGroupName );
    85.  
    86.     // set the game-state to play
    87.     gameConfig.gameState = game.GameState.Play;
    88. }
     
  2. ben4d85

    ben4d85

    Joined:
    Dec 26, 2018
    Posts:
    47
    It appears the problem was caused by the way in which I get the player.

    Changing

    Code (JavaScript):
    1. if( this.player == null ) {
    2.  
    3.     // for each entity that has the player-tag component
    4.     this.world.forEach(
    5.         [ ut.Entity, game.PlayerTag ],
    6.         ( entity, playerTag ) => {
    7.        
    8.             // store a reference to the player-entity
    9.             this.player = new ut.Entity( entity.index, entity.version );
    10.         }
    11.     );
    12. }
    to

    Code (JavaScript):
    1. this.player = this.world.getEntityByName( "Player" );  
    in all my scripts appears to solve the problem.

    I have multiple scripts that need to get a reference to the player entity, what is the best way to do this?
     
    Last edited: May 14, 2019
  3. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    The error you mentioned occurs whenever you do a .hasComponent() on an entity which has been deleted (for example by ut.EntityGroup.destroyAll() on the group which contains your player). I think the reason why this is occuring in your case is because you used to copy your player's entity into a variable. After the player-entity has been destroyed, your variable still contains the player's index and version, and you probably tried using a .hasComponent() on this variable, containing your deleted entity.

    A thing you could do to pinpoint your exact error location would be to go into your browser console an click the little arrow at the top left corner of the error. Then you can follow the stacktrace towards the first system you encounter which belongs to you, and click on it to let the browser take you to the exact line of the error:


    I'm not sure how exactly you are using your player-entity in your scripts, but using this.world.getEntityByName("Player"), is normally not recommended, especially when using it quite often. Normally (but again, I don't know your code structure), you would execute the code that you would like to execute on the player-entity within the this.world.forEach(). This way, you do not need to save the reference of the player, making your code more fail-safe.
     
    reallyhexln likes this.
  4. reallyhexln

    reallyhexln

    Joined:
    Jun 18, 2018
    Posts:
    69
    Btw, Zionisias, how you're working with objects on the scene that must be presented in the single instance only (like a "Player")?

    For example, case:
    "Check if the [current] player has more than 300 points".
     
  5. Zionisias

    Zionisias

    Joined:
    Apr 23, 2019
    Posts:
    40
    Even if there is only 1 player, I still use a .forEach(). How I set up my code, I know that there will only be a single player at a given time, so this normally does not cause any issues.

    For example: If you would indeed like to check if the score of the player is greater than 300, I would just do:
    Code (CSharp):
    1. this.world.forEach([ut.Entity, game.PlayerTag], (entity, playerComp) => {
    2.       if(playerComp.Score > 300){
    3.             //Execute code
    4.       }
    5. });
     
    reallyhexln likes this.