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);
}
}
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);
}