com.unity.netcode.gameobjects: Problem with Spawning at runtime and with NetworkedTransform

Hi,

I try to implement a jenga tower. So, I have introduced a JengaBlock prefab. I have added the Networked Object, the Tracked Object, the Networked Transform, and the Rigidbody component. I have also included this prefab in the Networked Prefabs of my Network Manager. Then I have created an empty object and named it Spawn Networked Objects. With the Spawn Networked Objects selected I added a new script and named it SpawnNetworkedObjects.cs. For convenience I’m attaching you the script so you can reproduce the buggy behavior I get.

using MLAPI;
using MLAPI.Data;
using MLAPI.MonoBehaviours.Core;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpawnNetworkedObjects : NetworkedBehaviour
{
    public GameObject JengaBlock;
    private GameObject[] JengaBlocks;
    const int height = 8;

    // This is equivalent to overriding OnStartServer()
    private void Start()
    {
        JengaBlocks = new GameObject[height * 3];
        NetworkingManager.singleton.OnServerStarted = makeJengaBlocks;
    }

    void makeJengaBlocks()
    {
        float xDistPercentage = 0.5f;
        float yDistPercentage = 0.4f;
        int i = 0;

        for (int y = 0; y < height; y++)
        {
            for (int x = -1; x <= 1; x++)
            {
                if ((y & 1) == 0)
                {
                    JengaBlocks[i] = Instantiate(JengaBlock, new Vector3(x * xDistPercentage, y * yDistPercentage, 0.0f), Quaternion.identity);
                    JengaBlocks[i].GetComponent<NetworkedObject>().Spawn();
                }
                else
                {
                    JengaBlocks[i] = Instantiate(JengaBlock, new Vector3(0.0f, y * yDistPercentage, x * xDistPercentage), Quaternion.Euler(0.0f, 90.0f, 0.0f));
                    JengaBlocks[i].GetComponent<NetworkedObject>().Spawn();
                }
                i++;
            }
        }
    }
}

There are two problems here:

  1. although the Jenga tower is properly constructed on the Host, this is not the case for the Client.

  2. When I interact with the Jenga blocks in one of the Clients, the blocks seem to not be synchronized between the Client and the Host.

How can I fix these issues? Is it something I’m doing so wrong here?

Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 87 (50 by maintainers)

Most upvoted comments

Cough NetworkedBehaviour.GetNetworkedObject(uint networkId)

I’m assuming the reason is that you are calling ChangeOwnership and RemoveOwnership on the client. That’s not allowed. I will add checks for that. Ownership takes time to take effect. It needs to be sent across. It’s not something you do in “realtime”.

Moreover, I don't get it why does MLAPI work well in syncing a single object that I move with my clients, but not with a more complicated construction like the Jenga tower. And it's quite weird that in the Jenga tower example, when I manipulate some blocks they are immediately updated correctly on the Server, but the updated positions seem to not be passed correctly on the client, and therefore I see some jittering behavior.

This is not the MLAPI’s job. The MLAPI is here to offer abstractions. To allow you to send messages for MonoBehaviours (NetworkedBehaviours), to allow spawning objects across instances etc. Syncing positions and doing logic, that’s what the game developer’s job is. The NetworkedTransform is a prototype component as stated in the Wiki. It’s designed with one purpose. To Sync position from Client to server, or Server to client. If you want more complicated behaviour, write it.

That’s the biggest problem about “Prototype components”. They are used as production. If they don’t fit your usecase, you have to write your own.

We write Singles because Unity uses singles for everything. Would be stupid to cast to a different datatype thats larger for transmission only to cast back on receive. It’s like sending a ushort as a ulong but casting back to ushort after reading.

I think receiving (getting) data like position should be thought of as an event. You don’t need to schedule that. You need to SEND the data M times per second. The prototype components in MLAPI probably give you a great idea how to do this.

Hi, I think part of the problem is that you should not be worried about naming the cube at all. Since you have the netid of the cube…just use that to get a reference to the object (NetworkedBehaviour.GetNetworkedObject(uint networkId) – thanks Albin) and stop trying to do Find at all. Find is a last resort, expensive, not something you should do on each frame, etc. You can keep a data structure filled with your cubes so they are easy to find, such as a dictionary. Pass NetID or whatever name you give it, get your cube back. I have a project where I assign an ID, which is not visible to the user, and a name, which is, via syncvar. Behind the scenes, presumably syncvar still has to use the netid to find the right object. I have my own ID simply because I use that ID for other systems and want a UID that is the same each time the game starts. So I have a dictionary with that ID as the key and the object it goes with as the value. Hope this helps!

huh? NetworkStart will be invoked once per behavior instance.

When client A selects a block, you send a command to the server requesting ownership of that object. When they are done moving it, you release ownership back to the server. Alternately, give the entire towers ownership to the current player if you are turn based.
I’d give you the API calls to do this, but don’t know them well enough yet and am on my phone.