The Headache of PhotonNetwork.Instantiate's initial position

When using PhotonNetwork.Instantiate, objects are initially spawned at their initial spawn location for a single frame before being updated to their actual "current" position a frame later. This is disastrous for objects with rigidbodies because they will collide with the old "ghosts" of any object that was spawned at that same position in the past. Since this is a deep collision, it will usually send newly spawned objects flying off in crazy directions.

To elaborate further, here's the scenario:

1. Player 1 joins a room
2. We PhotonNetwork.Instantiate a new vehicle for him at position 1000,20,1000 in the world.
3. He appears correctly at the new position (which is a few meters up in the air above the ground), his vehicles drops down onto the ground, and he drives off into the distance. All's well so far.
4. Player 2 joins the room
5. We PhotonNetwork.Instantiate a new vehicle for player 2 at position 1000,20,1000 in the world.
6. For a single frame, on player 2's client, player 1's vehicle is spawned at its ORIGINAL position of 1000,20,1000! <== THIS IS THE BUG
7. Player 2's newly spawned vehicle is now inside of the player 1's original vehicle so they collide and go flying off into space
8. One frame later, player 1's vehicle is moved to its actual world position which is no longer at the spawn point, but this it too late - the collision has already happened
9. Player 2 gazes in wonder as his vehicle rockets miles up into the air, wondering what's happening.

Is there anything we can do about step #6 in this flow with PUN?

For now, the ugly hackish workaround I'm doing is to spawn all new player vehicles at s temporary starting point, which is semi-guranteed to be unique for each spawn, and then wait a frame before moving it to the actual spawn point. Ugly.

Any way to make PUN wait for a read of a PhotonView prior to the instantiation, or to pass some required data (like position) as part of the Instantiation, or anything we can do about this?

Thanks!

Comments

  • 2 things.

    1. Are you syncing the scene?

    2. Are you monitoring the transform info?
  • What do you mean by "syncing the scene"?

    I am not observing a Transform directly, but instead a MonoBehaviour with its own OnPhotonSerializeView. Within that stream, the transform.position is one of the things that is written and read.

    Thanks!
  • As workaround I would recommend you disable collisions and visibility for vehicle and enable them on first OnPhotonSerializeView call.
  • This problem is a known one and by now, it's high on our todo list. It missed the release window pre-Christmas.

    Behind the scenes, this is a bit complicated: The message for "Instantiate X at pos Y" can't be updated on the server, so when a client gets the Instantiate, it has to put the object somewhere. Only after doing that, it can go on and apply updates and catch up with the real position.

    In worst case, we will have to add a server feature to be able to update the position but maybe I can find another solution.

    As Vadim says: At the moment, the workaround is probably in your hands. With a script on the GO, you could flag GO's as "unpositioned" by default. When a position update comes in, apply it as initial position and remove the flag. From then on, any other script runs in "positioned" mode...
  • Sebasrez
    Sebasrez
    edited November 2019
    Was this ever fixed? I saw this post was back in 2015 and I am dealing with this issue.
  • There is no automatic fix for this. If you instantiate objects somewhere, this is where they get created.
    In PUN 2, the PhotonTransformView now has a "first take" value, which is used internally to teleport the object to the position of the first "live" update.

    You could rewire this minimally to turn off physics component of new objects until the first take was received.
    Alternatively, instantiate at a unique position per player (Player.ActorNumber).

    We are not entirely sure if a solution by us "nail it". We consider the PhotonTransformView a starting point for more sophisticated solutions, which are (more) game specific.
  • I liked the solution the racing demo had. A check to see if IsWriting, was complete on the photon view and to turn on the game object when complete. I don't know if this will run into any issues down the line but it is working for me at the moment.