Dynamic vegetation

In this example we are going to use Obi to make detailed vegetation that responds to collisions. We will make more emphasis in scene and asset organization than cloth setup itself.

Please note that using Obi is not the most performant approach when trying to make lots of dynamic vegetation -e.g. grass- mainly due to the lack of built-in level of detail (LOD) and the fact that one particle per vertex is probably too much granularity for the task. However it is a great choice for detailed interaction with a few plants or trees.

Unity Chan walking trough some dynamic plants.

The first thing we need to do is set up cloth simulation for just one plant. This is made exactly in the same way as we've seen in previous examples and as detailed in the cloth setup page of the manual.

Let's have a quick glance over the setup steps:

  • Create an ObiMeshTopology asset and feed it our vegetation mesh.
  • Add an ObiCloth component to our cloth object, which must also have a MeshRenderer.
  • Add an ObiSolver component to any object in the scene (be careful here, read further).
  • Feed both the solver and the topology asset to our ObiCloth, and initialize it.

However there's two caveats in this particular case:

First, the mesh you use needs to be one-sided. Most vegetation models you'll find out there are two-sided, which is a modelling trick to get rid of backface culling. However this increases the amount of polygons in your scene and will also give you a hard time editing Obi particles. It's recommended to use Obi's backface shader in this case.

Second, if you're going to have several dynamic plants in your scene and they are unlikely to be seen onscreen at the same time, you'll benefit from using a separate ObiSolver for each one, and ticking off their "Simulate when invisible" property. Obi can only cull entire solvers, so if you use the same solver for all simulations in your scene, as long as one of the simulations is seen by the camera all of them will be updated. This is a tremendous waste of resources, as your player will probably care very little about simulations he cannot actually see. It's best to group nearby plants under the same solver, so that their simulation ceases to be updated when they all go out of the camera frustum.



So, let's assume we have one plant already set up, and a separate GameObject with the ObiSolver component. We could just create a prefab out of it in the usual Unity fashion, however as we just discussed it could be useful to group several of them together under one ObiSolver. So take your plant object and parent it under the solver object. Then, duplicate the plant several times and place the duplicates nearby. Your object hierarchy shoud look like the following image (the ObiSolver component is added to the "WeedsGroup" object):



Now, we can make a prefab out of our solver + plants hierarchy, and instantiate it wherever we want. There's some detais about simulation parameters that might be worth noting, though:

1.- You´ll need to fix at least some particles of your plant. Particles near the floor are good candidates, as they will allow the rest of particles to stay anchored to the floor. In case of tree leaves or similar, particles near the branch are the ones you want to fix. If you do not fix any particles, your plant leaves will just fall off.



2.- Bend constraints are mandatory. If you don´t use them, your plant will look dead.

The plant on the left needs some watering...

3.- Reducing your solver's gravity is a good way to help bend constraints keep the leaves stiff without cranking up the number of bending iterations. For the plants used in this example, it was set to -3 instead of the usual -9.81.

At this point plants can be instantiated anywhere and they will simulate just nice. However there's something missing: we haven´t set up any collisions! So when our character walks trough them they won´t react at all. Check out the Collisions section of the manual for detailed info on how to do this. The basic steps are:

  • Add an ObiColliderGroup component to any object and feed it to your solver(s).
  • Include any colliders you want to interact with the cloth in the ObiColliderGroup.
  • Remember to put the colliders and the cloth in separate layers.