Unlimited method arguments without GC

I am trying to make a function that can receive unlimited amount of arguments without crating GC.

I know that this can be done with the params keyword but it creates GC. Also understand that you can pass array to to the function but I want to know if it is possible to pass unlimited method arguments without creating GC and without creating array or list and passing it to the List.

This is the example with the param code:

void Update()
{
    GameObject player1 = GameObject.Find("Player1");
    GameObject player2 = GameObject.Find("Player2");

    GameObject enemy1 = GameObject.Find("Enemy1");
    GameObject enemy2 = GameObject.Find("Enemy2");
    GameObject enemy3 = GameObject.Find("Enemy3");

    Vector3 newPos = new Vector3(0, 0, 0);
    moveObjects(newPos, 3f, player1, player2, enemy1, enemy2, enemy3);
}

void moveObjects(Vector3 newPos, float duration, params GameObject[] objs)
{
    for (int i = 0; i < objs.Length; i++)
    {
        //StartCoroutine(moveToNewPos(objs[i].transform, newPos, duration));
    }
}

When executed even with the StartCoroutine function commented out, it allocates 80 bytes. At first, I thought this was happening because I used the foreach loop then I changed that to a for loop but it still creating GC then I realized that params GameObject[] is causing it. See the Profiler below fore more visual information on this:

enter image description here

So, how can I create a method that takes unlimited arguments without generating GC?

Please ignore the use of GameObject.Find function used in the Update function. That's just used for an example to get the reference of Objects I want during run-time. I have a script implemented to handle that but not related what's in this question.

Jon Skeet
people
quotationmark

If you use params and specify arguments in that way then yes, it will always create an array object.

If you want to avoid that, and if you don't need to worry about recursion or thread safety, you could keep a List<GameObject> around and use the same list multiple times. For example:

private readonly List<GameObject> objectListCache = new List<GameObject>();

private void Update()
{
    cachedObjectList.Clear();
    cachedObjectList.Add(GameObject.Find("Player1"));
    cachedObjectList.Add(GameObject.Find("Player2"));
    cachedObjectList.Add(GameObject.Find("Enemy1"));
    cachedObjectList.Add(GameObject.Find("Enemy2"));
    cachedObjectList.Add(GameObject.Find("Enemy3"));

    Vector3 newPos = new Vector3(0, 0, 0);
    moveObjects(newPos, 3f, cachedObjectList);
    cachedObjectList.Clear();
}

void MoveObjects(Vector3 newPos, float duration, List<GameObject> objs)
{
    foreach (GameObject obj in objs)
    {
        // ...
    }
}

When you clear the List<T> that will set all the elements of the internal buffer to null, but won't discard the buffer - so it can be used again for the next Update call without any allocation.

people

See more on this question at Stackoverflow