Hi, i have been working on a bullet-hell game for a bit. I, recently have been having a huge problem with frame drops when pooling bullets in my game. Each bullet is enabled with a rigidbody2d and a circle collider upon shooting a bullet, which results in around a 15 frame drop per bullet. When looking at the profiler, it says it is GC.Alloc does anyone know how I can prevent this? I provided a photo of the profiler, as well as the main bullet script I use.
using System.Collections;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float damage;
public bool rocketLanded;
public Vector3 direction;
public GameObject hitmarkerPrefab;
public GameObject bigShotDustExplosionPrefab;
public GameObject nanoBugPrefab;
public GameObject bulletContactObjectParticle;
public GameObject bulletContactEnemyParticle;
public GameObject bloodyPop;
public GameObject zodenExplodeParticles;
public GameObject palmOfZoden;
public bool PalmOfZodenActive;
private bool canCheckCollision = true;
private TrailRenderer trailRenderer;
private Player player;
private PlayerProjectiles playerProjectiles;
[SerializeField] private AudioClip[] fleshImpactSoundFX;
private void Awake()
{
player = FindObjectOfType<Player>();
playerProjectiles = FindObjectOfType<PlayerProjectiles>();
trailRenderer = GetComponent<TrailRenderer>();
}
private void OnEnable()
{
Ticker.OnTickAction += AllowCollisionCheck;
PalmOfZodenActive = false;
StartCoroutine(SetTrailRenderer());
}
private void OnDisable()
{
Ticker.OnTickAction -= AllowCollisionCheck;
}
private void AllowCollisionCheck()
{
canCheckCollision = true;
}
private IEnumerator SetTrailRenderer()
{
trailRenderer.time = 0;
yield return new WaitForSeconds(0.17f);
trailRenderer.time = 0.2f;
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (!canCheckCollision) return;
if (IsIgnoredTag(collision.tag))
{
Physics2D.IgnoreCollision(collision, GetComponent<Collider2D>());
return;
}
if (collision.CompareTag("Enemy"))
{
HandleEnemyCollision(collision);
}
else if (collision.CompareTag("Object"))
{
HandleObjectCollision();
}
}
private void HandleEnemyCollision(Collider2D collision)
{
if (player.playerHasInfestedCasings && Random.value >= 0.5f)
{
ObjectPoolManager.SpawnObject(nanoBugPrefab, transform.position, Quaternion.identity);
}
EnemyRecieveDamage enemyDamage = collision.GetComponent<EnemyRecieveDamage>();
if (player.playerHasMetamorphasis && Random.value >= 0.9f)
{
enemyDamage?.Metamorphasis();
}
if (player.playerHasGlassCasings)
{
enemyDamage?.GlassCasings();
}
if (player.playerHasPalmOfZoden && PalmOfZodenActive)
{
ObjectPoolManager.SpawnObject(palmOfZoden, collision.transform.position, Quaternion.identity);
}
if (player.playerHasSkullOfZoden && Random.Range(0, 4) <= player.playerLuck)
{
collision.GetComponent<StatusEffect>()?.InflictFleshRot();
}
if (player.playerHasBeefyBullets)
{
ApplyKnockback(collision);
}
enemyDamage?.DealDamage(damage);
PlayFleshImpactSound();
if (player.playerHasComboShot)
{
playerProjectiles.comboShot += 0.2f;
}
SpawnBulletImpactEffect(bulletContactEnemyParticle, bloodyPop);
HandleExplosionIfApplicable();
if (!player.playerHasFMJ)
{
ReturnBulletToPool();
}
}
private void HandleObjectCollision()
{
SpawnBulletImpactEffect(bulletContactObjectParticle, null);
HandleExplosionIfApplicable();
if (player.playerHasComboShot)
{
playerProjectiles.comboShot = 0f;
}
ReturnBulletToPool();
}
private void ApplyKnockback(Collider2D collision)
{
Rigidbody2D rb = collision.GetComponent<Rigidbody2D>();
if (rb != null)
{
Vector2 knockbackDirection = -(collision.transform.position - transform.position).normalized;
rb.AddForce(knockbackDirection * 10f, ForceMode2D.Impulse);
}
}
private void SpawnBulletImpactEffect(GameObject particlePrefab, GameObject secondaryEffect)
{
if (particlePrefab != null)
{
Rigidbody2D rb = GetComponent<Rigidbody2D>();
if (rb != null)
{
Vector3 bulletDirection = rb.velocity.normalized;
Vector3 spawnPosition = transform.position + bulletDirection * 0.2f;
float angle = Mathf.Atan2(bulletDirection.y, bulletDirection.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.Euler(0, 0, angle);
ObjectPoolManager.SpawnObject(particlePrefab, spawnPosition, rotation);
if (secondaryEffect != null)
{
ObjectPoolManager.SpawnObject(secondaryEffect, spawnPosition, rotation);
}
}
}
}
private void PlayFleshImpactSound()
{
SoundFXManager.instance.PlayRandomSoundFXClip(fleshImpactSoundFX, transform, 1f);
}
public void ReturnBulletToPool()
{
ObjectPoolManager.ReturnObjectToPool(gameObject);
}
public void HandleExplosionIfApplicable()
{
if (player.playerHasRocketLauncher || player.playerHasCombustionCanister || player.playerHasPredatorMissle || player.playerHasSkullOfZoden)
{
ObjectPoolManager.SpawnObject(bigShotDustExplosionPrefab, transform.position, Quaternion.identity);
if (player.playerHasSkullOfZoden)
{
ObjectPoolManager.SpawnObject(zodenExplodeParticles, transform.position, Quaternion.identity);
}
RaycastHit2D[] hits = Physics2D.CircleCastAll(transform.position, playerProjectiles.explosionRadius, Vector2.zero);
foreach (RaycastHit2D hit in hits)
{
if (hit.collider.CompareTag("Enemy"))
{
hit.collider.GetComponent<EnemyRecieveDamage>()?.DealDamage(playerProjectiles.damage / 2);
}
else if (hit.collider.CompareTag("Player") && !player.playerHasPHD)
{
hit.collider.GetComponent<PlayerReceiveDamage>()?.DealDamage(1);
}
}
}
}
private bool IsIgnoredTag(string tag)
{
return tag == "Player" || tag == "Familiar" || tag == "Deflector" || tag == "Water" || tag == "Ground" ||
tag == "Fish" || tag == "Boat" || tag == "FishWater" || tag == "Blood" || tag == "PlayerProjectile";
}
}
![FrameDrop|690x367](upload://qfZ31PE6g1bju2brdnkQ842bd6P.jpeg)