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:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
public class ValueChanger3 : NetworkBehaviour {
public NetworkVariable<int> index = new NetworkVariable<int>(); // NETWORKVARIABLE
public int getal; // CLASS VARIABLE
private NetworkObject prefabToSpawn;
public NetworkObject prefabToSpawn1;
public NetworkObject prefabToSpawn2;
public LayerMask spawnedObjectLayer;
Vector3 startDirection = new Vector3(0, 0, 0);
void Start() {
index.Value = 1; // WORKS AS EXPECTED, NETWORKVARIABLE CHANGES VALUE
getal = 1;
Debug.Log("index.value in Start(): " + index.Value);
//Debug.Log("getal in Start(): " + getal);
switch (index.Value)
{
case 1:
this.prefabToSpawn = prefabToSpawn1;
break;
case 2:
this.prefabToSpawn = prefabToSpawn2;
break;
default:
break;
}
Debug.Log("prefabToSpwan in Start() is " + prefabToSpawn.name);
}
public override void OnNetworkSpawn()
{
Debug.Log("hallo");
}
void Update() {
Debug.Log("index.value in Update(): " + index.Value); // NEVER GETS THE NEW VALUE WHICH WAS UPDATED WITH THE BUTTON OUT OF setIndexValue()
Debug.Log("getal in Update(): " + this.getal); // NEVER GETS THE NEW VALUE WHICH WAS UPDATED WITH THE BUTTON OUT OF setIndexValue()
if (IsServer)
{
UpdateServer();
}
if (IsClient && IsOwner)
{
UpdateClient();
}
}
private void UpdateServer()
{
Debug.Log("index.value in UpdateServer(): " + index.Value);
Debug.Log("this.getal in UpdateServer(): " + this.getal);
}
private void UpdateClient()
{
if (!prefabToSpawn) return;
if (Input.GetMouseButtonDown(0))
{
Debug.Log("index.value in UpdateClient(): " + index.Value);
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f);
Vector3 worldPos;
Ray ray = Camera.main.ScreenPointToRay(mousePos);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000f))
{
worldPos = hit.point;
if (hit.collider.gameObject.tag.Equals("EntrePlayer") && !Physics.CheckSphere(hit.transform.position, 1.0f, spawnedObjectLayer))
{
SpawnPrefabServerRpc(hit.transform.position);
}
}
else
{
worldPos = Camera.main.ScreenToWorldPoint(mousePos);
}
}
}
[ServerRpc]
private void SpawnPrefabServerRpc(Vector3 pos)
{
//Debug.Log("getal in SpawnPrefabServerRp -> getal is " + getal);
Debug.Log("index.value in SpawnPrefabServerRpc: " + index.Value);
switch (index.Value)
{
case 1:
this.prefabToSpawn = prefabToSpawn1;
break;
case 2:
this.prefabToSpawn = prefabToSpawn2;
break;
default:
break;
}
Debug.Log("prefabToSpwan in SpawnPrefabServerRp() is " + prefabToSpawn.name);
// NetworkObject no = Instantiate(prefabToSpawn, pos, Quaternion.LookRotation(startDirection));
//no.Spawn();
}
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 ?
// BUT ALSO THE CLASS VARIABLE getal DOES NOT UPDATE TO OUTSIDE THIS METHOD
{
this.getal = buttonValue;
index.Value = buttonValue;
Debug.Log("Networkvariable index.value in setIndexValue -> index.value is " + index.Value); // Works OK
Debug.Log("Class variable getal in changeIndexValueServerRp -> getal is " + getal); // Works OK
}
} // END CLASS
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)
What is the think-error which I make here? How do I solve the problem?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;
public class ValueChanger2 : NetworkBehaviour {
public NetworkVariable<int> index = new NetworkVariable<int>(); // NETWORKVARIABLE
public int getal; // CLASS VARIABLE
private NetworkObject prefabToSpawn;
public NetworkObject prefabToSpawn1;
public NetworkObject prefabToSpawn2;
public LayerMask spawnedObjectLayer;
Vector3 startDirection = new Vector3(0, 0, 0);
void Start() {
index.Value = 1; // WORKS AS EXPECTED, NETWORKVARIABLE CHANGES VALUE
getal = 1;
Debug.Log("index.value in Start(): " + index.Value);
//Debug.Log("getal in Start(): " + getal);
switch (index.Value)
{
case 1:
this.prefabToSpawn = prefabToSpawn1;
break;
case 2:
this.prefabToSpawn = prefabToSpawn2;
break;
default:
break;
}
Debug.Log("prefabToSpwans in Start() is " + prefabToSpawn.name);
}
public override void OnNetworkSpawn()
{
Debug.Log("hallo");
}
void Update() {
if (IsServer)
{
UpdateServer();
}
if (IsClient && IsOwner)
{
UpdateClient();
}
}
private void UpdateServer()
{
}
private void UpdateClient()
{
if (!prefabToSpawn) return;
if (Input.GetMouseButtonDown(0))
{
Vector3 mousePos = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f);
Vector3 worldPos;
Ray ray = Camera.main.ScreenPointToRay(mousePos);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 1000f))
{
worldPos = hit.point;
if (hit.collider.gameObject.tag.Equals("EntrePlayer") && !Physics.CheckSphere(hit.transform.position, 1.0f, spawnedObjectLayer))
{
SpawnPrefabServerRpc(hit.transform.position);
}
}
else
{
worldPos = Camera.main.ScreenToWorldPoint(mousePos);
}
}
}
[ServerRpc]
private void SpawnPrefabServerRpc(Vector3 pos)
{
//Debug.Log("getal in SpawnPrefabServerRp -> getal is " + getal);
Debug.Log("index.value in SpawnPrefabServerRpc: " + index.Value);
switch (index.Value)
{
case 1:
this.prefabToSpawn = prefabToSpawn1;
break;
case 2:
this.prefabToSpawn = prefabToSpawn2;
break;
default:
break;
}
Debug.Log("prefabToSpwan in SpawnPrefabServerRp() is " + prefabToSpawn.name);
// NetworkObject no = Instantiate(prefabToSpawn, pos, Quaternion.LookRotation(startDirection));
//no.Spawn();
}
public void setIndexValue(int buttonValue)
{
this.getal = buttonValue;
index.Value = buttonValue;
Debug.Log("Networkvariable index.value in setIndexValue -> index.value is " + index.Value); // Works OK
Debug.Log("Class variable getal in changeIndexValueServerRp -> getal is " + getal); // Works OK
changeIndexValueServerRpc(index.Value); // THIS DOES NOT WORK, FOR WHATEVER REASON? -> cannot call the ServerRpc *****
}
[ServerRpc]
private void changeIndexValueServerRpc(int localValue)
{
Debug.Log("Networkvariable index.value in changeIndexValueServerRp -> index.Value is " + index.Value); // Works OK
Debug.Log("Class variable getal in changeIndexValueServerRp -> getal is " + getal); // Works OK
getal = localValue;
index.Value = localValue;
}
} // END CLASS
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!


