I'm working on a 2D pixel art Unity game. I have multiple layers of scrolling so I need to use a perspective camera, the problem is though that it seems to mess up using particles as when the screen scrolls the particles move in perspective, when I need them to stay just in the x and y. Is there way to achieve this? I don't particularly want to go through every particle in real time and zero out their Z value, but maybe that's the only way?
There are three main approaches you can try:
1. Modify your particle emitter settings:
Ensure the particles are spawned at the same Z position. In Unity, this will be in the Shape section of the particle system inspector. For a sphere, hemisphere, or cone, set the radius to zero. For a box, set the Z extent to zero. If using a mesh as the emission surface, choose a flat mesh.
Ensure the particles do not stray from the Z plane they start in. In Unity you can do this with the "Limit Velocity over Lifetime" section. Check the "Separate Axis" box, and set the Z velocity limit to 0 and the space to World. Set the X and Y limits generously high (greater than or equal to your maximum speed) so that you don't slow the particles in the directions you want preserved. Watch out when using forces or collisions with the particles, as these might bump them out of plane.
2. Use a shader to flatten particles during rendering:
Write a custom vertex & fragment shader for your particles. Create a material using this shader and assign it in the Renderer section of the particle system inspector. In the vertex shader, set the z-coordinate of each vertex to some fixed value (either a constant or a shader parameter) before multiplying it by the projection matrix. (There are plenty of sources that explain how to write vertex shaders for Unity, so I won't clutter this answer with every step)
Note that, as far as I can tell, Unity pre-transforms particle vertices into camera space before submitting them to the GPU, so the z-value you use is relative to the camera. This may be a platform-specific batching behaviour, or dependent on quality settings, so be sure to test in your intended output format to double-check that it behaves as expected.
3. Render your particles (alone) with an orthographic camera.
Put your particles into their own layer. Set your main (perspective) camera to ignore this layer. Create a second camera, parented to your main camera. This one should render after the main camera, see only the particles layer, perform no clearing, and be set to Orthographic. Adjust its size so that the particles line up correctly. If your camera ever gets closer or further from the scene, you'll need to adjust the orthographic camera's size to match. (This will only work if all your particle sources sit in a single plane - otherwise the particles may be offset from their source when the source parallaxes and the particles don't)
Of these options, number 1 (emitter settings) is quickest to set up, and 2 (custom shader) is the most robust/flexible. I'd only recommend 3 (separate camera) if you need more flexible emission options than 1 allows, but aren't comfortable writing shaders (or are targeting a platform that lacks programmable vertex shaders)