Networking runtime mesh demolishing
Saturday, May 22, 2021 | Update at Saturday, Jun 5, 2021

RayFire is a plugin for Unity which allows for demolishing or slicing 3D objects in runtime or in the editor. In this prototype I experiment with trying to simulate it consistently over the network using DarkRift Networking 2

How it works

Breaking Rocks

Each rock has a Node script. This script handles all the requests and breaking on the server. When a client looks and hits the rock it will send a message to the server where it hit the rock and for how much damage. The server then validates this and sends the result back to every client including the person who requested the hit.

The RayFire Shatter script has its seed set to one and centre bias up to one hundred percent. The reason why the hit position is sent as well is so that the rocks all do not break in the same way, and, the seed is set to one so that the cracks all form the same way. All of this makes it possible for the rocks to break the same in everyone’s client.

public void RequestHit(float damage, Vector3 hitPosition)
{
    if (!_breakAble)
    {
        Debug.Log("This rock is not breakable");
        return;
    }

    if (NetworkManager.IsServer)
    {
        ServerHit(damage, hitPosition);
        return;
    }

    using (DarkRiftWriter writer = DarkRiftWriter.Create())
    {
        writer.Write(UID);
        writer.Write(damage);
        writer.Write(hitPosition.x);
        writer.Write(hitPosition.y);
        writer.Write(hitPosition.z);
        NetworkManager.SendMessage(NetworkTags.HitNodeRequest, writer, SendMode.Reliable);
    }
}

Link to code in Gitlab

Players Joining Mid Session

As these are procedurally generated meshes, I needed a way to catch people up if they joined late. The method I used for this was by sending the meshes vertices, triangles, normals and UV over the network. Then on the client, they could use this information to rebuild the mesh instead of simulating lots of rock breaking to get caught up.

This override called InitilizeData was from a custom derived class I made. The NetworkManager calls this on the NetworkedBehaviour when it wants to get the state of the object to send to a new client. In the if statement you can see I get the Mesh Filter and write the mesh to the writer.

public override void InitilizeData(out Message message, out DarkRiftWriter writer)
{
    writer = DarkRiftWriter.Create();

    writer.Write(Prefab.name);
    writer.Write(UID);
    writer.Write(transform.position);
    writer.Write(transform.rotation.eulerAngles);

    writer.Write(_health);
    writer.Write(transform.lossyScale);

    writer.Write(_meshBroken);
    if (_meshBroken)
    {
        MeshFilter meshFilter = GetComponent<MeshFilter>();
        Mesh mesh = meshFilter.mesh;
        writer.WriteMesh(mesh);
    }

    writer.Write(_breakAble);

    message = Message.Create((ushort)NetworkTags.SpawnPrefab, writer);
}

Link to code in Gitlab

Links