Created
October 5, 2025 12:54
-
-
Save adammyhre/a232f6da67222d98ae8c72d0143a50e0 to your computer and use it in GitHub Desktop.
Decal Pooling in Unity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections; | |
| using UnityEngine; | |
| using UnityEngine.Pool; | |
| using UnityEngine.Rendering.Universal; | |
| public class BulletHoleSpawner : MonoBehaviour { | |
| #region Fields | |
| IObjectPool<DecalProjector> decalPool; | |
| [Tooltip("Material to use for the bullet hole decal.")] | |
| public Material decalMaterial; | |
| [Tooltip("Layers that can receive bullet hole decals.")] | |
| public LayerMask decalLayers = -1; | |
| [Tooltip("Size of each decal in world units (x = width, y = height, z = depth).")] | |
| public Vector3 decalSize = new Vector3(0.5f, 0.5f, 0.5f); | |
| [Tooltip("Duration in seconds for the decal to fade out before being returned to the pool.")] | |
| public float fadeDuration = 5f; | |
| Camera cam; | |
| #endregion | |
| void Start() { | |
| cam = Camera.main; | |
| decalPool = new ObjectPool<DecalProjector>( | |
| createFunc: () => { | |
| GameObject go = new GameObject("DecalProjector"); | |
| DecalProjector dp = go.AddComponent<DecalProjector>(); | |
| go.transform.parent = this.transform; | |
| dp.material = decalMaterial; | |
| dp.fadeFactor = 1f; | |
| dp.fadeScale = 0.95f; | |
| dp.startAngleFade = 0f; | |
| dp.endAngleFade = 30f; | |
| return dp; | |
| }, | |
| actionOnGet: dp => dp.gameObject.SetActive(true), | |
| actionOnRelease: dp => dp.gameObject.SetActive(false), | |
| actionOnDestroy: dp => Destroy(dp.gameObject), | |
| collectionCheck: false, | |
| defaultCapacity: 10, | |
| maxSize: 20 | |
| ); | |
| } | |
| void SpawnDecal(RaycastHit hit) { | |
| DecalProjector projector = decalPool.Get(); | |
| projector.transform.position = hit.point + hit.normal * 0.01f; | |
| Quaternion normalRotation = Quaternion.LookRotation(-hit.normal, Vector3.up); | |
| Quaternion randomRotation = Quaternion.Euler(0, 0, Random.Range(0f, 360f)); | |
| projector.transform.rotation = normalRotation * randomRotation; | |
| projector.size = decalSize; | |
| StartCoroutine(FadeAndRelease(projector, fadeDuration)); | |
| } | |
| void Update() { | |
| if (Input.GetMouseButtonDown(0)) { | |
| Ray ray = cam.ScreenPointToRay(Input.mousePosition); | |
| if (Physics.SphereCast(ray, decalSize.x * 0.3f, out RaycastHit hitInfo, Mathf.Infinity, decalLayers)) { | |
| SpawnDecal(hitInfo); | |
| } | |
| } | |
| } | |
| IEnumerator FadeAndRelease(DecalProjector projector, float duration) { | |
| float time = 0f; | |
| float initialFade = projector.fadeFactor; | |
| while (time < duration) { | |
| if (projector == null) yield break; | |
| time += Time.deltaTime; | |
| float t = time / duration; | |
| projector.fadeFactor = Mathf.Lerp(initialFade, 0f, t); | |
| yield return null; | |
| } | |
| if (projector != null) { | |
| projector.fadeFactor = initialFade; | |
| decalPool.Release(projector); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment