Search Unity

Resolved Networkvariable Value does not update , cannot solve problem with ServerRpc

Discussion in 'Netcode for GameObjects' started by twinmatrix, Jan 3, 2022.

  1. twinmatrix

    twinmatrix

    Joined:
    Sep 6, 2012
    Posts:
    38
    Well, my very first question on a forum, and I think it's a very simple, for me embarrassing question, with a simple answer . But I just can't find the solution (probably because I don't think in a proper network way yet).

    To make my question clearer, I have stripped the program as much as possible and added comments and Debugs.

    The program now consists of only two buttons, which are intended to change the value of a Network variable index (one button gives the value 1 to the setIndexValue() method, the other the value 2. However, the value of the Network variable changes only within the method called by the Button, but remains unchanged in the rest of the program.

    Because I thought it had something to do with Writing persmissions (the value of Networkvariable can only be changed on a Server) I also tried to solve the problem this with a Class variable (getal) but it gives the same issue.

    After that I tried to solve the problem with a ServerRpc, but this threw up another problem. See second piece of code.

    What stupid thinking mistake am I making? How do I solve the problem?

    Original Problem:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Netcode;
    5.  
    6.  
    7. public class ValueChanger3 : NetworkBehaviour {
    8.  
    9.     public NetworkVariable<int> index = new NetworkVariable<int>(); // NETWORKVARIABLE
    10.     public int getal; // CLASS VARIABLE
    11.  
    12.     private NetworkObject prefabToSpawn;
    13.     public NetworkObject prefabToSpawn1;
    14.     public NetworkObject prefabToSpawn2;
    15.     public LayerMask spawnedObjectLayer;
    16.  
    17.     Vector3 startDirection = new Vector3(0, 0, 0);
    18.  
    19.     void Start() {
    20.         index.Value = 1; // WORKS AS EXPECTED, NETWORKVARIABLE CHANGES VALUE
    21.         getal = 1;
    22.         Debug.Log("index.value in Start(): " + index.Value);
    23.         //Debug.Log("getal in Start(): " + getal);
    24.         switch (index.Value)
    25.         {
    26.             case 1:
    27.                 this.prefabToSpawn = prefabToSpawn1;
    28.                 break;
    29.             case 2:
    30.                 this.prefabToSpawn = prefabToSpawn2;
    31.                 break;
    32.             default:
    33.                 break;
    34.         }
    35.         Debug.Log("prefabToSpwan in Start() is " + prefabToSpawn.name);
    36.     }
    37.  
    38.     public override void OnNetworkSpawn()
    39.     {
    40.         Debug.Log("hallo");
    41.     }
    42.  
    43.     void Update() {
    44.         Debug.Log("index.value in Update(): " + index.Value); // NEVER GETS THE NEW VALUE WHICH WAS UPDATED WITH THE BUTTON OUT OF setIndexValue()
    45.         Debug.Log("getal in Update(): " + this.getal); // NEVER GETS THE NEW VALUE WHICH WAS UPDATED WITH THE BUTTON OUT OF setIndexValue()
    46.         if (IsServer)
    47.         {
    48.             UpdateServer();
    49.         }
    50.  
    51.         if (IsClient && IsOwner)
    52.         {
    53.             UpdateClient();
    54.         }
    55.     }
    56.  
    57.  
    58.     private void UpdateServer()
    59.     {
    60.         Debug.Log("index.value in UpdateServer(): " + index.Value);
    61.         Debug.Log("this.getal in UpdateServer(): " + this.getal);
    62.     }
    63.  
    64.     private void UpdateClient()
    65.     {
    66.         if (!prefabToSpawn) return;
    67.  
    68.         if (Input.GetMouseButtonDown(0))
    69.         {
    70.             Debug.Log("index.value in UpdateClient(): " + index.Value);
    71.             Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f);
    72.             Vector3 worldPos;
    73.             Ray ray = Camera.main.ScreenPointToRay(mousePos);
    74.             RaycastHit hit;
    75.             if (Physics.Raycast(ray, out hit, 1000f))
    76.             {
    77.                 worldPos = hit.point;
    78.  
    79.                 if (hit.collider.gameObject.tag.Equals("EntrePlayer") && !Physics.CheckSphere(hit.transform.position, 1.0f, spawnedObjectLayer))
    80.                 {
    81.                     SpawnPrefabServerRpc(hit.transform.position);
    82.                 }
    83.             }
    84.             else
    85.             {
    86.                 worldPos = Camera.main.ScreenToWorldPoint(mousePos);
    87.             }
    88.         }
    89.     }
    90.  
    91.  
    92.     [ServerRpc]
    93.     private void SpawnPrefabServerRpc(Vector3 pos)
    94.     {
    95.         //Debug.Log("getal in SpawnPrefabServerRp -> getal is " + getal);
    96.         Debug.Log("index.value in SpawnPrefabServerRpc: " + index.Value);
    97.         switch (index.Value)
    98.         {
    99.             case 1:
    100.                 this.prefabToSpawn = prefabToSpawn1;
    101.                 break;
    102.             case 2:
    103.                 this.prefabToSpawn = prefabToSpawn2;
    104.                 break;
    105.             default:
    106.                break;
    107.         }
    108.         Debug.Log("prefabToSpwan in SpawnPrefabServerRp() is " + prefabToSpawn.name);
    109.        // NetworkObject no = Instantiate(prefabToSpawn, pos, Quaternion.LookRotation(startDirection));
    110.         //no.Spawn();
    111.     }
    112.  
    113.     public void setIndexValue(int buttonValue) // THIS DOES NOT WORK BECAUSE ONLY A SERVER CAN WRITE TO A NETWORKVARIABLE ? SO WE NEED TO WRITE TO A SERVERRPC ?
    114.                                                 // BUT ALSO THE CLASS VARIABLE getal DOES NOT UPDATE TO OUTSIDE THIS METHOD
    115.     {
    116.         this.getal = buttonValue;
    117.         index.Value = buttonValue;
    118.         Debug.Log("Networkvariable index.value in setIndexValue -> index.value is " + index.Value); // Works OK
    119.         Debug.Log("Class variable getal in changeIndexValueServerRp -> getal is " + getal); // Works OK
    120.     }
    121.  
    122. } // END CLASS
    123.  

    I tried to solve the Writepermissions error (if that was the problem?) with using an ServerRpc, see next code. But this delivers an NullReferenceException. It makes no difference if I use the Networkvariable as parameter or the Class variable. I am not allowed to use the ServerRpc call.
    Error meddage:
    [Netcode] Could not get NetworkObject for the NetworkBehaviour. Are you missing a NetworkObject component?
    UnityEngine.Debug:LogWarning (object)


    upload_2022-1-3_14-43-58.png


    What is the think-error which I make here? How do I solve the problem?



    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using Unity.Netcode;
    6.  
    7.  
    8. public class ValueChanger2 : NetworkBehaviour {
    9.  
    10.     public NetworkVariable<int> index = new NetworkVariable<int>(); // NETWORKVARIABLE
    11.     public int getal; // CLASS VARIABLE
    12.  
    13.     private NetworkObject prefabToSpawn;
    14.     public NetworkObject prefabToSpawn1;
    15.     public NetworkObject prefabToSpawn2;
    16.     public LayerMask spawnedObjectLayer;
    17.  
    18.     Vector3 startDirection = new Vector3(0, 0, 0);
    19.  
    20.     void Start() {
    21.         index.Value = 1; // WORKS AS EXPECTED, NETWORKVARIABLE CHANGES VALUE
    22.         getal = 1;
    23.         Debug.Log("index.value in Start(): " + index.Value);
    24.         //Debug.Log("getal in Start(): " + getal);
    25.         switch (index.Value)
    26.         {
    27.             case 1:
    28.                 this.prefabToSpawn = prefabToSpawn1;
    29.                 break;
    30.             case 2:
    31.                 this.prefabToSpawn = prefabToSpawn2;
    32.                 break;
    33.             default:
    34.                 break;
    35.         }
    36.         Debug.Log("prefabToSpwans in Start() is " + prefabToSpawn.name);
    37.     }
    38.  
    39.     public override void OnNetworkSpawn()
    40.     {
    41.         Debug.Log("hallo");
    42.     }
    43.  
    44.     void Update() {
    45.         if (IsServer)
    46.         {
    47.             UpdateServer();
    48.         }
    49.  
    50.         if (IsClient && IsOwner)
    51.         {
    52.             UpdateClient();
    53.         }
    54.     }
    55.  
    56.  
    57.     private void UpdateServer()
    58.     {
    59.     }
    60.  
    61.     private void UpdateClient()
    62.     {
    63.         if (!prefabToSpawn) return;
    64.  
    65.         if (Input.GetMouseButtonDown(0))
    66.         {
    67.             Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f);
    68.             Vector3 worldPos;
    69.             Ray ray = Camera.main.ScreenPointToRay(mousePos);
    70.             RaycastHit hit;
    71.             if (Physics.Raycast(ray, out hit, 1000f))
    72.             {
    73.                 worldPos = hit.point;
    74.  
    75.                 if (hit.collider.gameObject.tag.Equals("EntrePlayer") && !Physics.CheckSphere(hit.transform.position, 1.0f, spawnedObjectLayer))
    76.                 {
    77.                     SpawnPrefabServerRpc(hit.transform.position);
    78.                 }
    79.             }
    80.             else
    81.             {
    82.                 worldPos = Camera.main.ScreenToWorldPoint(mousePos);
    83.             }
    84.         }
    85.     }
    86.  
    87.  
    88.     [ServerRpc]
    89.     private void SpawnPrefabServerRpc(Vector3 pos)
    90.     {
    91.         //Debug.Log("getal in SpawnPrefabServerRp -> getal is " + getal);
    92.         Debug.Log("index.value in SpawnPrefabServerRpc: " + index.Value);
    93.         switch (index.Value)
    94.         {
    95.             case 1:
    96.                 this.prefabToSpawn = prefabToSpawn1;
    97.                 break;
    98.             case 2:
    99.                 this.prefabToSpawn = prefabToSpawn2;
    100.                 break;
    101.             default:
    102.                break;
    103.         }
    104.         Debug.Log("prefabToSpwan in SpawnPrefabServerRp() is " + prefabToSpawn.name);
    105.        // NetworkObject no = Instantiate(prefabToSpawn, pos, Quaternion.LookRotation(startDirection));
    106.         //no.Spawn();
    107.     }
    108.  
    109.     public void setIndexValue(int buttonValue)
    110.     {
    111.         this.getal = buttonValue;
    112.         index.Value = buttonValue;
    113.         Debug.Log("Networkvariable index.value in setIndexValue -> index.value is " + index.Value); // Works OK
    114.         Debug.Log("Class variable getal in changeIndexValueServerRp -> getal is " + getal); // Works OK
    115.         changeIndexValueServerRpc(index.Value); // THIS DOES NOT WORK, FOR WHATEVER REASON? -> cannot call the ServerRpc *****
    116.     }
    117.  
    118.     [ServerRpc]
    119.     private void changeIndexValueServerRpc(int localValue)
    120.     {
    121.         Debug.Log("Networkvariable index.value in changeIndexValueServerRp -> index.Value is " + index.Value); // Works OK
    122.         Debug.Log("Class variable getal in changeIndexValueServerRp -> getal is " + getal); // Works OK
    123.         getal = localValue;
    124.         index.Value = localValue;
    125.     }
    126.  
    127. } // END CLASS
    128.  
    Like I said I am not used to using forums, so excuses when I don't follow the proper rules for using it.
    I will upload the full code but I do not know if that is the proper way to do it or that it is too much.

    Thanks in advance!
     
  2. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    666
    Check all your network prefabs have the NetworkObject component.

    Are you also testing this code on a separate client as well as the host, as you should be getting an error trying to set the index in Start without an IsServer check.

    Forgot to mention, you might need to use
    [ServerRpc(RequireOwnership = false)]
    if you're calling the server rpc without client ownership.
     
    Last edited: Jan 3, 2022
  3. twinmatrix

    twinmatrix

    Joined:
    Sep 6, 2012
    Posts:
    38
    Hi Cerestorm, thanks for your assistance.

    You are right, I was first trying to get it right on the Host.

    All object have an NetworkObject (and NetworkTransform) component. I even did some on the Canvas and the buttons, just to test, and that made no difference (so I removed them afterwords).

    I've tried
    but it has no effect. See code below.

    I've reduced the problem to being stucked in the public void setIndexValue(int buttonValue) method.
    It is not posible (in my code haha) to get (changed) values out off the method.

    NothingWorksHaHa.PNG

    Like you see in the code, I even tried a class variable (getal) to get the values from this method to other methods. But it seems that instances of NetworkBehaviour cannot handle class variables (class members) like we normal do??? I cannot get this value either out of the method. The values update like they have to within the method (see the Debugs).

    This if OR a think-error of me OR a bug within Netcode NetworkBehaviour. I'm counting on it being the first of the two haha.

    I've simplefied the project and code further. If you or somebody else can see what I do wrong (and it HAS to be a think-error of me :confused:, because the solution should be simple, but I don't see it), I would appreciate it and than I can sleep again :p:p:p.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Netcode;
    5.  
    6.  
    7. public class ValueChanger4 : NetworkBehaviour {
    8.  
    9.     public NetworkVariable<int> index = new NetworkVariable<int>(); // NETWORKVARIABLE
    10.     public int getal; // CLASS VARIABLE
    11.  
    12.     private NetworkObject prefabToSpawn;
    13.     public NetworkObject prefabToSpawn1;
    14.     public NetworkObject prefabToSpawn2;
    15.     public LayerMask spawnedObjectLayer;
    16.  
    17.     Vector3 startDirection = new Vector3(0, 0, 0);
    18.  
    19.     void Start() {
    20.         this.getal = 1;
    21.         switch (getal)
    22.         {
    23.             case 1:
    24.                 this.prefabToSpawn = prefabToSpawn1;
    25.                 break;
    26.             case 2:
    27.                 this.prefabToSpawn = prefabToSpawn2;
    28.                 break;
    29.             default:
    30.                 break;
    31.         }
    32.         Debug.Log("prefabToSpwans in Start() is " + prefabToSpawn.name);
    33.     }
    34.  
    35.     public override void OnNetworkSpawn()
    36.     {
    37.         Debug.Log("hallo");
    38.     }
    39.  
    40.     void Update() {
    41.         if (IsServer)
    42.         {
    43.             UpdateServer();
    44.         }
    45.  
    46.         if (IsClient && IsOwner)
    47.         {
    48.             UpdateClient();
    49.         }
    50.     }
    51.  
    52.  
    53.     private void UpdateServer()
    54.     {
    55.         Debug.Log("this.getal in UpdateServer() -> " + this.getal);
    56.         Debug.Log("index.Value in UpdateServer() -> " + index.Value);
    57.         //index.Value = this.getal; // HAS NO EFFECT EITHER, CLASS VARIABLE DOES NOT UPDATE IN THE CLASS
    58.     }
    59.  
    60.     private void UpdateClient()
    61.     {
    62.        // if (!prefabToSpawn) return;
    63.  
    64.         if (Input.GetMouseButtonDown(0)) // EVERY CLIENT LOOKS FOR MOUSECLICK
    65.         {
    66.             Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f);
    67.             Vector3 worldPos;
    68.             Ray ray = Camera.main.ScreenPointToRay(mousePos);
    69.             RaycastHit hit;
    70.             if (Physics.Raycast(ray, out hit, 1000f))
    71.             {
    72.                 worldPos = hit.point;
    73.  
    74.                 if (hit.collider.gameObject.tag.Equals("EntrePlayer") && !Physics.CheckSphere(hit.transform.position, 1.0f, spawnedObjectLayer))
    75.                 {
    76.                     SpawnPrefabServerRpc(hit.transform.position); // IF MOUSECLICK IS OK, LET SERVER SPAWN A NETWORKOBJECT
    77.                 }
    78.             }
    79.             else
    80.             {
    81.                 worldPos = Camera.main.ScreenToWorldPoint(mousePos);
    82.             }
    83.         }
    84.     }
    85.  
    86.  
    87.     [ServerRpc]
    88.     private void SpawnPrefabServerRpc(Vector3 pos)
    89.     {
    90.         if (!prefabToSpawn) return;
    91.  
    92.         switch (index.Value) // SERVER LOOKS FOR VALUE OF THE NETWORKVARIABLE, AND SPAWNS CORRESPONDENDING OBJECT
    93.         {
    94.             case 1:
    95.                 this.prefabToSpawn = prefabToSpawn1;
    96.                 break;
    97.             case 2:
    98.                 this.prefabToSpawn = prefabToSpawn2;
    99.                 break;
    100.             default:
    101.                break;
    102.         }
    103.         Debug.Log("prefabToSpwan in SpawnPrefabServerRp() is " + prefabToSpawn.name);
    104.         NetworkObject no = Instantiate(prefabToSpawn, pos, Quaternion.LookRotation(startDirection));
    105.         no.Spawn();
    106.     }
    107.  
    108.     public void setIndexValue(int buttonValue) // VALUE SEND BY BUTTON TO CLIENT
    109.     {
    110.         this.getal = buttonValue; // BECAUSE WE CAN BE ON CLIENT USE CLASS VARIABLE OF LOCAL VARIABLE
    111.         Debug.Log("this.getal after Mouseclick -> " + this.getal); // THIS WORKS INSIDE THIS METHOD
    112.  
    113.         //changeIndexValueServerRpc(this.getal); // SEND THIS VALUE TO SERVERRPC TO UPDATE THE VALUE OF THE NETWORKVARIABLE
    114.         // FOR WHATEVER REASON? -> cannot call the ServerRpc *****
    115.  
    116.         index.Value = buttonValue; // THIS ALSO WORKS INSIDE THIS METHOD but index does not update to outside this method
    117.  
    118.         prefabToSpawn = prefabToSpawn2; // Just in case: does not work either
    119.  
    120.     }
    121.  
    122.     [ServerRpc(RequireOwnership = false)]
    123.     private void changeIndexValueServerRpc(int classValue)
    124.     {
    125.         index.Value = classValue; // UPDATE THE NETWORKVARIABLE ON THE SERVER
    126.     }
    127.  
    128.  
    129. } // END CLASS
    130.  
     
  4. twinmatrix

    twinmatrix

    Joined:
    Sep 6, 2012
    Posts:
    38
    I found an indication about the error. Somehow using IsOwner throws an exception error.
    within the setIndexValue(int buttonValue) method. Both the IF Clause and the ELSE Clause cannot be executed. Instead, the program hangs on using IsOwner in the method.

    NullReferenceException: Object reference not set to an instance of an object
    Unity.Netcode.NetworkBehaviour.get_IsOwner () (at C:/UnityProjects/Simpel tester 2 Battle Gears Basis 2020_3 Multiplayer/Library/PackageCache/com.unity.netcode.gameobjects@1.0.0-pre.3/Runtime/Core/NetworkBehaviour.cs:227)


    IsClient, IsServer and IsHost are OK within the method setIndexValue(int buttonValue). And also the use of IfOwner on line 48 gives no problem!!!

    So why is there a problem with the use of the ownership in the method setIndexValue(int buttonValue) ???

    It surely is the reason that the ServerRpc cannot be called (that needs Ownership). But I cannot imagíng why there is a problem. The script is bounded to a NetworkObject (the Player object that is spawned into the scene). See below the code.

    Code (CSharp):
    1.  
    2. public void setIndexValue(int buttonValue) // VALUE SEND BY BUTTON TO CLIENT
    3.     {
    4.         Debug.Log("WE ZITTEN IN SETINDEXVALUE");
    5.        if (IsOwner)
    6.         {
    7.             Debug.Log("OWNER GAAT SERVERRPC AANROEPEN");
    8.             this.getal = buttonValue; // BECAUSE WE CAN BE ON CLIENT USE CLASS VARIABLE OF LOCAL VARIABLE
    9.             Debug.Log("this.getal after Mouseclick -> " + this.getal); // THIS WORKS INSIDE THIS METHOD
    10.  
    11.             //changeIndexValueServerRpc(buttonValue); // SEND THIS VALUE TO SERVERRPC TO UPDATE THE VALUE OF THE NETWORKVARIABLE
    12.             // FOR WHATEVER REASON? -> cannot call the ServerRpc *****
    13.             changeIndexValueServerRpc(buttonValue);
    14.             index.Value = buttonValue; // THIS ALSO WORKS INSIDE THIS METHOD
    15.  
    16.             prefabToSpawn = prefabToSpawn2; // Just in case: does not work either
    17.  
    18.         }
    19.         else
    20.         {
    21.             Debug.Log("THIS CLIENT IS NO OWNER");
    22.         }
    View attachment 981792
     

    Attached Files:

    Last edited: Jan 5, 2022
  5. twinmatrix

    twinmatrix

    Joined:
    Sep 6, 2012
    Posts:
    38
    I can't explain it at the moment, but because an "external" button calls the method, ownership is somehow disrupted (Button takes ownership of the method???). And so the new values don't come into the ownership of the object. How is that possible?

    I checked by adding a simple new method with a timer, and it can adjust the value of the network variable index (see code). After 30 seconds, the value of prefabToSpawn is changed, as encoded.
    So my old code was normally good, but not within this Netcode environment.

    Can someone please explain to me the strange behavior that that happens when a value is passed by an external button??? I don't see the logic at all that this can change the Ownership of the script (locally).

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Netcode;
    5.  
    6.  
    7. public class ValueChanger4 : NetworkBehaviour {
    8.  
    9.     public NetworkVariable<int> index = new NetworkVariable<int>(); // NETWORKVARIABLE
    10.     public int getal; // CLASS VARIABLE
    11.  
    12.     private NetworkObject prefabToSpawn;
    13.     public NetworkObject prefabToSpawn1;
    14.     public NetworkObject prefabToSpawn2;
    15.     public LayerMask spawnedObjectLayer;
    16.  
    17.     Vector3 startDirection = new Vector3(0, 0, 0);
    18.  
    19.     private int keuze;
    20.  
    21.     float timeLeft = 30.0f;
    22.  
    23.     void Start() {
    24.         this.getal = 1;
    25.         switch (getal)
    26.         {
    27.             case 1:
    28.                 this.prefabToSpawn = prefabToSpawn1;
    29.                 break;
    30.             case 2:
    31.                 this.prefabToSpawn = prefabToSpawn2;
    32.                 break;
    33.             default:
    34.                 break;
    35.         }
    36.         Debug.Log("prefabToSpwans in Start() is " + prefabToSpawn.name);
    37.     }
    38.  
    39.     public override void OnNetworkSpawn()
    40.     {
    41.         Debug.Log("hallo");
    42.     }
    43.  
    44.     void Update() {
    45.         timerToChangeIndexValue();
    46.  
    47.         if (NetworkManager.Singleton.IsServer)
    48.         {
    49.             UpdateServer();
    50.         }
    51.  
    52.         if (NetworkManager.Singleton.IsClient && IsOwner)
    53.         {
    54.             UpdateClient();
    55.         }
    56.     }
    57.  
    58.  
    59.     private void UpdateServer()
    60.     {
    61.         Debug.Log("this.getal in UpdateServer() -> " + this.getal);
    62.         Debug.Log("index.Value in UpdateServer() -> " + index.Value);
    63.         //index.Value = this.getal; // HAS NO EFFECT EITHER, CLASS VARIABLE DOES NOT UPDATE IN THE CLASS
    64.     }
    65.  
    66.     private void UpdateClient()
    67.     {
    68.        // if (!prefabToSpawn) return;
    69.  
    70.         if (Input.GetMouseButtonDown(0)) // EVERY CLIENT LOOKS FOR MOUSECLICK
    71.         {
    72.             Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f);
    73.             Vector3 worldPos;
    74.             Ray ray = Camera.main.ScreenPointToRay(mousePos);
    75.             RaycastHit hit;
    76.             if (Physics.Raycast(ray, out hit, 1000f))
    77.             {
    78.                 worldPos = hit.point;
    79.  
    80.                 if (hit.collider.gameObject.tag.Equals("EntrePlayer") && !Physics.CheckSphere(hit.transform.position, 1.0f, spawnedObjectLayer))
    81.                 {
    82.                     SpawnPrefabServerRpc(hit.transform.position); // IF MOUSECLICK IS OK, LET SERVER SPAWN A NETWORKOBJECT
    83.                 }
    84.             }
    85.             else
    86.             {
    87.                 worldPos = Camera.main.ScreenToWorldPoint(mousePos);
    88.             }
    89.         }
    90.     }
    91.  
    92.  
    93.     [ServerRpc]
    94.     private void SpawnPrefabServerRpc(Vector3 pos)
    95.     {
    96.         if (!prefabToSpawn) return;
    97.  
    98.         switch (index.Value) // SERVER LOOKS FOR VALUE OF THE NETWORKVARIABLE, AND SPAWNS CORRESPONDENDING OBJECT
    99.         {
    100.             case 1:
    101.                 this.prefabToSpawn = prefabToSpawn1;
    102.                 break;
    103.             case 2:
    104.                 this.prefabToSpawn = prefabToSpawn2;
    105.                 break;
    106.             default:
    107.                break;
    108.         }
    109.         Debug.Log("prefabToSpwan in SpawnPrefabServerRp() is " + prefabToSpawn.name);
    110.         NetworkObject no = Instantiate(prefabToSpawn, pos, Quaternion.LookRotation(startDirection));
    111.         no.Spawn();
    112.     }
    113.  
    114.     public void timerToChangeIndexValue()
    115.     {
    116.         if (timeLeft > -5) Debug.Log("timeLeft is " + timeLeft);
    117.             timeLeft -= Time.deltaTime;
    118.             if (timeLeft < 0)
    119.             {
    120.                 changeIndexValueServerRpc(2); // ServerRpc CAN BE CALLED!!!!
    121.             }
    122.     }
    123.  
    124.  
    125.     public void setIndexValue(int buttonValue) // VALUE SEND BY BUTTON TO CLIENT
    126.     {
    127.         if (IsOwner) // IS TOTAL DISRUPTED!!!!!!
    128.         {
    129.             this.getal = buttonValue; // BECAUSE WE CAN BE ON CLIENT USE CLASS VARIABLE OF LOCAL VARIABLE
    130.              //changeIndexValueServerRpc(buttonValue); // SEND THIS VALUE TO SERVERRPC TO UPDATE THE VALUE OF THE NETWORKVARIABLE
    131.             // FOR WHATEVER REASON? -> cannot call the ServerRpc *****
    132.             index.Value = buttonValue; // THIS ALSO WORKS INSIDE THIS METHOD BUT NOT UPDATED OUTSIDE
    133.  
    134.             prefabToSpawn = prefabToSpawn2; // Just in case: does not work either
    135.  
    136.         }
    137.         else
    138.         {
    139.             Debug.Log("THIS CLIENT IS NO OWNER");
    140.         }
    141.  
    142.     }
    143.  
    144.     //[ServerRpc(RequireOwnership = false)]
    145.     [ServerRpc]
    146.     public void changeIndexValueServerRpc(int classValue)
    147.     {
    148.         index.Value = classValue; // UPDATE THE NETWORKVARIABLE ON THE SERVER
    149.     }
    150.  
    151.  
    152. } // END CLASS
    153.  
     
  6. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    666
    When I added a simple rpc to your script and ran it with a button call from another game object it ran fine. First thing to do is work out whether the problem is inside or outside of the script. Create a new script or network object with just a simple rpc call and check that's working first.

    In case you haven't, have you added your network prefabs to the network manager prefab array?
     
  7. twinmatrix

    twinmatrix

    Joined:
    Sep 6, 2012
    Posts:
    38
    Well, it has to come from outside the script. It has something to do with the Canvas Buttons and Ownership of the script (call of the method setIndexValue(int buttonValue).

    Maybe its because of the buttons being part of the Canvas, and already in the scene before the NetworkSpawn. Or it is just the way I approach the problem.

    How did you use the buttons?

    I programmed the "program" again from scratch, in its bare minimal form. But alas, without success. I included it here as an custom unity package export.
    IF you ever have some time, please take a look at it. You'll be a hero if you can find an solution for the problem in its current state, I can't :eek:.

    I'm afraid that I have to find an total other approach for what I want to do, or use Photon.
     

    Attached Files:

  8. cerestorm

    cerestorm

    Joined:
    Apr 16, 2020
    Posts:
    666
    I had a look, the problem is for the button OnClick call you attached the prefab of your player object which you can't use in this case as you need a network object instantiated and spawned from that prefab.

    The easiest thing to do and what I always have is a game object already in the scene to handle the legwork and have any OnClick calls if needed.

    Something like this should work for you:

    Code (CSharp):
    1. public class GameSceneController : MonoBehaviour
    2. {
    3.  
    4.     public void OnClickSpawnShape(int shapeId)
    5.     {
    6.         ValueChanger valueChanger = FindObjectOfType<ValueChanger>();
    7.  
    8.         Debug.Log("ValueChanger: " + valueChanger);
    9.  
    10.         valueChanger.setIndexValue(shapeId);
    11.     }
    12. }
     
  9. twinmatrix

    twinmatrix

    Joined:
    Sep 6, 2012
    Posts:
    38
    Hi, thanks, you are a Hero! :)

    Your simple solution works great. I was indeed at fault to think that I could use player object as a normal NetworkObject (I also had put the PlayerObject in de NetworkObject list). But seemingly a PlayerObject lacks a kind of ownership (or something). Like I said, a think-error of me.

    BTW, just before I red you solution I found one myself, by making the Canvas a child of the PlayerObject (making the PlayerObject a direct parent of the Canvas, and so owner of the Canvas). But I think your solution is much cleaner and better.

    Well, on to the next (still for me) strange behaviours of Netcode haha.

    Thanks again.
     
    cerestorm likes this.