- Home /
Why Does Adding to My SyncListStruct Break SyncVar?
So I tried making a SyncListStruct that didn't work. So then I tried just doing SyncVar on the same Game Object and that didn't work. After checking each portion of code I found out why my SyncVar wasn't working and it turns out that it was because of the line that adds to my SyncStructList. Question is why?
Inside my RandomSpawnLocation method I have the line vPosList.Add(tempVpos); which seems to prevent SyncVar from working.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
public class PickUpSpawner : NetworkBehaviour {
public int spawnAmount;
public GameObject PickUpPrefab;
public Camera MainCam;
float posX, posY, posZ;
float randSide;
Vector3 randomPosition;
private GameObject ground;
public GameObject currentGO;
private Plane[] planes;
NetworkClient _client;
public List<GameObject> SpawnedList = new List<GameObject>();
[SyncVar (hook="TestChanged")]
private int test = 0;
[SyncVar]
private string syncName;
public struct vPos
{
public Vector3 vector;
public vPos(Vector3 v)
{
this.vector = v;
}
};
private vPos tempVpos;
public class vPosClass : SyncListStruct<vPos> { }
vPosClass vPosList = new vPosClass();
//SyncListStruct<vPos> vPosList = new SyncListStruct<vPos>();
public List<Vector3> SpawnPositions = new List<Vector3>();
void TestChanged(int testChange) {
test = testChange;
}
// Use this for initialization
void Start () {
planes = GeometryUtility.CalculateFrustumPlanes(MainCam);
ground = GameObject.FindGameObjectWithTag("Ground");
//This would be used to resgister a handlers (So when a certain type of msg is sent to call a spcific method
//NetworkServer.RegisterHandler(MsgType.SyncEvent, OnServerPopulateSpawnPoints);
if (isServer)
{
SpawnPickUpObject();
for (int i = 0; i < vPosList.Count - 1; i++)
{
SpawnPositions.Add(vPosList[i].vector);
}
Debug.Log("<color=red> Server Test </color> " + test);
}
else
{
for (int i = 0; i < vPosList.Count - 1; i++)
{
SpawnPositions.Add(vPosList[i].vector);
}
}
Debug.Log("SPAWN Count: " + vPosList.Count);
}
// Update is called once per frame
void Update () {
if (isServer)
{
test = 5;
}
else {
Debug.Log("<color=red> Client Test </color> " + test);
}
if (isServer)
{
syncName = "Setting Name on Server";
}
else
{
Debug.Log("<color=red> Client Updated? </color>" + syncName);
}
if (Vector3.Distance(MainCam.velocity, Vector3.zero) > 5.0f)
{
for (int i = 0; i < SpawnPositions.Count - 1; i++)
{
//if random position is ever in view, spawn object
//if (MainCam.WorldToViewportPoint(SpawnPositions[i]).x <= 1 && MainCam.WorldToViewportPoint(SpawnPositions[i]).x >= 0 && MainCam.WorldToViewportPoint(SpawnPositions[i]).y <= 1 && MainCam.WorldToViewportPoint(SpawnPositions[i]).y >= 0)
if (InfiniteCameraCanSeePoint(MainCam, SpawnPositions[i]))
{
//Debug.Log("Got 1");
currentGO = Instantiate(PickUpPrefab, SpawnPositions[i], Quaternion.identity) as GameObject;
currentGO.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
SpawnedList.Add(currentGO);
//Remove pos added as to not add there again
SpawnPositions.RemoveAt(i);
}
}
}
else {
for (int i = 0; i < SpawnedList.Count - 1; i++)
{
if (!InfiniteCameraCanSeePoint(MainCam, SpawnedList[i].transform.position)) {
Destroy(SpawnedList[i]);
//Add back the spawn we just destroyed, might set a timer on this to add after a certain period of time has passed, in which case a queue could be used of position to spawn?
SpawnPositions.Add(SpawnedList[i].transform.position);
SpawnedList.RemoveAt(i);
}
}
}
}
public bool InfiniteCameraCanSeePoint(Camera camera, Vector3 point)
{
Vector3 viewportPoint = camera.WorldToViewportPoint(point);
return (viewportPoint.z > 0 && (new Rect(0, 0, 1, 1)).Contains(viewportPoint));
}
public void SpawnPickUpObject() {
for (int i = 0; i < spawnAmount; i++) {
RandomSpawnLocation();
//currentGO = Instantiate(PickUpPrefab, randomPosition, Quaternion.identity) as GameObject;
//currentGO.transform.localScale = new Vector3(0.3f, 0.3f, 0.3f);
//SpawnedList.Add(currentGO);
//Debug.Log(randomPosition);
}
}
public void RandomSpawnLocation() {
//X might be pos or neg
randSide = Random.Range(0, 10);
if (randSide <= 5)
{
posX = Random.Range(1, ((ground.GetComponent<Renderer>().bounds.size.x / 2) - 1));
}
else
{
posX = Random.Range(((ground.GetComponent<Renderer>().bounds.size.x / 2)) * -1, -1);
}
//z might be pos or neg
randSide = Random.Range(0, 10);
if (randSide <= 5)
{
posZ = Random.Range(1, ((ground.GetComponent<Renderer>().bounds.size.z / 2) - 1));
}
else
{
posZ = Random.Range(((ground.GetComponent<Renderer>().bounds.size.z / 2)) * -1, -1);
}
posY = 0.5f;
randomPosition = new Vector3(posX, posY, posZ);
tempVpos = new vPos(randomPosition);
//Breaks syncVar
vPosList.Add(tempVpos);
//SpawnPositions.Add(randomPosition);
//transform.position = randomPosition;
}
}
edit i just realized that you already use a SyncListStruct. I somehow misread the question i guess ^^.
Well i "guess" that SyncListStruct only supports structs with primitive datatypes. Since Vector3 is also a struct that "might" cause problems.
I haven't yet looked at the implementation of the SyncListStruct class.
second edit
Well i'm still not 100% sure but it actually looks like the serialization weaver should be able to construct the needed write methods automatically, even for deeper nested structs. I don't think the SyncListStruct should cause any problems here.
However your specified hook method most likely will. As far as i know the method doesn't take any parameters. So specifying a name ("TestChanged") that requires a parameter will get you in trouble. Furthermore that method also sets the syncvar which won't work on all other machines since they don't have authority over that variable. You should remove the hook method completely. It's ment as notification on the clients so you know when the variable has changed. So in that callback you should only read the value, not write it.
So I tried changing it from a vector to an int just to see if that would make a difference but the outcome is the same.
EDIT:
I'd like to restate that I haven't gotten the SynListStuct to work given the code used above. Now I've commented out the Hook SyncVar and replaced it with just SyncVar and it still will not work.
However with the above change as with the orginal hook if I comment out the vPosList.Add(tempVpos); line the SyncVar again works.
Your answer
Follow this Question
Related Questions
SyncVar on objects in a list 1 Answer
show sync var on two text ui (unet - networking) 3 Answers
SyncList TO 3 Answers
I want to set play scene of network lobby manger through script 0 Answers
Unet assigning local player Authority to a gameObject. 1 Answer