I would advise using neither for this particular case.
InvokeRepeating
takes a method name, which means it's using reflection at runtime to look up the method to call. That's work we don't need to do, since we can already point the compiler at the exact method we want.
Update
executes every frame, but for spawning we typically want to leave some time (or other condition) between spawns so things don't bunch-up. That means we're repeatedly calling the function just to do nothing until the right frame.
Neither of these is awful, but we can do better with coroutines. These let us set up recurring behaviours that execute only when we want them to, without any unnecessary string lookup complexity.
bool keepSpawning = true;
IEnumerator SpawnAtIntervals(float secondsBetweenSpawns)
{
// Repeat until keepSpawning == false or this GameObject is disabled/destroyed.
while(keepSpawning)
{
// Put this coroutine to sleep until the next spawn time.
yield return new WaitForSeconds(secondsBetweenSpawns);
// Now it's time to spawn again.
Spawn();
}
}
NowThen we can kick off the sapwningspawning with...
StartCoroutine(SpawnAtIntervals(3f)); // Or whatever delay we want.
And we can stop spawning by setting keepSpawning = false;
If you need more granular control (eg. the ability to switch between two spawning streams, etc.) this is possible too - you'll just need to include in your question more details about your use cases.