I have a VFX graph of simple (prototype) projectiles shot out of a gun rendering simple particle Quad outputs.
I have one instance of VFX graph to handle the flight of all projectiles.
I have a collection of projectile positions that I periodically update with each FixedUpdate() by the CPU.
I don’t have any GameObjects representing projectiles, just data – position Vector3 structures and corresponding velocity Vector3 structures.
My first incarnation has the CPU updating the position structures and the VFX graph updating the particle positions with the same velocity vectors. But I want only one calculation by the CPU to update both the CPU projectile position structures and the GPU particle positions.
What is the best practice to updating the particle positions with the position structures updated by the CPU?
I looked at using Set Position in the VFX graph Update section, but i don’t see how to get the latest position information passed to the particle. And I don’t see how to match each position update with their corresponding particle.
I have been looking all day and haven’t found any clarity on this issue. Any help would be greatly appreciated.
Your particle simulation is running on CPU and the VFX is only displaying a bunch of particles, do I understand correctly?
In that case, I would recommend the usage of an exposed Graphics Buffer updated every frame, the VFX will use a Sample Buffer based on particleId attribute to retrieve updated position from the CPU. In that case, the Update Context is optional and the position fetching can be done in Output Context.
However, this approach only works for a reasonable amount of particles, doing a lot of upload of GPU data every frame isn’t generally recommended for real-time application.
Side note: if you want a fine control on your spawn event, you can also directly send data to the initialize context using direct link . It can be an alternative approach where your initial particle position and velocity on GPU are matching your CPU simulation, assuming your physic integration is equivalent, both particles on CPU and GPU should have the same behavior.
The ceiling for the number of concurrent rounds in flight would be 4k (all 80 players shooting a 50 round clip simultaneously in full auto mode). The typical would be around 50…100. Each position is represented in a Vector4 in their raw collection for 16 byte alignment already. Let me know what you think about these numbers even if only in the general sense.
I wouldn’t mind keeping two simultaneous simulations of the flight path, but I am not sure the VFX system could handle the following scenarios:
know when to stop a projectile upon impact of a target or hard surface
know when and to what values to alter the velocity (direction and speed) upon ricochet off a surface
know when to slow a projectile upon entering water (due to drag)
Where could I find a simple example (sample code?) of implementing the Graphics Buffer approach?
after struggling with this for a few days. I’d recommend looking into the sample project linked in this thread.
You can see what the script/vfx graph setup looks like. I just got a real basic setup working.
Actually I got a variant of the sample working already. The only thing that I see failing is that in a burst fire, say 8 rounds, I see all the rounds moving away from the gun as they should (slow velocity looks dope), and they all disappear after they reach the end of their life (say 2 secs), except the last one. I haven’t had a chance to look into why, but I suspect the VFX object itself stopped and didn’t finish destroying the last round. Not sure if that is even close, like I said I haven’t investigated it. But it is coming along fine at this point.
shout out to Qriva for the samples that were straight forward and the blog that talked about it some.
Ok, so I am back on this particular section of my game and I came across an issue and I think I know generally why it is happening, but I don’t know how to solve it. My solution is based upon the code Qriva offered for a sample to start with. In my solution, I can spawn particles to represent projectiles and position them in real time. That works. I can shoot, for example, 3 projectiles over 9 frames, thus 1 projectile every 3 frames. In the VFX graph I pass an array of positions with the first three elements for those three particles. The positions are in the form of Vector4, with the fourth member, w, counting down to 0 to denote end of life.
Once the three projectiles die, I then send another three. They take the Position array indices of 0, 1, and 2. But I think these don’t match to the newly spawned particles in the VFX. It seems that though the particles from the first burst of 3 projectiles should have destroyed, I think they still linger invisible and inactive. I think that the array indices no longer match to the particle id values.
There is a bigger picture to this problem. How would I ever be able to specify which particle has which id value? It seems to be implied for me, which is what I am struggling with I believe. If I cannot free up a particle with a specific id value, then I cannot reuse the array index matching it. But when it does free up, it seems that all the particles in the system automatically shift down to match those lower id values?!?
So I think I solved the issue I was having with not matching up the particle identifier with the indices in my array. I was using the particleId built in attribute, and I honestly believe it floats (changes) as the total number of particles changes. Instead, I used a custom event ID attribute. The challenge was finding a way to associate it with the update group, and by switching to Current, it works just fine.
Could you provide some clarification on why this method might not be recommended for real-time application? I’ve implemented several Visual Effect components that utilize a game object’s position and locality so I would assume these attributes are updated internally as the objects move around the scene. How would directly inheriting a game object’s attributes or letting the system use the locality of the object be any more performant than MrBigly’s implementation here?
I’m asking because I’m currently working on implementing VFX graph systems with my own particle controller to manage collision events and implement custom positional methods via script. Without graphics buffers, I had to create multiple instances of each system and bind them to each individual game object I had active. Essentially, I was pooling these systems, similar to what I would do when using the Shuriken particle system, and that was something I wanted to avoid.
Even if this isn’t the ideal performance solution, it addresses many of the issues I’ve been facing with the VFX graph. So, additional shoutouts to MrBigly and Qriva for the guidance and solution to this problem.
You can definitely use a VisualEffect as an helper to display a collection of bullet. In that scenario, I would recommend to upload your positions into a GraphicsBuffer and potentially use a system without any update.
My advice about performance was only relative to the amount of data sent from the CPU to the GPU every frame, it would probably be fine for thousand of particles but maybe not for millions of positions.