I sometimes hear people say that singletons are ■■■■ and you should not make stuff like that. I don’t realy know whats their problem, I love them and it clearly states their shall only be this one instance. There might be some problems, e.g. if you want to subclass the manager and exchange the singleton with that subclass can be a bit tricky/impossible.
What you definitly need to take care of is creating new objects. That is pretty expensive cause of all the registration stuff that is going on. Spawning every bullet anew, also means lots of garbage to be collected, which also consumes lots of ressources. What you definitely need is a Object Pool if you still want to use components/actors. You can create that on you own, or use this: Object Pool Plugin in Code Plugins - UE Marketplace (I gues that is what you ment by using a manager)
But yeah, you can also just keep an array or something with bullet information and use a InstancedStaticMeshComponent where you update the instances based on your array or use some custom render code similar to InstancedStaticMeshComponent. You definitely want to do that in C++. Looping over thousands of instance data in Blueprint will crush your performance.