Before reading and using this workflow, you should understand how the C# Job System works. Review that information, then continue.
Create a client job to handle your inputs from the network. As you only handle one client at a time, use IJob as your job type. You need to pass the driver and the connection to the job to handle updates within the
Execute method of the job.
The data inside the
ClientUpdateJob is copied. If you want to use the data after the job is completed, you need to have your data in a shared container, such as a NativeContainer.
You may want to update the
NetworkConnection and the
done variables inside your job as you may receive a disconnect message. Verify you can share the data between the job and the caller. In this case, use a NativeArray.
You can only use blittable types in a
NativeContainer. In this case, instead of a
bool you need to use a
byte, as its a blittable type.
Execute method, move over your code from the
Update method that you have already in place from ClientBehaviour.cs and you are done.
You need to change any call to
connection to refer to the first element inside your
NativeArray. The same goes for your
done variable, you need to call
done when you refer to the
done variable. See the following:
When you have a job, you need to verify that you can execute the job.
Complete changes to
- Add a JobHandle to track ongoing jobs
Start method looks pretty similar to before, the major update here is to verify you create your
OnDestroy method, dispose all
NativeArray objects. Add a
ClientJobHandle.Complete() call. This ensures your jobs complete before cleaning up and destroying the data they might be using.
Finally update your core game loop:
Before you start running your new frame, check that the last frame has completed. Instead of calling
m_Driver.ScheduleUpdate().Complete(), use the
JobHandle and call
To chain your job, start by creating a job struct:
To schedule the job, pass the
JobHandle dependency that was returned from the
m_Driver.ScheduleUpdate call in the
Schedule function of your
IJob. Start by invoking the
m_Driver.ScheduleUpdate without a call to
Complete, and pass the returning
JobHandle to your saved
Pass the returned
ClientJobHandle to your own job, returning a newly updated
You now have a JobifiedClientBehaviour that looks like this.
The server side is pretty similar to start with. You create the jobs you need and then you update the usage code.
Consider this: you know that the
NetworkDriver has a
ScheduleUpdate method that returns a
JobHandle. The job as you saw above populates the internal buffers of the
NetworkDriver and lets us call
PopEventForConnection method. What if you create a job that will fan out and run the processing code for all connected clients in parallel? If you look at the documentation for the C# Job System, you can see that there is a IJobParallelFor job type that can handle this scenario
Because you do not know how many requests you may receive or how many connections you may need to process at any one time, there is another
IJobPrarallelFor job type that you can use namely:
However, you cannot run all of your code in parallel.
In the client example above, you begin by cleaning up closed connections and accepting new ones, which cannot be done in parallel. You need to create a connection job.
Start by creating a
ServerUpdateConnectionJob job. Pass both the
connections to the connection job. Then you want your job to "Clean up connections" and "Accept new connections":
The code above should be almost identical to your old non-jobified code.
ServerUpdateConnectionsJob done, implement the
There are two major differences compared with the other
- You are using the
NetworkDriver.Concurrenttype, this allows you to call the
NetworkDriverfrom multiple threads, precisely what you need for the
- You are now passing a
NetworkConnectioninstead of a
IParallelForJobDeferdoes not accept any other
Unity.Collectionstype than a
NativeArray(more on this later).
The only difference between the old code and the jobified example is that you remove the top level
for loop that you had in your code:
for (int i = 0; i < m_Connections.Length; i++). This is removed because the
Execute function on this job will be called for each connection, and the
index to that a available connection will be passed in.
You can see this
index in use in the top level
You are using the
index that was passed into your
Execute method to iterate over all the
You now have two jobs:
- The first job is to update your connection status:
- Add new connections.
- Remove old or stale connections.
- The second job is to parse
NetworkEventon each connected client.
Access your MonoBehaviour and start updating the server.
The only change made in your variable declaration is adding a
JobHandle to keep track of your ongoing jobs.
You do not need to change your
Start method as it should look the same:
You need to remember to call
ServerJobHandle.Complete in your
OnDestroy method so you can properly clean up code:
Update method, call
Complete on the
JobHandle. This forces the jobs to complete before you start a new frame:
To chain the jobs, you want to follow this process:
Start by populating your
Then create your
ServerUpdateJob. Remember to use the
ToConcurrent call on your driver, to verify you are using a concurrent driver for the
The final step is to verify the
NativeArray is populated to the correct size. This
can be done using a
DeferredJobArray. When executed, it verifies the connections array is populated with the correct number of items that you have in your list. When runnning
ServerUpdateConnectionsJob first, this may change the size of the list.
Create your job chain and call
Scheduele as follows:
In the code above, you have:
- Scheduled the
JobHandlereturned as a dependency on the
- The final link in the chain is the
ServerUpdateJobthat needs to run after
ServerUpdateConnectionsJob. In this line of code, there is a trick to invoke the
NativeListis passed to the
Schedulemethod, which updates the count of connections before starting the job. It will fan out and run all
If you are having trouble with the
serverUpdateJob.Schedule(m_Connections, 1, ServerJobHandle); call, you may need to add
"com.unity.jobs": "0.0.7-preview.5" to your
manifest.json file, inside the /Packages folder.
You should now have a fully functional jobified server.
You can download all examples from here.