ParticleSystem.ColliderData.GetCollider(int particleIndesx, int colliderIndex) returns null.

I would like to find out why it returns null and more importantly how I get to the collider of the object I hit.

My setup:

(Attached to the shooting particle system)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Gamekit3D;
using System;
using System.Linq;

[RequireComponent(typeof(ParticleSystem))]
public class DamagingParticleTriggerListener : MonoBehaviour
{
    [SerializeProperty("DamageAmount")] float damageAmount;
    public float DamageAmount { get; internal set; } = 1;
    public Damageable owner;
    private ParticleSystem myParticleSystem;
    private List<ParticleCollisionEvent> collisionEvents;
    protected VList<Damageable> hittables;

    void Start()
    {
        myParticleSystem = GetComponent<ParticleSystem>();
        collisionEvents = new List<ParticleCollisionEvent>();
        hittables = FindObjectsOfType<Damageable>().ToVList();
        hittables -= hittables.Where((damageable) =>
        {
            if (damageable == null) Debug.LogWarning(String.Format("'{0}' found an object in the {4} Script with a {1} owned by '{2}' that is null. Que???", name, nameof(Damageable), damageable.name, typeof(DamagingParticleTriggerListener)));
            else
            {
                if (owner == null) Debug.LogWarning(String.Format("'{0}' found in the {1} Script that {2} is null. Que???", name, nameof(DamagingParticleTriggerListener), nameof(owner)));
                else return damageable.team == owner.team;
            }
            return false;
        });

        ParticleSystem.TriggerModule particleSysTrigger = myParticleSystem.trigger;

        foreach (Component component in hittables) particleSysTrigger.AddCollider(component);
    }

    void OnParticleTrigger()
    {
        // Get all of the systems particles entering one of the given triggers this frame
        List<ParticleSystem.Particle> particlesTriggeredEntered = new List<ParticleSystem.Particle>();
        int numEntered = myParticleSystem.GetTriggerParticles(ParticleSystemTriggerEventType.Enter, particlesTriggeredEntered, out ParticleSystem.ColliderData insideData);

        // Iterate over these particles, send a damage message to all hit triggers and destroy the particle by setting its remaining lifetime to 0
        for (int particleIndex = 0; particleIndex < numEntered; particleIndex++)
        {
            for (int colliderIndex = 0; colliderIndex < insideData.GetColliderCount(particleIndex); colliderIndex++)
            {
                Component collider = insideData.GetCollider(particleIndex, colliderIndex);
                if (collider != null) SendDamageMessage(collider.gameObject);
                else Debug.LogWarning(string.Format("'{0}' hit something that doesn't exist.", name));

                ParticleSystem.Particle particle = particlesTriggeredEntered[particleIndex];
                particle.remainingLifetime = 0;
            }
        }

        // Push the remainingLifetime = 0 particles into the system, replacing the old particles.
        myParticleSystem.SetTriggerParticles(ParticleSystemTriggerEventType.Enter, particlesTriggeredEntered);
    }
    void SendDamageMessage(GameObject other)
    {
        if (!other.TryGetComponent(out Damageable theHurtOne))
        {
            return;
        }

        Damageable.HealthInteractionMessage message = new Damageable.HealthInteractionMessage()
        {
            difference = -DamageAmount,
            damager = this,
            direction = Vector3.up,
            stopCamera = false,
            AppliesToTeamsX = (Damageable.Teams)(!(owner is null) ? owner.team != 0 ? 4/*~(owner.team)*/ : 0 : 0)
        };

        theHurtOne.ApplyHealthInteraction(message);
    }
}

Note: VList is a custom defined List wrapper, inheriting from List and overloading all bitwise operators, “-=” in this case amounts to

public static VList<T> operator -(VList<T> a, IEnumerable<T> b)
    {
        return new VList<T>(a.Where((x) => !b.Contains(x)));
    }

Results while Debugging:
When I shoot someone of my team, the particle passes through the target. Yay!
When I slow down the particles and walk through them, nothing happens. Yay!

When I shoot someone of the opposing team it triggers the “hit something that doesn’t exist.”-warning, I set for when ParticleSystem.ColliderData.GetCollider(int particleIndesx, int colliderIndex) returns null. :frowning:
The particle moves through the opposing player. :frowning:
Nay…

No other Logs are in the Debug Log.

Thanks to everyone helping!

Hmm this is interesting… if we are saying you have interacted with a collider, it seems to me that it must be a bug if we then give you a null collider.

Are you able to submit a bug report?

Did so through the link below your reply: Case 1356510

1 Like

What do you think, would be a workaround?