Atlas Creation

From Sprites

Let Unity assemble the single images for you into a sprite. You can then use the sprite converter to convert the sprite to an atlas.

1. Create a new atlas object by right-clicking within the project view "Create > Easy Decal > Texture Atlas"

2. Select the atlas object and assign a material with at least the base color texture assigned.

3. Click on the "From Sprites" button.

4. Assign all sprites by dragging them to the sprites slot.

 

 


 

 

 

 

Decals in Prefabs

Decals can be placed within prefabs when they either are soft-baked using "Bake on Awake" or hard baked using the "Save as Asset" option as found in the "Extras" tab. The normal "Bake" option is only available within the scene because the mesh can be serialized in the scene root.

Create a prefab and mesh asset from a decal

  1. Place decal within your scene and bring it to its final shape.
  2. Navigate to the "extras" tab on the decal inspector.
  3. Enable the "Instantiate after save" option.

 

The decal is now hard-baked into a regular mesh and referenced by the prefab.

Note: This does not work in Prefab Stage mode because of Unity limitation.

 


 

 

 

 

 

Switch to the source version

When switching to the source code version of Easy Decal the shared libraries must be kept as they are shared between the Sycoforge plugins.

What to replace

Replace the following DLLs with their respective source version:

  1. "Assets\Sycoforge\Easy Decal\Scripts"
  2. "Assets\Sycoforge\Easy Decal\Scripts\Editor"

You may want to create an Assembly Definition file for them and call it "EasyDecal.Runtime" and "EasyDecal.Editor" to get better compile times. Don't forget to add a runtime reference to the editor assembly.

What to keep

Everything in the "Assets/Sycoforge/Shared" folder.

 

 


 

 

 

 

 

Access the Source Code

The source code is by default not included. However, we provided it on demand.

  1. Send us an email or DM on Discord containing your invoice number.
  2. We send you back an access voucher code
  3. Add Easy Decal to the shopping cart on the webshop
  4. Do a checkout and apply the voucher code. Don't forget to verify that the total is $0.00
  5. You can then download all additional content (including the source) from your account.

 

 


 

 

 

 

Combine Decals at Runtime

Sometimes it's necessary to combine decals at runtime to a shared mesh to save draw calls. 

The method below makes use of Unity's built-in combine functionality to get the job done. Note that if the keepMaterials argument is set to true and the decals use different materials you may not be able to reduce draw calls.

    /// <summary>
    /// Combines decals to one mesh at runtime.
    /// </summary>
    /// <param name="decals">The decals to combine.</param>
    /// <param name="meshRenderer">The target mesh renderer</param>
    /// <param name="meshFilter">The target mesh filter</param>
    /// <param name="keepMaterials">When set to <c>false</c> the first material gets used, otherwise all materials get preserved. 
    /// Note that preserving all materials may result in more drawcalls</param>
    public static void Combine(IList<EasyDecal> decals, MeshRenderer meshRenderer, MeshFilter meshFilter, bool keepMaterials)
    {
        if (decals.Count == 0) { Debug.LogError("No decals to combine."); return; }

        List<MeshFilter> meshFilters = new List<MeshFilter>();
        List<Material> materials = new List<Material>();

        foreach (EasyDecal decal in decals)
        {
            meshFilters.Add(decal.MeshFilter);
            materials.Add(decal.DecalMaterial);
        }

        CombineInstance[] combineInstances = new CombineInstance[meshFilters.Count];

        for (int i = 0; i < meshFilters.Count; i++)
        {
            combineInstances[i].mesh = meshFilters[i].sharedMesh;

            // Transform from model to world space
            combineInstances[i].transform = meshFilters[i].transform.localToWorldMatrix;
        }

        meshFilter.mesh = new Mesh();

        if (keepMaterials)
        {
            meshFilter.mesh.CombineMeshes(combineInstances, false);

            meshRenderer.materials = materials.ToArray();
        }
        else
        {       
            meshFilter.mesh.CombineMeshes(combineInstances, true);

            meshRenderer.material = decals[0].DecalMaterial;
        }
    }

The Combine() method above can be used as the following:

 

using ch.sycoforge.Decal;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class RuntimeCombine : MonoBehaviour
{
    //------------------------------------
    // Exposed Fields
    //------------------------------------
    public EasyDecal[] Decals;

    //------------------------------------
    // Private Fields
    //------------------------------------
    private MeshRenderer meshRenderer;
    private MeshFilter meshFilter;

    //------------------------------------
    // Unity Methods
    //------------------------------------
    private void Start()
    {
        meshRenderer = GetComponent<MeshRenderer>();
        meshFilter = GetComponent<MeshFilter>();
    }

    private void Update()
    {
        // Combine when pressing Enter/Return
        if(Input.GetKeyUp(KeyCode.Return))
        {
            Combine(Decals, meshRenderer, meshFilter, false);
        }
    }

    private void OnDestroy()
    {
        // Cleanup runtime instance
        Destroy(meshFilter.mesh);
    }

}

While the method above will work for decals placed in the scene root (no parent GameObject). The method will fail if the decals are parented to a transformed GameObject. To account this fact one could rewrite the method to reflect the parent's world transformation.

/// <summary>
/// Combines decals to one mesh at runtime and creates a new <c>GameObject</c> as container.
/// </summary>
/// <param name="decals">The decals to combine.</param>
/// <param name="parent">The parent <c>GameObject</c> of the decals.</param>
/// <param name="keepMaterials">When set to <c>false</c> the first material gets used, otherwise all materials get preserved. 
/// Note that preserving all materials may result in more drawcalls</param>
/// <param name="deleteOriginals">When set to <c>true</c> the original decals get deleted. 
public static GameObject CombineToChild(IList<EasyDecal> decals, GameObject parent, bool keepMaterials, bool deleteOriginals)
{
    if (decals.Count == 0) { Debug.LogError("No decals to combine."); return null; }

    GameObject container = new GameObject("[Decal Container]");

    MeshRenderer meshRenderer = container.AddComponent<MeshRenderer>();
    MeshFilter meshFilter = container.AddComponent<MeshFilter>();


    List<MeshFilter> meshFilters = new List<MeshFilter>();
    List<Material> materials = new List<Material>();


    foreach (EasyDecal decal in decals)
    {
        meshFilters.Add(decal.MeshFilter);
        materials.Add(decal.DecalMaterial);
    }

    CombineInstance[] combineInstances = new CombineInstance[meshFilters.Count];

    for (int i = 0; i < meshFilters.Count; i++)
    {
        combineInstances[i].mesh = meshFilters[i].sharedMesh;

        Transform decalTransform = meshFilters[i].transform;

        // Create local-to-world transformation matrix
        Matrix4x4 localDecalTransform = decalTransform.localToWorldMatrix;

        // Transform from model to world space
        combineInstances[i].transform = localDecalTransform;
    }

    // Create new mesh
    meshFilter.mesh = new Mesh();
    meshFilter.mesh.name = "Combined Decals";

    if (keepMaterials)
    {
        meshFilter.mesh.CombineMeshes(combineInstances, false, true);

        meshRenderer.materials = materials.ToArray();
    }
    else
    {
        meshFilter.mesh.CombineMeshes(combineInstances, true, true);

        meshRenderer.material = decals[0].DecalMaterial;
    }

    container.transform.parent = parent.transform;

    if(deleteOriginals)
    {
        foreach(EasyDecal decal in decals)
        {
            Destroy(decal.gameObject);
        }
    }

    return container;
}
 

 

 

Page 3 of 4

Copyright © 2020 by Sycoforge Technologies. All Rights Reserved.