Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Dynamic Wall Creation Networked - Not showing walls spawned from client on the host.

Discussion in 'Multiplayer' started by Vinnyd21, Nov 7, 2018.

  1. Vinnyd21

    Vinnyd21

    Joined:
    Sep 5, 2018
    Posts:
    5
    I'm having issues with networking a script to spawn dynamic walls. I can get it "working" in several different capacities, but none to the actual desired effect. In this state, both the client player and host player can spawn and draw the walls, but only the client is able to view the walls spawn by the host. The host has no knowledge of the walls spawned by the client.

    Here is the script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Networking;
    5.  
    6. [RequireComponent(typeof(Camera))]
    7. public class DrawWalls_Network : NetworkBehaviour {
    8.  
    9.     public bool creating;
    10.     public GameObject startPrefab;
    11.     public GameObject endPrefab;
    12.     public GameObject[] wallPrefabs;
    13.     GameObject wall;
    14.     public int currentWall = 0;
    15.     Camera drawCam;
    16.     //public NHNetworkedPoolWalls[] walls;
    17.  
    18.     // Use this for initialization
    19.     void Start ()
    20.     {
    21.         drawCam = GetComponent<Camera>();
    22.         //if (NetworkServer.active)
    23.             //pools = FindObjectsOfType<NHNetworkedPoolWalls>();
    24.  
    25.         SelectWall();
    26.     }
    27.    
    28.     // Update is called once per frame
    29.     void Update ()
    30.     {
    31.         if (!isLocalPlayer)
    32.             return;
    33.  
    34.         GetInput();
    35.  
    36.         int previousWall = currentWall;
    37.  
    38.         if ((Input.GetAxis("Mouse ScrollWheel") > 0f))
    39.         {
    40.             if (currentWall >= wallPrefabs.Length - 1)
    41.                 currentWall = 0;
    42.             else
    43.                 currentWall++;
    44.         }
    45.         if ((Input.GetAxis("Mouse ScrollWheel") < 0f))
    46.         {
    47.             if (currentWall <= 0)
    48.                 currentWall = wallPrefabs.Length - 1;
    49.             else
    50.                 currentWall--;
    51.         }
    52.  
    53.         if (previousWall != currentWall)
    54.         {
    55.             SelectWall();
    56.         }
    57.     }
    58.  
    59.     public void GetInput()
    60.     {
    61.         if (Input.GetMouseButtonDown(0))
    62.         {
    63.             SetStart();
    64.         }
    65.         else if (Input.GetMouseButtonUp(0))
    66.         {
    67.             SetEnd();
    68.         }
    69.         else
    70.         {
    71.             if (creating)
    72.             {
    73.                 Adjust();
    74.             }
    75.         }
    76.     }
    77.  
    78.     public void SetStart()
    79.     {
    80.         creating = true;
    81.         startPrefab.transform.position = getWorldPoint();
    82.         wall = (GameObject)Instantiate(wallPrefabs[currentWall], startPrefab.transform.position, Quaternion.identity);
    83.         NetworkServer.Spawn(wall);
    84.         //CmdSpawnWall(currentWall);
    85.     }
    86.  
    87.     //[Command]
    88.     //public void CmdSpawnWall(int currentWall)
    89.     //{
    90.         //wall = (GameObject)Instantiate(wallPrefabs[currentWall], startPrefab.transform.position, Quaternion.identity);
    91.         //NetworkServer.Spawn(wall);
    92.     //}
    93.  
    94.     public void SetEnd()
    95.     {
    96.         creating = false;
    97.         endPrefab.transform.position = getWorldPoint();
    98.     }
    99.  
    100.  
    101.     public void Adjust()
    102.     {
    103.         endPrefab.transform.position = getWorldPoint();
    104.         AdjustWall();
    105.     }
    106.  
    107.     public void AdjustWall()
    108.     {
    109.         startPrefab.transform.LookAt(endPrefab.transform.position);
    110.         endPrefab.transform.LookAt(startPrefab.transform.position);
    111.         float distance = Vector3.Distance(startPrefab.transform.position, endPrefab.transform.position);
    112.         wall.transform.position = startPrefab.transform.position + distance / 2 * startPrefab.transform.forward;
    113.         wall.transform.rotation = startPrefab.transform.rotation;
    114.         wall.transform.localScale = new Vector3(wall.transform.localScale.x, wall.transform.localScale.y, distance);
    115.     }
    116.  
    117.     Vector3 getWorldPoint()
    118.     {
    119.         Ray ray = drawCam.ScreenPointToRay(Input.mousePosition);
    120.         RaycastHit hit;
    121.         if(Physics.Raycast(ray, out hit))
    122.         {
    123.             return hit.point;
    124.         }
    125.         return Vector3.zero;
    126.     }
    127.  
    128.     void SelectWall()
    129.     {
    130.         int i = 0;
    131.         foreach (GameObject wall in wallPrefabs)
    132.         {
    133.             if (i == currentWall)
    134.                 wall.gameObject.SetActive(true);
    135.             else
    136.                 wall.gameObject.SetActive(false);
    137.             i++;
    138.         }
    139.     }
    140. }
    The CmdSpawnWall, that is currently commented out, will make it so that the client won't spawn anything, and that the host only spawns the prefab post without changing the scale
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Clients cannot call NetworkServer.Spawn, because they are not a server. If you want to spawn something from the client, you don't instantiate it at all on the client. You send a command from either that client's Player GameObject, or another object that the server assigned authority to that client, and in the Command (which runs on the server) you instantiate/spawn the object.

    From the way this script is written, it doesn't look like it would be attached to a Player GameObject, or another object that a single client would be assigned authority over. Assuming I'm correct, whenever the client would call any commands on it you will see a warning in the console about lack of authority to send the Command (which means it won't be sent).

    So as written, your SetStart method shouldn't be run on a client. Your commented out Command is confusing because you're naming its only parameter the same name as a public variable of the same class, which at best is not recommended.

    Your StartPrefab and EndPrefab objects, I don't understand what you are doing with setting their position. Why would you set positions of prefabs? Or are you mislabeling them, instead of being prefabs they are instantiated objects? (prefabs are objects in your assets folder that don't exist in the scene, you instantiate a prefab to create one in your scene, but the object that is instantiated is not a prefab - it is analogous to the blueprints of a house vs an actual house, as you would never say you just moved into a 3 bedroom blueprint even though a contractor effectively instantiated a blueprint to create the house)

    If they are instantiated/spawned objects, you should only move them on the server unless the server has assigned this client authority over the object, or you are manually syncing movement between the server and client without using a NetworkTransform component. If you just move them on the client they will be immediately out of sync from their position on the server.
     
    Last edited: Nov 7, 2018
  3. Vinnyd21

    Vinnyd21

    Joined:
    Sep 5, 2018
    Posts:
    5
    Joe-Censored, the script is attached to a Player GameObject, but I am getting the error you described, which doesn't make sense to me. The StartPrefab and EndPrefab have been both prefabs and instantiated objects, Setting their positions is what sets the start and end point of the dynamic wall. How would I only move them on the server? is that done thru command? I have been using them as prefabs because all players of the game will be able to draw walls at the same time, and it was my assumption (which could be entirely incorrect) that if they existed in the scene that the server and client would fight for control over them. How do you recommend changing the script so it works?
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    To move them on the server, you'd just check for isServer (or if the server has authority over the objects, you can check for has Authority) and then move the objects. If the objects have a NetworkTransform component they should automatically move to the new position on all clients. If you want to move them from the client, you'd send a Command to the server to tell the server to do the movement as above.

    If you're going to let players move the same objects, you're going to want server authority over the objects and have the players tell the server through Commands to make those movements.