What is the best/easiest way to keep a ScriptableObject (class) updated for both players ?

Options
Hi,

I have a ScriptableObject (SO) that is basically the status of towns in my game. This SO is just a class with variables int, floats, strings, but also references to other ScriptableObjects (soldiers, houses).

I have 2 players connected in my Pun2 Room.

I know how to share data between them using RPCs, and also using RaiseEvents and CustomProperties.

what about SO's ?

1. serialization?
Let say:
- when Player 1 has finished his turn he has impacted CITY1_SO and CITY2_SO (they are scriptable objects)
- both these ScriptableObject hold several int/float and strings.
- I have learned and managed to convert them into a byterray and use the Serialization in order to send the data...to the other player.
>> is it the right way to do all that ? serialize/deserialize the data each end of turn and send it to the other player ?

Question1: if the Class (scriptableobject) holds a reference to another class (and another scriptable object).... what do i do ? Both players will have all these scriptable objects in their Ressources folder. How do I let all the players know that :
- in CITY1_SO the "soldier" reference has changed from "BigSoldier42" to "SmallSoldier31" (both scriptableobjects in the ressources folder) ?

2. PhontonView
i am confused to what OnPhotonSerializeView does.
I understand that with a photonview component, and having the OnPhotonSerializeView call with iswriting/isreading, i can have (all?) players observe a script and check when it's changing and update it locally (am in understanding right?)....
but this method does not work on custom classes (like a ScriptableObject that holds many variables).... so do I have here also to serialize/deserialize ?


3. Network Instantiated Object
I am sure it is not the case....but are networked instantiated object (which have scripts attached to them (and thus variables....)) automatically updated for all players when their values change?



all in all, I am trying to understand what is the best/easiest way to have the 2 players keep the same updated view of several scriptable objects....



thank you so much


Comments

  • From my current level of understanding it would go as such:

    - if its controller by a player and only their client sees it use: Unity Instantiate
    (cameras, joysticks, UI displays)
    - if its controlled by a player and all clients should see it use: PhotonNetwork.Instantiate
    (player character, health bars)
    - If its created by a player and owned by that player but other clients need to see it use: PunRPC
    (bullets, item pickup)
    - Object that all players must register (similar to a player), but isn't controlled by any client: use PhotonNetwork.InstantiateRoomObject
    (enemies, npcs)
    - If its a status of a SO, use custom properties as RPCs with buffering will stack and cause huge initial load times if they're loading an area where many RPCS needed to be pre loaded so the state is clear
    (doors / chests / unlock states / destroyed state (like a wall from a house in fortnite.. you dont need to know who / how / why its destroyed, just that its destoryed)

    it really depends on what needs to be seen, if players can join late / the game level is loaded through Async scene loading.
    If the players never leave each others game view / can't late join, then in your case you'll want to have a Multiplayer GameManager in your scene in which it has a check for:
    public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
    
    then when you update the custom properties of one player (after their turn finishes per say), the game manager will update the other players custom properties to be the same
  • thanks for your help it's nice to have people here
    From my current level of understanding it would go as such:

    - if its controlled by a player and all clients should see it use: PhotonNetwork.Instantiate
    (player character, health bars)

    - Object that all players must register (similar to a player), but isn't controlled by any client: use PhotonNetwork.InstantiateRoomObject

    so, question about PhotonNetwork.Instantiate
    - if I have a prefab (in my ressource folder) with a script attached, in this simple monobehavior I have 3 variables and a public method that modify these variables.
    - if I PhotonNetwork.Instantiate that prefab
    - all players see it, ok ?
    - if 1 player call the method (locally i guess) that modify those variables : will those variables be changed for all players (without the need to send any info via RPC or whatever) ?


    2.
    my players wont join late games, the 2 players join at the same time, if 1 player drops, game is ended.
    so I will check the OnPlayerPropertiesUpdate, thank you.
    but I read that customproperties is really for only a fews simple variables and not complex set of data.... ?
    but yeah, it can work, i already used them for a few INT for each players.


  • anytime, glad to be of help :)

    1. for your first question, it really depends on what is being updated, for instance if its just setting some data for it to do something later on with, then yes it'll cross between both players, but for that data to be used and crossed properly, you'll either need to use an RPC or extend the class as an IPunObservable, and then add a OnPhotonSerializeView method to send the prefabs data back and forth. (review the default class Photon Transform View to see how it should be done to compensate for lag).

    I'd recommend using RoomObjects combined with RPC's though as they're actually much easier to deal with.
    - For instance, create a NPC or Enemy as a roomObject.
    - Then, whenever it performs an action, run it as an RPC and all players will get the proper displays

    (Enemy performs an attack, which involves it creating a bullet per-say, well because the Enemy is a roomObject and you're creating its attack in an RPC, you can just instantiate the bullet the same way you would if it wasn't multiplayer! No need to add photonViews or check anything on that bullet any different than you would without photon. Thats the beauty of RoomObjects + RPC's combined.

    2. That is true, when it comes to customProperties, think of them as more or like a bool, its either (open/close), (destroyed/alive). You shouldn't be using it for complex things, but heres an example:

    (fornite - They have a house (may or may not be a prefab) but everything that makes it up is a prefab FORSURE.
    - They create this house as a roomObject (if it is a prefab of prefabs), or already have it loaded as sceneObjects in the level (many prefabs not a whole house prefab)
    - Each wall piece / furniture / door / chest is a room object that has its own customProperties.
    - properties can be simple for example a wall has 5 states (new, slightly damage, medium damage, major damaged, destroyed). This is all the wall really is with resource grabs to edit the look based on its customProperty and all it has to do is OnEnable, check its properties and set its state.