Create mesh prefab from decal

To create a proper mesh prefab out of a decal instance, copy the script below to one of your Editor folders (e.g. Assets/Scripts/Editor). To create e prefab, just select your decal in the scene view and press Assets/Create Decal Mesh Prefab from the main menu.
 

using UnityEditor;
using UnityEngine;

public class WizardCreateLight
{
    [MenuItem("Assets/Create Decal Mesh Prefab")]
    static void CreateWizard()
    {
        GameObject o = Selection.activeGameObject;

        MeshFilter filter = o.GetComponent();

        if (filter != null)
        {
            if (filter.sharedMesh != null)
            {
                AssetDatabase.CreateAsset(filter.sharedMesh, AssetDatabase.GenerateUniqueAssetPath("Assets/decal_mesh.asset"));
                AssetDatabase.SaveAssets();
            }
        }
    }
}

 

 

 

 

 

Using an external pooling system

Since version 1.5.9 Easy Decal has the ability to inject a custom instantiating method to delegate the instantiating to an external pooling system.

The following example is using the PoolManager from Path-o-logical Games. But you could of course roll your own or use any other pooling system, as they all are similar in terms of functionality and API.

Somewhere in your code (e.g. in your game manager) register your custom instantiation method like this:

public void Awake()
{
    EasyDecal.Instantiation = PoolInstantiation;
}
 
private static EasyDecal PoolInstantiation(GameObject decalPrefab, GameObject parent, Vector3 position, Quaternion rotation)
{
    EasyDecal clone = PoolManager.Pools[PoolName].Spawn(decalPrefab, position, rotation).GetComponent<EasyDecal>();
    clone.Reset(true);// Version >= 1.6.0
    clone.Reset();// Version < 1.6.0

    return clone;
}

 

On your decal prefab add the following script to recycle the game object after it has been faded out:

using ch.sycoforge.Decal;
using UnityEngine;
 
[RequireComponent(typeof(EasyDecal))]
public class DecalPooling : MonoBehaviour
{
    //-------------------------------
    // Static Fields
    //-------------------------------
    public static string PoolName = "Decals";
 
    //-------------------------------
    // Fields
    //-------------------------------
    private Vector3 prefabScale;
    private EasyDecal decal;
 
    //-------------------------------
    // Methods
    //-------------------------------
    public void Awake()
    {
        decal = GetComponent<EasyDecal>();
        decal.OnFadedOut += decal_OnFadedOut;
 
        //Cache prefab scale
        prefabScale = gameObject.transform.localScale;
    }
 
    private void decal_OnFadedOut(EasyDecal obj)
    {
        // Set parent to scene root
        obj.gameObject.transform.parent = null;
 
        //Reset to prefab scale for the case that your pooling system doesn't take care about scale inheritance
        obj.gameObject.transform.localScale = prefabScale;
 
        PoolManager.Pools[PoolName].Despawn(obj.transform);
    }
}

 

 

Projection Targets

Plane Projection

Easy Decal Plane Projection 

Plane projection targets must always have a collider as the projection is done using raycasts. It's also important that the collider completely envelops the target mesh.

Box Projection

Easy Decal Box Projection 

When using the Box Projection technique the targets can be categorized in to two classes: Static and non-static targets.

Static Mesh

A static mesh target needs either a perfect fitting BoxCollider or a MeshCollider to reconstruct the freezed/combined geometry at runtime. At design-time in the editor a static, colliderless target can receive decals without providing any collider, but the decal must be baked before entering the play mode.

If you need to include static meshes that have no collider component attached, you have to use a Mesh Proxy Collection (see manual). But you have to keep in mind that a large proxy collection can slow down your application/game due the linear search performed while seraching for possible targets. The Mesh Proxy Collection is suitable for example for small, static probs laying around in a room.

Non-Static Mesh

Non-static targets containing a collider can always receive decals. To allow colliderless targets to receive decals, the Colliders Only option has to be disabled in the Constraints tab.

Screen Space and Deferred

Decals rendered in screen space do not have any restrictions or special requirements for the recievers. The target geometry can have any degree of complexity because the performance is independent of the scene's geometry.

But in reality you will have to use some sort of colliders to detect collision points to precisely place bullet holes or damage maps.  

 

Create Custom Mesh Post-Processor

Mesh post-processor can be used to alter the geometry after the decal has been projected. This method can be used to change the vertex positions, UVs, etc.

 

using UnityEngine;
using ch.sycoforge.Decal.Projectors.Geometry;

public class CustomProcessor : IMeshProcessor 
{
    public void Process(IMesh mesh)
    {
        // Iterate over triangles
        for (int i = 0; i < mesh.TriangleIndices.Count - 3; i += 3)
        {
            int t1 = mesh.TriangleIndices[i];
            int t2 = mesh.TriangleIndices[i + 1];
            int t3 = mesh.TriangleIndices[i + 2];

            Vector3 a = mesh.Vertices[t1];
            Vector3 b = mesh.Vertices[t2];
            Vector3 c = mesh.Vertices[t3];

            Vector3 ab = b - a;
            Vector3 ac = c - a;

            // Make something with data
        
        }
    }
}

Each custom processor needs to implement the IMeshProcessor interface.

 

CustomProcessor processor = new CustomProcessor();
...
EasyDecal decal = EasyDecal.ProjectAt(DecalPrefab.gameObject, parent, position, averageNormal);
decal.MeshProcessors.Add(processor);

The custom processor can be hooked to the decal instance as shown in the snippet above.

 

 

Performance Considerations

Screen Space Decal

The screen space decal's performance is completely independent of the underlying geometry. The performance consumption stays the same for a 1k or 30k mesh target.

Plane Projector

The plane projector's performance is mainly affected by its Resolution (quality) property.

Plane projector resolution.

Note: As with all mesh-based decals, make sure to bake the decal once it has been placed. When spawned in code, use decal.LateBake() or the "Bake" toggle in the inspector UI when in design mode.

Box Projector

The box projector's performance is mainly affected by its world space size and the complexity of the target meshes.

Box projector world size.Note: As with all mesh-based decals, make sure to bake the decal once it has been placed. When spawned in code, use decal.LateBake() or the "Bake" toggle in the inspector UI when in design mode.

Design-Time Use

For decals placed at design-time, the performance mainly depends on the amount of different materials/atlases. As decals sharing a common atlas can be combined to mesh groups using the same draw call.

Runtime Use

It's always a hard task to estimate the runtime performance as it depends on many different things. But roughly said, it mainly depends on the following points:

  1. The world space size of the decal.
  2. The complexity of the receiving geometry (How many polygons have to be cut?)
  3. The collider setup (Does the projector have to recursively search for potential geometry?)
  4. The number of instantiations per timestep.
  5. The runtime mode. (Is the decal geometry static (e.g. bullet hole) or dynamic (e.g. drop shadow)?)
  6. The settings you use in the Easy Decal component. (See images below for some of the settings that may affect performance)


Easy Decal Constraints

 

Page 2 of 4

Copyright © 2020 by Sycoforge Technologies. All Rights Reserved.