Search Unity

Third Party PhotonNetwork, syncing objects?

Discussion in 'Multiplayer' started by darkAbacus247, Jul 31, 2014.

  1. darkAbacus247

    darkAbacus247

    Joined:
    Sep 7, 2010
    Posts:
    251
    Trying to build controls that will allow a box within the scene to be moved by either the Host or Client. The box is different from the players because it has already been placed in the scene and is not being instantiated. I'm hoping to avoid instantiating the box, as it represents vehicles and other random objects that have been placed around the map.

    ::Current Script::
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class tellToMove : MonoBehaviour {
    5.     bool firstUpdate;
    6.     Vector3 realPosition;
    7.  
    8.     void Update () {
    9.         if (Input.GetKey (KeyCode.Keypad8)){
    10.             realPosition += Vector3.forward;
    11.         }
    12.         if (Input.GetKey (KeyCode.Keypad2)){
    13.             realPosition -= Vector3.forward;
    14.         }
    15.  
    16.         if (PhotonNetwork.inRoom){
    17.             if(!firstUpdate){
    18.                 firstUpdate = true;
    19.                 realPosition = transform.position;
    20.             }
    21.  
    22.             GetComponent<PhotonView>().RPC ("moveMe", PhotonTargets.AllBuffered, realPosition);
    23.         }
    24.     }
    25.  
    26.     [RPC]
    27.     public void moveMe(Vector3 realPosition){
    28.         //print ("moveMe");
    29.         transform.position = Vector3.Lerp (transform.position, realPosition, Time.fixedDeltaTime);
    30.     }
    31.  
    32.     public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info){
    33.         if(stream.isWriting){
    34.             //print ("Writing");
    35.             stream.SendNext(transform.position);
    36.         }
    37.         else{
    38.             //print ("Reading");
    39.             realPosition = (Vector3)stream.ReceiveNext();
    40.         }
    41.     }
    42. }
    With this, if I observe the gameobject transform with the attached photonView I'm able to move the box on either machine but it seems to be fighting with data ((jumps back and forth strangely)). If I observe the above script with photonView I can still move the box on either machine but now it only has a full range of motion with the Host, it seems the client can only move it x-distance from where the host left it, and both seem to jump strangely as before...

    Unfamiliar with networking, I'm not sure how best to describe what I'm viewing, hopefully someone has an idea.
     
  2. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    OK I think with photon network if you use the photon view then the transform should be shared amongst players, so any inputs that affect a transform will be automatically networked and updated.

    Also if the move amount is per the Update() then you should scale it by the Time.deltaTime variable not the fixedDelta time. DeltaTime is per a frame, fixedDelta time is per a physics tick (about 6 times faster).
     
  3. darkAbacus247

    darkAbacus247

    Joined:
    Sep 7, 2010
    Posts:
    251
    I'm still having issues with this actually,
    I can control the box with both players, now it seems that if machineA is moving the box machineA sees the box move while machineB sees machineA's player move to where the box would be and follow along it's path of control dictated by machineA, while their box (machineB) remains still. And the opposite of this if you're controlling with machineB.

    In this video link, you can see everything's good with the players, until I move the box


    I feel i'm closer but still missing something pretty important. Changing the photonView ownership is probably where I've gone wrong, how to fix this...I do not know. In all honesty I thought this would be more straight forward? This seems like a pretty generic thing to want to do.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class tellToMove : Photon.MonoBehaviour {
    5.     bool firstUpdate;
    6.     Vector3 realPosition;
    7.    
    8.     void Update () {
    9.         if (PhotonNetwork.inRoom){
    10.             if(!firstUpdate){
    11.                 firstUpdate = true;
    12.                 realPosition = transform.position;
    13.             }
    14.  
    15.             if (Input.GetKey (KeyCode.Keypad8)){
    16.                 photonView.ownerId = PhotonNetwork.player.ID;
    17.                 realPosition += Vector3.right;
    18.             }
    19.             if (Input.GetKey (KeyCode.Keypad2)){
    20.                 photonView.ownerId = PhotonNetwork.player.ID;
    21.                 realPosition -= Vector3.right;
    22.             }
    23.  
    24.             transform.position = Vector3.Lerp (transform.position, realPosition, Time.deltaTime);
    25.         }
    26.     }
    27.  
    28.     void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info){
    29.         if (stream.isWriting){
    30.             stream.SendNext(realPosition);
    31.         }
    32.         else{
    33.             realPosition = (Vector3)stream.ReceiveNext();
    34.         }
    35.     }
    36. }
     
  4. Arowx

    Arowx

    Joined:
    Nov 12, 2009
    Posts:
    8,194
    No I can't think why you would need something that multiple players can control at once, unless your doing a Ouija board. ;)

    I would expect that most game objects can only be controlled by the closest player and once one player is in control another cannot take it over.

    You could change it so that both players don't control the position but change the physics velocity.
     
  5. BFGames

    BFGames

    Joined:
    Oct 2, 2012
    Posts:
    1,543
    I would drop using the OnPhotonSerializeView.

    Just save realposition when you receive the RPC and then Lerp it locally in Update. If you do so remember to update its position for newly joined players, by sending it from the master client to the newly joined client.

    However the problem with changing the position from more players is that the cube will likely not be in the exact same position on all clients as they will receive the messages at different times, so when a lot of changes from the players occur it might start looking like some crazy movement is going on, just saying :D
     
  6. darkAbacus247

    darkAbacus247

    Joined:
    Sep 7, 2010
    Posts:
    251
    Ha yeah Ouija board would be pretty awesome though

    I'm open to anything really, this is my first attempt at networking, I've only been able to find tutorials on moving players, none for moving objects unfortunately. Basic get in/out of a vehicle, make sure my vehicle movements are updated across server. I could be attacking it all wrong, i don't even know. but since the player moves around fine I thought I'd just convert that code to work for the box. Quickly realized it doesn't, been trying things since
     
  7. darkAbacus247

    darkAbacus247

    Joined:
    Sep 7, 2010
    Posts:
    251
    Sorry guy's I'm clearly not picking up what you're laying down...

    This is exactly what I'm doing:

    Open New scene
    - Create a cube
    - Place 'PhotonView.cs' on cube
    - Place 'viewMe.cs' on cube
    - Drag/Drop 'viewMe.cs' into the Observe field of 'PhotonView.cs'
    - Update the 'viewMe.cs' script with a script that's placed on the player called 'setNumber.cs' . ((This should only be enabled on 1 player at a time, for now...I just want to see something work)).


    viewMe.cs
    (This is on the cube that's in each players scene, not instantiated)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class viewMe : Photon.MonoBehaviour{
    5.     public int setThisNumber;
    6. }


    setNumber.cs
    (This is on the instantiated players)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class setNumber : Photon.MonoBehaviour {
    5.     void Update (){
    6.         if (Input.GetKey (KeyCode.UpArrow)) {
    7.             GameObject.Find ("Cube").GetComponent<viewMe>().setThisNumber = 1;
    8.         }
    9.         if (Input.GetKey (KeyCode.DownArrow)) {
    10.             GameObject.Find ("Cube").GetComponent<viewMe>().setThisNumber = 2;
    11.         }
    12.     }
    13. }
    I really hate asking repeat questions. It all seems pretty straight forward though, this is EXACTLY what I'm doing. Step by step, everything. Hopefully you can see where I'm making my errors and correct me in my no0b ways :)
     
  8. BFGames

    BFGames

    Joined:
    Oct 2, 2012
    Posts:
    1,543
    Right now you are only updating setThisNumber locally.

    Create a method in viewMe in which you pass on a number as an argument, then let that method call a RPC and update the number.

    Also save a reference for the cubes viewMe in Start() så you don't call Find AND GetComponent each time.
     
  9. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    Have you considered creating an array of controllable objects and, if a player is moving it, send it's data via that player's OnPhotonSerializeView and just updating everyone else's array of moveable objects? So essentially you'd use an RPC to build the array initially and to add/remove objects so that everyone has the same array, and then you're only updating if it's being used. This way you'll not need to treat it any differently than any other object in your scene, and in fact could techincally add any object in your scene to that array and players could interact with it and have it sync across clients.
     
  10. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,066
    Please follow the Marco Polo Tutorial. It covers what you describe as "Fight for Control". You basically have to make sure that your key/controller input is only applied to the one character instance you control (and not to each character that is in the room, total). The solution is to check isMine of a PhotonView on the instanced GameObjects.

    See:
    http://doc.exitgames.com/en/pun/current/tutorials/tutorial-marco-polo
     
  11. darkAbacus247

    darkAbacus247

    Joined:
    Sep 7, 2010
    Posts:
    251
    Hey all, sorry for late reply been doing life things.

    Thank you for the responses! I've worked my way through the Marco Polo tutorial, I get decently lost around "Switch it", I feel I followed pretty well up to this point.

    I think this is similar to what I had attempted with my original code post, I've since incorporated some of your suggestions and I can view changes on both machines made by either player. The downside is the changes viewed on receiving machines is a bit choppy, I think this is what BFGames was commenting towards?

    This is what I'm working with now, using the RPC approach :

    NetworkManager (placed on gameobject in scene)
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class NetworkManager_Test : MonoBehaviour {
    6.  
    7.     public GameObject testPlayer;
    8.     public GameObject[] vehicles; //Array of moveable objects
    9.     public Vector3[] realPosition;
    10.  
    11.     void Start (){
    12.         //PhotonNetwork.logLevel = PhotonLogLevel.Full;
    13.         PhotonNetwork.ConnectUsingSettings("0.1");
    14.         vehicles = GameObject.FindGameObjectsWithTag ("Vehicle");
    15.         realPosition = new Vector3[vehicles.Length];
    16.  
    17.         for(int i = 0; i < realPosition.Length; i++){
    18.             realPosition[i] = vehicles[i].transform.position;
    19.         }
    20.     }
    21.  
    22.     void OnJoinedLobby(){
    23.         PhotonNetwork.JoinRandomRoom();
    24.     }
    25.  
    26.     void OnPhotonRandomJoinFailed(){
    27.         PhotonNetwork.CreateRoom(null);
    28.     }
    29.  
    30.     void OnJoinedRoom(){
    31.         print ("Joined Room");
    32.         PhotonNetwork.Instantiate ("testPlayer", Vector3.zero, Quaternion.identity, 0);
    33.     }
    34.  
    35.     void OnGUI(){
    36.         GUILayout.Label(PhotonNetwork.connectionStateDetailed.ToString());
    37.     }
    38.  
    39.     //TODO: Doesn't appear to change anything.
    40.     /*
    41.     public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info){
    42.         for (int i = 0; i < vehicles.Length; i++) {
    43.             if(stream.isWriting){
    44.                 print ("Writing");
    45.  
    46.                 realPosition[i] = vehicles[i].transform.position;
    47.                 //stream.SendNext(this.realPosition);
    48.             }
    49.             else{
    50.                 print ("Reading");
    51.                 //vehicles[i].transform.position = (Vector3)stream.ReceiveNext();
    52.             }
    53.         }
    54.     }*/
    55. }
    Instantiated PlayerController:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class testPlayerController : Photon.MonoBehaviour{
    5.     GameObject NetworkManager;
    6.  
    7.     void Start(){
    8.         NetworkManager = GameObject.Find ("GameObject");
    9.     }
    10.  
    11.     void Update(){
    12.         if (Input.GetKey (KeyCode.Keypad8)) {
    13.             Vector3 newPos = Vector3.Lerp (GameObject.Find ("GameObject").GetComponent<NetworkManager_Test>().vehicles[0].transform.position, GameObject.Find ("GameObject").GetComponent<NetworkManager_Test>().vehicles[0].transform.position + Vector3.forward*10f, Time.deltaTime);
    14.             GetComponent<PhotonView>().RPC ("vehiclePosition", PhotonTargets.AllBuffered, newPos);
    15.         }
    16.         if (Input.GetKey (KeyCode.Keypad2)) {
    17.             Vector3 newPos = Vector3.Lerp (GameObject.Find ("GameObject").GetComponent<NetworkManager_Test>().vehicles[0].transform.position, GameObject.Find ("GameObject").GetComponent<NetworkManager_Test>().vehicles[0].transform.position - Vector3.forward*10f, Time.deltaTime);
    18.             GetComponent<PhotonView>().RPC ("vehiclePosition", PhotonTargets.AllBuffered, newPos);
    19.         }
    20.     }
    21.  
    22.     [RPC]
    23.     void vehiclePosition(Vector3 newPos){
    24.         NetworkManager.GetComponent<NetworkManager_Test>().vehicles[0].transform.position = newPos;
    25.     }
    26. }
    Quite rough I know, I can clean it up when I better understand what's going on...
     
  12. veermalik

    veermalik

    Joined:
    Nov 20, 2019
    Posts:
    2
    Actually in photon the scene object by default own by the master client and only master client can change their position if you want to change their position by client then either you must change their ownership or you can make it a network object using PhotonNetwork.Instantiate(Gameobject),it means you need to spawn the object when we load the scene.
     
  13. Shimagurat

    Shimagurat

    Joined:
    Jan 26, 2019
    Posts:
    1
    if the masterClient left the room the instantiated gameobject will disappear too i need that one time so that game object can still keep running even if the masterclient leave the game
     
  14. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,066
    The Master Client is allowed to InstantiateSceneObject().
    Those should stay alive.
     
    Mr_WindDog likes this.