Change movement of a instantiated GameObject from next instantiation

I'm using Unity and C#.

In my game. enemies are instantiated repeatedly and move towards the player in linear path. I want is to make the movement of enemy in sine wave after some specific time has elapsed, to make game tougher.

The movement changes instantly,but i want the change to come in effect from instantiation of new(next) enemy and not to the ones currently present. What can i do?

EnemySpawner script -

void Start()
{
    timeelapsed = 0f;
    StartCoroutine(SpawnEnemies(delay));
}

void Update()
{
    timeelapsed+= Time.deltaTime;
}

IEnumerator SpawnEnemies(float delay)
{
    while (true)
    {
        SpawnNewEnemy();
        yield return new WaitForSeconds(delay);
    }
}

void SpawnNewEnemy()
{
    if (!enemyclone)
    {
        enemyclone = Instantiate(enemy, enemySpawner.transform.position + offset, Quaternion.identity);
    }
}

Enemy Movement Script -

void Update()
{
    t = Time.time;
    if (EnemySpawner.timeelapsed > 0f && EnemySpawner.timeelapsed <= 20f)
    {
        enemy.transform.Translate(Vector3.forward * speed * Time.deltaTime);
    }
    if (EnemySpawner.timeelapsed > 20f && EnemySpawner.timeelapsed <= 40f)
    {
        enemy.GetComponent<Rigidbody>().velocity = Vector3.forward * 5 + Vector3.left * 3 * Mathf.Sin(10f * t);
    }


}

1 answer

  • answered 2018-07-15 07:27 Milan Egon Votrubec

    There's a thousand ways to accomplish this, but one I think might be easy to implement and understand might be to set up Action that is fired when you instantiate a new enemy from the spawner. I've quickly written up a few changes to your EnemySpawner and EnemyMovement scripts that I think might help you.

    First, EnemySpawner:

    public static event Action EnemySpawning;
    void SpawnNewEnemy ( )
    {
        if ( !enemyclone )
        {
            EnemySpawning?.Invoke ( );
            enemyclone = Instantiate ( enemy, enemySpawner.transform.position + offset, Quaternion.identity );
        }
    }
    

    Now, the EnemyMovement:

    private bool travelInLinearPath = true;
    
    private void OnEnable ( )
    {
        EnemySpawner.EnemySpawning -= OnEnemySpawning;
        EnemySpawner.EnemySpawning += OnEnemySpawning;
        travelInLinearPath = true;
    }
    
    public void OnEnemySpawning( )
    {
        EnemySpawner.EnemySpawning-= OnEnemySpawning;
        travelInLinearPath = false;
    }
    
    private void Update ( )
    {
        if ( travelInLinearPath )
            enemy.transform.Translate ( Vector3.forward * speed * Time.deltaTime );
        else
            enemy.GetComponent<Rigidbody> ( ).velocity = Vector3.forward * 5 + Vector3.left * 3 * Mathf.Sin ( 10f * Time.time );
    }
    

    Every time you enable an enemy, you're asking to be notified when the NEXT enemy is about to be spawned. When this happens, you tell THIS enemy to change from linear, to sinusoidal movement (travelInLinearPath). You also ask that this enemy not be notified anymore when a new enemy is spawned (unless you re-enable this enemy).

    I've also not gone into whether you should be grabbing a new enemy from a pool of enemy objects. But the hope that you do is why I added the removal and re-enrolling in the event in OnEnable(). You might want/need to place that code within Start() instead depending on your enemy instantiation and creation later in the game.