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

ComponentBehaviour with setTimeout

Discussion in 'Project Tiny' started by SorneBachse, Jan 25, 2019.

  1. SorneBachse

    SorneBachse

    Joined:
    Dec 27, 2012
    Posts:
    62
    Hey all.

    I have an issue where I'm trying to invoke a function after x amount of seconds, where I'm passing parameters into the function. It looks like this:

    Code (JavaScript):
    1. namespace game
    2. {
    3.     export class EnemyOnSpawnedSystemFilter extends ut.EntityFilter
    4.     {
    5.         tag: game.EnemyTag;
    6.         moveThreshold: game.MovementThreshold;
    7.         direction: game.MovementDirection;
    8.         position: ut.Core2D.TransformLocalPosition;
    9.     }
    10.  
    11.     export class EnemyOnSpawnedSystem extends ut.ComponentBehaviour
    12.     {
    13.         filter: EnemyOnSpawnedSystemFilter;
    14.  
    15.         OnEntityEnable(): void
    16.         {
    17.             console.log("HAS COMPONENT", this.world.hasComponent(this.entity, game.MovementDirection));
    18.             let oldMove = new Vector2().copy(this.filter.direction.Direction);
    19.  
    20.             this.Test(this.world, this.entity, oldMove);
    21.             setTimeout(this.EnableEnemy, 1000, this.world, this.entity, oldMove);
    22.         }
    23.  
    24.         Test(world: ut.World, entity: ut.Entity, oldMove: Vector2): void
    25.         {
    26.             console.log("TEST HAS COMPONENT", world.hasComponent(entity, game.MovementDirection));
    27.         }
    28.  
    29.         EnableEnemy(world: ut.World, entity: ut.Entity, oldMove: Vector2): void
    30.         {
    31.             //Enabled movement after a short period of time here
    32.             console.log("HAS COMPONENT", world.hasComponent(entity, game.MovementDirection));
    33.         }
    34.     }
    35. }
    And here is my log:


    Can someone tell me what I'm doing wrong? Why is it working the Test function but not EnableEnemy function? Cheers.
     
  2. Nkon

    Nkon

    Unity Technologies

    Joined:
    Jun 12, 2017
    Posts:
    65
    Hi there,

    Try changing the delayed call to this:
    setTimeout(this.EnableEnemy, 1000, this.world, new ut.Entity(this.entity.index, this.entity.version), oldMove);


    I'm trying to provide a thorough explanation why this would fix the problem.

    First of all, 'this.entity' is a reference to data, instead of actual data. If this reference is passed somewhere, no data is actually copied. Instead, a new reference pointing to the same piece of data is created.

    Second, 'ut.Entity' is merely two numbers, an index number and a version number.

    Third, in your case the data behind the reference is accessed one second later in EnableEnemy. It's possible that during this time, the data has been changed or reused for something else.

    So, to be sure that the entity reference still points to the same entity in the game world, even after some time has passed, copy the data behind the reference (index and version numbers).

    I hope this clarifies the nature of entities, entity references and such. If there is more questions I'm happy to help.

    Edit: Here's another thread with somewhat similar issues:
    https://forum.unity.com/threads/storing-entity-references-to-new-objects.613426/

    Cheers!
     
    Last edited: Jan 25, 2019
    SorneBachse likes this.
  3. SorneBachse

    SorneBachse

    Joined:
    Dec 27, 2012
    Posts:
    62
    Hi Nkon, your fix worked perfectly! Thanks!

    Although I'm still not 100% sure why the entity data just suddenly can be changed/reused? Or is the the reference to that data that has been changed?