destroy scene object

Options
hi guys.
when a scene object need to be destroyed the master client destroy and in some cases an rpc is sent to the master client to destroy it.
but when a new player enter the room he can see some old objects that isn't visible to the master client, so to other come this i made script to indicate the wrong object "behaviour" and local destroy it.
is there a proper way to handle it?

Comments

  • Tobias
    Options
    Usually, all Instantiate calls are buffered and Destroy calls will remove the instantiate from the buffer.
    New players should get the "clean" event buffer state.
    If you send a RPC to destroy things, you break this rule. RPCs are only received by clients who are active in the same room. Anyone who joins later, doesn't get the old RPCs.

    You can either send the RPC buffered, or (better) you use PhotonNetwork.Destroy to get rid of objects someone might load with the scene.
  • guyhazi
    Options
    yea i added a buffered destroy to that specific object after it destroyed by the master, but this is only needed for the "recent" destroyed scene objects that show when new user connect, i think i should remove it from buffer after lets say 30 sec because it is not needed, is there a way to removed a specific buffered rpc after an amount of time or it happen automatically?
  • Tobias
    Options
    The buffer is not cleaned up for you.
    Currently, there is no support to clean up a specific RPC. But if you use a separate PhotonView, you could remove all RPCs for that PhotonView. See PhotonNetwork.RemoveRPC().
  • guyhazi
    Options
    i think i was able to find some more specific information about the case since the game have a lot more downloads and there are always some players online so it go like this:

    the host instantiate sceneObject ai enemy that go from point A to point B, when they reach point B host destroy them.
    also host instantiate a "bonus drop" that get called to destroy on pickup or after 15 seconds.

    when only the above was in the code almost all the time when a player joined in he could see a "non responding and non moving enemy" scene object that the host couldn't see because it was destroyed.

    so i added another buffered rpc to the destroy cycle and when the host destroy the object that reached point B he also send buffered rpc to call a local Destroy(gameObject) on that specific enemy ai object.

    after that, things went a lot smoother and it worked perfect but there is another thing:

    as you probably know when player presses his home button to exit a game on android the loose focus in unity doesn't always fire up and not like iPhone, on android it doesn't disconnect after 10 seconds:

    void OnApplicationFocus(bool pauseStatus) {
    Debug.Log ("paused " + pauseStatus);
    if (pauseStatus) {
    PhotonNetwork.Disconnect();
    Application.LoadLevel("MainMenu");
    }
    }


    so there are times that the ai enemy = scene objects are not moving and doesn't respond at all because the whole process happens on the host so i made an rpc that host send to "others" every 1 second and if it wasn't received for 5 seconds i switch a host and local destroy all the non responding things.

    but after that when another user comes in he can still see some of the scene object that the new host destroyed + more objects from the old host that exited the game using his home button.

    i can make some more tweaks with rcp's and add them to the ai enemy - scene objects to identify if they are shown on the host screen to destroy them but that will take like 4 seconds when a use join and he will see a lot of mess until its all cleared, i can even put him in a waiting spot for a few seconds and then move him to the game area when he join but all this things are not solving the main problem.

    is there a better way to solve this issues?
    can a host force disconnect another player or maybe force him leave the room?

  • Tobias
    Options
    I think you are a bit on a wrong track for 2 things you want to achieve.

    If you use buffered RPCs to instantiate things, you need to somehow remove the RPCs, when you destroyed the GameObject and don't want others to see it on join. There is a difference between deleting the initial RPC and just buffering yet another to destroy a GO (less than seconds later when you join).

    As said, you can check out the methods of RemoveRPC() and if those don't help, you could have a look inside PUN to gain more control for your needs. I can't present a great solution at the moment.
    You can try to think outside of the box, too. What if you don't destroy the GO but keep it as "pooled"? Could you hide it and re-use later on?


    Also, you don't need to send RPCs to measure of some player is active or not. If you wanted to, you can measure if the GOs of a player move within some time. The RPC is just overhead. You can send it, if the player doesn't send anything else.

    If you call Disconnect in OnApplicationFocus(), you should be disconnected. Are you saying the connection is kept alive for long?
  • guyhazi
    Options
    Tobias said:



    If you call Disconnect in OnApplicationFocus(), you should be disconnected. Are you saying the connection is kept alive for long?

    yes, if you got 2 android devices i can give you a link to my game that uses the that code to disconnect and you will see, or you can believe me :wink: .
    as you suggested i will go on "pool" of scene object, i will not instantiate or destroy the enemies, i will make an empty game object that will hold their current "status" such as location direction speed and their "target" player and once host i changed i will make sure they keep their "statues" or so, i still thinking about it once il finish updating and adding some more stuff i will get to that object handling part and il come up with some better idea hopefully

    thanks for the replay.
  • Tobias
    Options
    I will look into the issue on Android.
    The client might not be disconnected right away but it should no longer react to incoming messages (as it's at least locally disconnected) and it should timeout after no more than 10 seconds. Maybe you don't have the time to wait for that...
  • Tobias
    Options
    I checked this and found that calling Disconnet() usually informs the server of the client's disconnect. The player gets removed from the room within a second usually.

    Why "usually"?
    When you disconnect because the app goes to the background or gets closed, then the Photon client has only one shot of telling the server it disconnects. It can send a package but if that's lost, the client is not active to repeat it and the server has to timeout the client.

    There are various issues in Unity with OnApplicationFocus() and OnApplicationPause(). Some exports don't call them before the app is suspended, some get the parameter wrong. If the parameter is wrong (e,g,), you disconnect when the app gets focus again.
    Make extra sure those methods are called as you expect! Debug.Log is your friend.