Now, 100,000 birds means 100,000 skeletal meshes right?
No! We can use an old-school trick called vertex animation.
It’s now easier than ever to make smart particles that interact with your environment.
Mesh and Material Setup
I started with a simple bird skeletal-mesh from the marketplace, which I converted into a static mesh and baked all its animations into a single vertex animation texture.
I am feeding in the animation frame from the emitter using a Dynamic Parameter.
https://lh6.googleusercontent.com/M7GVF4qYApLLjsiFNAzgGH-7v-FsitQfuaEN_nF-mh_ossrZfXjBdYkAhBumnnRa1WZQZjf06daySF6xpsd-OOfnyk5IlzRbHuEBWsf0G8OHDMX6V0x8FxWmafP2ueqL2JP5Cg01
Emitter Module Setup (Niagara)
We need to create a custom module that consists of the following:
- A set of conditions for when to play each animation
- If statement that specifies the Animation StartFrame, EndFrame and State (or Animation_ID)
- (Optional) FinishCurrentAnimation before switching to the next Function
- Play Animation Function
https://lh6.googleusercontent.com/Z3fCgLjB9-2vj1xLIYJkhgRussjFL_GR-KrwX5K6eSbIOAivilv8WMRgiQt–D3_KL9OdUerHI2Sb3zlGMLpM5HBgGyeopcfu1zUuMrB348RDRE1Mz-gUNDkFbGZtGat5cefS0g-
If-statements and Conditions
If-statements define the animation Start and End Frame.
In this case, it picks between flying or gliding based on the up velocity sign.
The animation info is then sent to FinishCurrentAnimation (optional), then PlayAnimation.
https://lh5.googleusercontent.com/eYUxTMNjjqlaQ-MV0JXb7OItzbgHEgWaR1f6hJOSnAM74fRPGAtprTNTVXWxw32s4Ri6oxZNklFxR7Mnoa_Gpf4_48b88jZ9BokL2gv91BuZyBYcGsFiIaWhuz-Dx9qvgHfrb6Hr
FinishCurrentAnimation Function
This Function Stores the Current State Properties and ignores all new states until the current one is complete.
I am outputting the same output twice as a reminder that you need to store the value, as functions don’t have persistent variables.
https://lh4.googleusercontent.com/aiWS2bu6lhpY2RFJ6E4_uYYREhY1RUjFWhYKKh8lQewnNmr3VOtuA-TTQiTR5tRUjQgprrmetlBvroC9741aR7TAcf6MoJ1v0QkW_5QA9B5sID-Psf_h_hw4I2tGP-TAzHmjj93n
PlayAnimation Function
AnimationFrame = StartFrame + ElapsedFrames + (AnimationSpeed*DeltaTime) * FrameRate.
If the current animation’s EndFrame is reached, it will loop back to the StartFrame.
If the animation changes, it will reset to the new animation StartFrame.
The InitialState check is used to prevent resetting the ElapsedAnimationFrames. Useful if you want to randomize animations offsets, you can do so during the initial state.
https://lh5.googleusercontent.com/tmI3eTj2xOaVANqd5fgagnxDZHwHn-fDqTBFbUQMcpLeKsw48vfFemvpbXzys8sQVrdFyqZ7EQIw83LRC1kdxzcc_XOquYGAvJHGBdHzSQwAJef0G08Q-Nz2qcPK7CL3UxeDHHdE
The Particle System Setup (Niagara)
This part controls the bird movement. In this case, I am setting the velocity via a curve.
The Animation module we just created then decides which animation to play.
A debug Module changes the particle color based on the animation state.
https://lh6.googleusercontent.com/qQb-pxdPl8E7HlxpvV_Ulr15DR3Hbv9d8dyCXNUOasTWfsjlo8cwHotoiPyki1FEODHVfR-HJvijLICatWWTHs32VKqpBN00aLxHZZnxCxzSAYxoKg4hmYCgCIeJaNs6oM4YeWEd
Putting it all Together
This bird particle is switching between different animations based on velocity and position.
If you try to make a bird that does it all, you can end up with something large like this:
https://lh3.googleusercontent.com/Pu43HkszOBQJQPbwBAe0bpdqgrRjMM2WdWjomK2N0X4vZgG_hVty7desIljQnFDGt3bbdGLQgNFp7nAmnlXu56pEnicULcwynFZDdshr_AlBm-TwH-tnZkoa9uLQNH1yigGMOW2r
Best to create a custom module for each system with its own set of conditions.
This sums up how to setup Animated Particles to simulate large flocks in Unreal.
Below are a few systems that demonstrate different bird logics
Birds that Land on Tree
Birds are spawned in a grid, their orientation and their animation start-time are randomized.
The destination points are sampled from a StaticMesh tree, where the top surface of branches is filtered using MaterialID.
Lerp between the two positions.
Birds that Land on Tree (Breakdown)
Since we are controlling the movement with a lerp and knowing each animation duration, there is no need to guess when the bird is going to land.
We can map each animation’s start to the lerp position.
https://lh5.googleusercontent.com/7Z4mW098xOBAAl1Y6Zw-tlg34oSS1Kw9aLXKoh025cg0QoXjYNwnn5KS9fWjxqey8-d0ZEfeMcZDr9U8QyVIXYyG4eaCmRiPY7KENMG9S0ZyVe-xukdoo7w6Y06-wq4m1sBu5x5X
https://lh3.googleusercontent.com/y7iBA4p-zXeMs6V6tgBLLcRgW1VRJipvZwIueYYrCDSesI4FvjiKPE20G6yLlFd3jIe3dlpP712iu-g-A55wZcUf08UYoRWubDrE9KkhQLUgF3a7uoIL8_4oapJmCSIgZU4wT_Ua
A Flock of Birds
Vortex Velocity Module is used with a randomized axis to make the birds fly inside a sphere.
The animation module is selecting Fly Up or Fly Down based on the velocity z-direction.
With a simple effect like this, I managed to have 100k birds on screen.
https://lh3.googleusercontent.com/6Uk0c3D_KY0jGDzuu6p4dKI7EF4ymi716UPcN1kshBF-zk6nOIEuX9EuEnNJNitMuQmChCW5BQSWUIhwskjGw6Pbp9YK7yy6q81RErTNPeou1HgXmihidl33g2vN4FDbM1n-jWjy
https://lh6.googleusercontent.com/UofDPM450RkfjA-YAvsiMBAuLx4Uw7SgrbCGpdhExSDnvJn2XFGDje2Ma14O4b6i10lSr0zE8JGokF2XqHUyLFd4HYnq_BYGofC3GIaHM2y05znhKqZKi7ef1tKwX2Hu_Bd7Uijw
https://lh6.googleusercontent.com/ZvtUBZqRWf29ST3QX0aEwJs4ghhTm50P4AgQPn4qbZb2n1EMp70wP9B8aFsYo08zCe47vmC6Bhf5bAYvGj8gyAwElnnLw9AdlXKHTLILAI8rrUZxNPldC1JiYFGgmhe-Iu8DeYxA
Make sure to follow my on Twitter @JosephRAzzam](https://twitter.com/JosephRAzzam) for more #UETip](https://twitter.com/search?q=%23UETip), and check back in two weeks where I plan to cover how to add player interaction.