Scriptableobject delay for AoE skill which instantiates multiple objects;

Hello,
I’m making some SO skills , however I have a AoE one which I need to instantiate cannonballs in random circle over time. When they start there’s a cannon sound and then that high pitched falling sound followed by an explosion sfx/vfx on collision.
Like Gangplank’s ult in LoL if anyone plays, here’s an example ( Gangplank Champion Spotlight ( Old and new ) - YouTube )

The problem is exactly how do I cause a delay on the instantiate…

public override void (Trigger()
{
    for (int i = 1; i < iterations + 1; i++)
    {
        //Invoke("InstantiateCannonball", 0.5f * i);
    }
}

void InstantiateCannonball()
{
    GameObject cb = Instantiate(cannonball, new Vector3(
            caster.transform.position.x + Random.Range(-2f, 2f),
            caster.transform.position.y + 4,
            caster.transform.position.z + Random.Range(-2f, 2f)), Quaternion.identity) as GameObject;
}

I thought I might use Invoke, but it derives from Mono after all.
Now I had the idea of maybe starting a coroutine in the script that manages and calls the skills like so, haven’t tested it yet as I need to figure out which skill would need to be called. Any ideas anyone? Thanks.

IEnumerator CallRepeatedely(string function, float delay, float times)
{
    WaitForSeconds wfs = new WaitForSeconds(delay);
    for (int i = 0; i < times; i++)
    {
        Invoke(function, 0);
        yield return wfs;
    }
}

Hello, I figured a workaround for this one.

I set the cannonball as kinematic at first and the set the delay parameters.

In the skill SO

for (int i = 1; i < iterations + 1; i++)
        {
            CannonBall cb = Instantiate(cannonball, new Vector3(
                caster.transform.position.x + Random.Range(-2f, 2f),
                caster.transform.position.y + 4,
                caster.transform.position.z + Random.Range(-2f, 2f)), Quaternion.identity).GetComponent<CannonBall>();

            // Set up the cannonball;
            cb.Set(i/2, damage, cannonSFX, fallSFX, explosionSFX, explosionVFX);
            
            //   InstantiateCannonball(i / 2);
        }

Then in the cannonball monobehaviour:
The reason for the reaaaally long parameters is that I think putting everything on the cannonball would defeat the purpose of having a scriptable object skill, that way the special effect references are all in the SO and not in the prefab, which could be interchanged.
Speaking of which maybe I should add some code to detect whether the prefab has a Rigidbody and CannonBall script as well.

public void Set(float delay, float dmg, VariableVolumePitch cannonSfx, VariableVolumePitch fallSfx, VariableVolumePitch explosionSfx, GameObject explosionVfx)
    {
        damage = dmg;

        // Sound effects.
        cannonSFX = cannonSfx;
        fallSFX = fallSfx;
        explosionSFX = explosionSfx;

        // Visual effects.
        explosionVFX = explosionVfx;

        Invoke("Fire", delay);
    }

    public void Fire()
    {
        cannonSFX.Play(GetComponent<AudioSource>());
        Invoke("Fall", 1);
    }

    public void Fall()
    {
        fallSFX.Play(GetComponent<AudioSource>());
        GetComponent<Rigidbody>().isKinematic = false;
    }

    private void OnCollisionEnter(Collision collision)
    {
        (...)
    }