0

I have a spawner object. Every time a gameobject is spawned, I want that object to move randomly (wandering). The problem in my script is that the gameobject movement is very random (jittery). How can I solve this?

void Start () { InvokeRepeating("SpawnNPC", Spawntime, Spawntime); } // Update is called once per frame void Update () { population = GameObject.FindGameObjectsWithTag("NPCobject"); for (int i = 0; i < population.Length; i++) { getNewPosition(); if (population[i].transform.position != pos) { population[i].transform.position = Vector3.MoveTowards(population[i].transform.position, pos, .1f); } } } void getNewPosition() { float x = Random.Range(-22, 22); float z= Random.Range(-22, 22); pos = new Vector3(x, 0, z); } 

I made the New randomize vector in different method, because I plan to change it with pathfinder function and make it in different thread/task.

4 Answers 4

1

You are choosing a new direction every single frame. That will always be very jittery. You wan't to only change direction after, at least, a small interval. Here is a link to one way to do that from Unity's website. https://docs.unity3d.com/ScriptReference/MonoBehaviour.InvokeRepeating.html

Sign up to request clarification or add additional context in comments.

Comments

1

What about using Navigation? As you said wandering, I thought it would give you a nice result and also make your code simple.

The following screenshot is a sample with Navigation. The moving game objects are also changing their direction nicely, although it cannot be seen in the sample because the game object is capsule...

enter image description here

Ground game object in the sample program has NavMesh. See here to build NavMesh.

Agent game object has NavMeshAgent Component. See here to set it up.

Th Behaviour class below is for Agent game object.

using UnityEngine; using UnityEngine.AI; public class NavAgentBehaviour : MonoBehaviour { public Transform[] Destinations { get; set; } // Use this for initialization void Start () { InvokeRepeating("changeDestination", 0f, 3f); } void changeDestination() { var agent = GetComponent<NavMeshAgent>(); agent.destination = Destinations[Random.Range(0, Destinations.Length)].position; } } 

The next Behaviour class is just for spawning the Agent and setting up the destinations. On Unity, set it to whatever game object in the scene, and allocate game objects to the fields.

using UnityEngine; public class GameBehaviour : MonoBehaviour { public GameObject Agent; public Transform SpawnPoint; public Transform Destination1; public Transform Destination2; public Transform Destination3; // Use this for initialization void Start() { Agent.SetActive(false); InvokeRepeating("Spawn", 0f, 2f); } void Spawn() { var newAgent = Instantiate(Agent); newAgent.GetComponent<NavAgentBehaviour>().Destinations = new[] { Destination1, Destination2, Destination3 }; newAgent.transform.position = SpawnPoint.position; newAgent.SetActive(true); } } 

Increase the number of destination, to make the moves look more random. By the way, the destinations do not need to be specified by game objects, which is only for making it easy to see the sample program's behaviour.

2 Comments

This is the proper way to do this
yes the proper way is to use navmesh. But i'm trying to make getNewPosition() run in another thread. As example before i make pathfinding code. But, thank you for the answer and explanation.
0

The source of the jitteriness comes from the fact that you are updating the position to move every frame so your objects never have a consistent location to move to. I would instead suggest attaching a new script to each of your objects that individually handles their movement. In that script you could do something like the following, which has a delay to keep the target position for more than 1 frame.

float delaytimer; Vector3 pos; void Start () { getNewPosition(); // get initial targetpos } void Update () { delaytimer += Time.deltaTime; if (delaytimer > 1) // time to wait { getNewPosition(); //get new position every 1 second delaytimer = 0f; // reset timer } transform.position = Vector3.MoveTowards(transform.position, pos, .1f); } void getNewPosition() { float x = Random.Range(-22, 22); float z= Random.Range(-22, 22); pos = new Vector3(x, 0, z); } 

Comments

0

You are changing the direction they are moving in every frame, thats what is causing the jitter.

You could wait a few moments before you change the direction, perhaps something like this.

// Outside update float betweenChanges = 2; float lastChange = 0; // Inside update if(Time.realtimeSinceStartup > lastChange) { // Change directions // ... lastChange = Time.realTimeSinceStart + betweenChanges; } 

You could also solve this by using InvokeRepeating or a Coroutine.

If you dont want all the NPC's to change direction at the same time and still plan on controlling every NPC from the same class like in your example, you should perhaps add a timer for each NPC instance instead and use that to decide when to change its direction.

A better idea would be to let each NPC have its own Movement-script.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.