Coder Social home page Coder Social logo

unity-job-system-mesh-deformer's Introduction

Unity Job System: Mesh Deformer.

Mesh deformation using the Unity Job System.


This project is a proof of concept application that deforms a mesh using the new Unity Job System and is made with Unity 2018.2.0f2. The Unity Job System is a way to write multithreaded code in the CPU providing high performance boost to the games using it. It is integrated with the Unity’s native job system which creates a thread per CPU core and manages small units of work named jobs. This design avoids the thread context switches that cause a waste of CPU resources.

To create a new job you need to implement one interface corresponding to the type of job you want to execute. There are several types of jobs, IJob, IJobParallelFor and IJobParallelForTransform are the most common. The basic one, IJob, allows you to execute the code in the secondary threads. It is also very common to want to execute the same operations on large collections of data, for this task you have the job IJobParallelFor (which is the one used in this example). The last one, IJobParallelForTransform, is another parallel job that is designed for operations using Transform components.

Another important thing to consider when writing high performance code is the memory layout of your data. Memory allocations are slow and to gain meaningful speed ups you have to control the lifecycle of your data, avoiding the garbage collector. A new set of native collections of blittable types are exposed to the managed side of Unity to achieve this.

The namespaces that are necessary to use the Job System and the native collections are the following ones:

using UnityEngine.Jobs;
using Unity.Collections;
using Unity.Jobs;

The job that performs the vertex displacement is an IJobParallelFor job and receives the following inputs:

  • deltaTime. Time in seconds it took to complete the last frame.
  • center. Center of the sphere.
  • radius. Radius of the sphere.
  • force. Force that is going to be applied to offset the vertices.
  • normals. The normal for each vertex to obtain the displacement direction (read only).
  • vertices. The vertex positions that are going to be updated.

It is also important to highlight that the delta time must be copied because the jobs are asynchronous and don't have the concept of frame. The operation that is executed is a vertex inside sphere check and a displacement across the normal with the given force.

public struct MeshDeformerJob : IJobParallelFor
{
    [ReadOnly] public float deltaTime;
    [ReadOnly] public Vector3 center;
    [ReadOnly] public float radius;
    [ReadOnly] public float force;
    [ReadOnly] public NativeArray<Vector3> normals;

    public NativeArray<Vector3> vertices;

    public void Execute( int index )
    {
        Vector3 vertex = vertices[index];

        float a = Mathf.Pow(vertex.x - center.x, 2);
        float b = Mathf.Pow(vertex.y - center.y, 2);
        float c = Mathf.Pow(vertex.z - center.z, 2);
        if( a + b + c < Mathf.Pow(radius, 2) )
        {
            vertex += normals[index] * force * deltaTime;
            vertices[index] = vertex;
        }
    }
}

The execution of this job is performed in the MeshDeformer.cs script after the helper class Pointer.cs calls it when the mouse button is pressed. The class declares 2 native arrays for the normals and vertices and a Mesh that will be shared by the MeshFilter and the MeshCollider.

public class MeshDeformer : MonoBehaviour
{
    private Mesh mesh;
    private MeshCollider meshCollider;

    private NativeArray<Vector3> vertices;
    private NativeArray<Vector3> normals;

    private bool scheduled = false;
    private MeshDeformerJob job;
    private JobHandle handle;

    private void Start()
    {
        mesh = gameObject.GetComponent<MeshFilter>().mesh;
        mesh.MarkDynamic();

        meshCollider = gameObject.GetComponent<MeshCollider>();
        meshCollider.sharedMesh = null;
        meshCollider.sharedMesh = mesh;

        vertices = new NativeArray<Vector3>(mesh.vertices, Allocator.Persistent);
        normals = new NativeArray<Vector3>(mesh.normals, Allocator.Persistent);
    }

    ...
}

Each time the method public void Deform( Vector3 point, float radius, float force ) is called, the job is scheduled for execution.

public void Deform( Vector3 point, float radius, float force )
{
    job = new MeshDeformerJob();
    job.deltaTime = Time.deltaTime;
    job.center = transform.InverseTransformPoint(point);
    job.radius = radius;
    job.force = force;
    job.vertices = vertices;
    job.normals = normals;

    handle = job.Schedule(vertices.Length, 64);
}

The job is completed in the LateUpdate, the vertices are copied from the job's native array to the mesh and the bounds are recalculated.

private void LateUpdate()
{
    handle.Complete();
    job.vertices.CopyTo(vertices);
    mesh.vertices = vertices.ToArray();
    mesh.RecalculateBounds();
}

Lastly, don't forget to free resources when the process is done, remember that the native collections are not managed.

private void OnDestroy()
{
    vertices.Dispose();
    normals.Dispose();
}

References.

Unity Manual: C# Job System
Unite Europe 2017 - C# job system & compiler
Unite Austin 2017 - Writing High Performance C# Scripts

unity-job-system-mesh-deformer's People

Contributors

adcimon avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.