0
\$\begingroup\$

I'm making an infinite runner game in Unity 3D. I have it so that platforms spawn and move backwards toward the player and they are destroyed once past the player. Over time when the platforms are spawned, the position they're spawned at gets more and more inaccurate. Sometimes they over lap slightly and sometimes there are small gaps in between them. And as the game is continuously played, it gets worse and worse. You can watch the video below to see what I mean. This is the script I use to spawn the object

 public GameObject[] objectSpawned;

 public PlatformKiller myPlatformKiller;

 void Start()
 {
     myPlatformKiller = GameObject.Find("PlatformKiller").GetComponent<PlatformKiller>();
 }

 private void Update()
 {
     if (myPlatformKiller.readyForSpawn)
     {
         int rand = Random.Range(0, objectSpawned.Length);
         Instantiate(objectSpawned[rand], transform.position, transform.rotation * Quaternion.Euler (-90f, 0f, 0f));
     }
 }

Here is a video so you can see what I'm talking about: https://youtu.be/eASouQlTsqs

Also, I know the exact unit size for each platform is 11.92. I know this because I added a c# script to each one that shows me the vector3 values. There are originally 20 platforms. And to know exactly where to spawn the object I did 11.92*20 = 238.4. And the first platform is at -4.78. So I subtracted that from 238.4 and got 233.62. So a z position of 233.62 is the correct place to spawn the object. I just wanted to include that in there so you know that the spawner gameobject is in the right place. Please let me know if there is any additional information about this that I can give you. Everything should theoretically work I think, so I seriously have no idea what to do. Thanks for your help!

readyForSpawn is set in my PlatformKiller script shown below:

public bool readyForSpawn;

void Update()
{
    readyForSpawn = false;
}

void OnTriggerEnter(Collider target)
{
    if (target.tag == "Floor")
    {
        readyForSpawn = true;
        Destroy(target.gameObject);
    }
}

And that script is attached to PlatformKiller Game Object: PlatformKiller Picture

\$\endgroup\$
  • \$\begingroup\$ Looks like your platforms are spawning at the right place for the wrong time - a little early or a little late to perfectly match the edge of the previous platform as it recedes. Show us how you determine readyForSpawn and the movement speed of the platforms, and we can help you adjust either the time or position to compensate. \$\endgroup\$ – DMGregory Jun 24 '20 at 21:58
  • \$\begingroup\$ DMGregory, I just edited the post to show what you asked for \$\endgroup\$ – Matheson Jun 24 '20 at 23:04
  • \$\begingroup\$ Looks like we're still missing the platform movement speed. \$\endgroup\$ – DMGregory Jun 24 '20 at 23:13
0
\$\begingroup\$

Your mistake is assuming that time in a game is continuous.

In a perfect world, if we had a sensor that fired the very instant that the first atom of a platform hit the kill box, and that triggered the new platform to be spawned at exactly that instant (or as fast as the speed of light will allow), then your platforms would match up end-to-end, no problem.

But time in games is quantized in steps. So the first frame that your kill box detects a platform touching it, might be 19 milliseconds after the contact actually happened. If we don't account for that "spare change" time between the theoretical moment of contact and the next opportunity our script ran to detect it, we'll end up with gaps.

So, instead, let's make a version of this that's based on space, not time. That should be easier to reason about:

 public Transform[] prefabs;    
 public Transform latestSpawn; // Set this to the platform closest to the spawner.

 public float spawnDistance = 11.92; // We could also read this from the bounds of the object.

    
 private void Update()
 {
     float distance = Vector3.distance(latestSpawn.position, transform.position);

     if (distance >= spawnDistance)
     {
         Vector3 spawnPosition = transform.position;
         spawnPosition.z -= distance - spawnDistance; // Advance the platform to close the gap.

         int rand = Random.Range(0, prefabs.Length);

         latestSpawn = Instantiate(
                           prefabs[rand],
                           position,
                           transform.rotation * Quaternion.Euler (-90f, 0f, 0f)
                       );
     }
 }

This can still be a little off if the script runs after your platforms have already moved for the frame (because the new platform hasn't yet, so it will try to catch up and overshoot), so adjust it in the script execution order to run before the platform movement.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.