WaitForFixedUpdate - bug or feature implementation?

Hello, while working on my toy project with dungeon generation I found an interesting implementation that I did not expect.

In short, my algorithm for dungeon generation was simple as that:

  • place rooms in some area
  • steer each other away from each other until no intersections between their colliders

Steering behavior was made like that:

    IEnumerator SteeringBehaviour(List<Room> rooms)
    {
        while(rooms.Any(x => this.roomCollider.bounds.Intersects(x.roomCollider.bounds)))
        {
            foreach(var r in rooms.OrderBy(x => Vector3.Distance(x.roomCollider.bounds.center, this.roomCollider.bounds.center)))
            {
                if(CheckRoomCollision(r, out var direction))
                {
                    this.transform.Translate(-direction);
                    yield return new WaitForFixedUpdate();
                }
                yield return new WaitForFixedUpdate();
            }
            yield return new WaitForFixedUpdate();
        }
        steerStopped = true;
    }

Rooms for some reason are placing each other on exact same positions every generation with the same seed inserted in Random.InitState(x).
I can provide pictures of this behavior if you want.
But when I change WaitForFixedUpdate on something else, for example on WaitForEndOfFrame — every time I get different result from generation even though such results were much more faster which I can explain.

What I can not explain is why I get the same results if I use WaitForFixedUpdate()?
I could not find any explanation of this behavior in docs. Can someone explain me this effect?

It is really important topic for me, I have witnessed magic I can not explain.

You must have something else generating random numbers that’s disrupting your seeded state that’s only apparent by the change in frequency.

Another candidate idea is that until the physics cycle runs, those colliders haven’t been fully updated and may collide differently with your overlap.

This may or may not be true, so definitely test it.

I base this conjecture on the following timing chart:

1 Like

In fact I was expecting that it would never be the same either way. I mean, why would it be the same if all objects check intersections separately?
And no, at the moment of steering of all rooms nothing uses UnityEngine.Random.

    bool CheckRoomCollision(Room room, out Vector3 direction)
    {
        if(room != this && room.roomCollider != null)
        {
            if(this.roomCollider.bounds.Intersects(room.roomCollider.bounds))
            {
                direction = (room.roomCollider.bounds.center - this.roomCollider.bounds.center).normalized;
                return true;
            }
        }
        direction = new Vector3(0, 0, 0);
        return false;
    }

I want to provide the code for checking of room collision. It is simple intersection between two rooms that is returning the direction also. So no, there is no physics involved. I think…

I have no idea what this is doing really but you do not control physics via the Transform so if this is what you’re trying to do then know that it’s not how you’re supposed to do it and this won’t even be applied to any physics components until the next simulation runs.

You’re talking to a Collider so yes, physics is involved.

2 Likes

I am trying to implement something like this https://www.gamedeveloper.com/programming/procedural-dungeon-generation-algorithm
And it was successful overall. I simply trying to understand why using WaitForFixedUpdate() I get same result every time and using every other method I get different each time.

In case of doubt, add Debug.Log() calls everywhere. Are you sure those bounds are updating correctly? You may not be using physics, but I’m not sure the collider bounds will be recalculated immediately when updating the transform.

1 Like

The hint I gave to maybe why is above. Consecutive frames don’t necessarily mean physics has been updated and your transform changes won’t have been applied.

1 Like

So, when I am using WaitForFixedUpdate() physics are not updated and thus there are no random collisions\interactions between room objects and they can be placed in the same positions each time? Or is it the other way around?
I don’t really get it.

Is there anything I can do to make this more consistent or do it right?

Sounds like you need to follow some tutorials on what the difference between Update and FixedUpdate is and when physics updates. I did explain above the basics here but you’re essentially asking again so I’d recommend reading up a little on what these are.

1 Like

I am sorry, my bad about physics and fixed update. I simply trying to get it.
If in my coroutine I call WaitForFixedUpdate() what exactly removes additional random factor from that implementation compared to other methods? Is it simply the number of calls, which is supposedly bigger using other methods, before physics update?