How to I make part of my code to not run every frame?

Hi everybody.

I have been working on something to make the enemies on my game move on random directions every certain ammount of seconds. The problem here is that Random.Range I made for the directions runs every single frame so the enemies change direction every frame and the movement looks bad.

Also, if I use something like Random.Range(-5f, 5f); Is it going to choose one of those two or will it choose one of the 10 numbers that are between -5 and 5?

Here is my code for you to take a look at it

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveEnemies : MonoBehaviour
{
    public float speed = 40.0f;
    public float xRange = 7;
    public float upBoundary = 4;
    public float downBoundary = -2;
    private float startDelay = 0.5f;
    private float startInterval = 5.0f;

    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("EnemieMovement", startDelay, startInterval);
    }

    // Update is called once per frame
    void Update()
    {


        if (transform.position.x < -xRange)
        {
            transform.position = new Vector3(-xRange, transform.position.y, transform.position.z);
        }

        if (transform.position.x > xRange)
        {
            transform.position = new Vector3(xRange, transform.position.y, transform.position.z);
        }

        // Screen limits for y
        if (transform.position.y < downBoundary)
        {
            transform.position = new Vector3(transform.position.x, downBoundary, transform.position.z);
        }

        if (transform.position.y > upBoundary)
        {
            transform.position = new Vector3(transform.position.x, upBoundary, transform.position.z);
        }
    }

    IEnumerator GoRandom()
    {
        // This will wait 1 second like Invoke could do, remove this if you don't need it
        yield return new WaitForSeconds(1);   

        float timePassed = 0;
        while (timePassed < 3)
        {
            transform.Translate(Vector3.right * Time.deltaTime * Random.Range(-speed, speed));
            transform.Translate(Vector3.forward * Time.deltaTime * Random.Range(-speed, speed));
            timePassed += Time.deltaTime;

            yield return null;
        }

    }

    void EnemieMovement()
    {
        StartCoroutine(GoRandom());
    }
    }

[ICODE][/ICODE]

Vibrating enemies!!!

Do this: use a cooldown timer. Until the timer runs down, don’t choose a new spot. Here’s more:

Cooldown timers, gun bullet intervals, shot spacing, rate of fire:

https://discussions.unity.com/t/821482/2

GunHeat (gunheat) spawning shooting rate of fire:

https://discussions.unity.com/t/824570/2

It’s a little weird and inconsistent… Random.Range(int,int) returns from the first to the last minus one. But Random.Range(float,float) will return everything up to and including each end number… but getting that is EXTREMELY unlikely.

EDIT: as Brath points out below, note that Random.Range(float,float) can return any fractional decimal number between the high and low, inclusive. That’s why hitting high or low is vanishingly unlikely, because there’s a MASSIVE number of possible fractional numbers between -5.0f and +5.0f, eg, such as 3.1415926f…

1 Like

To add a little to what @Kurt-Dekker said, if you use the float version, it’s not just 10 numbers, you could get 3.128484 as a number also. You literally can get any number between the two. It’s not just -5, -4, -3, etc.

2 Likes

Thank you for the help, exactly the enemies were just vibrating.
I did set the cooldown timer and changed the transform for addforce because my enemy was teleporting and it is looking way better now.

About the Random.Range, that is good to know I think that could be related to the IndexOutOfRangeException error I am getting on this Instantiate line.

int meteorIndex = Random.Range(0, meteor.Length);
Vector3 positionZ = new Vector3(Random.Range(-spawnRangeX, spawnRangeX),(Random.Range(spawnRangeYdown, spawnRangeYup)), spawnPosZ);

Instantiate(meteor[meteorIndex], positionZ, meteor[meteorIndex].transform.rotation);

Any ideas?

thanks for the help again.

Is this script also on a GameObject other than the one you think it is?

No, it is only on an empty object that I named SpawnManager.

Well something isn’t adding up… one possibility is meteor has zero elements.

Here are some notes on IndexOutOfRangeException and ArgumentOutOfRangeException:

http://plbm.com/?p=236

Steps to success:

  • find which collection it is (critical first step!)
  • find out why it has fewer items than you expect
  • fix whatever logic is making the indexing value exceed the collection
  • remember you might have more than one instance of this script in your scene/prefab
1 Like

It was always step 4. I left some of my meteors on the scene view to modify them. You have no idea how long I struggled with that. Ill play your games and watch every ad.

1 Like