I have to draw lots of grass objects and small rock objects, but I need to do so efficiently and place them efficiently. I use HDRP and I cannot use terrain. I am not interested in purchasing anything, we would rather make our own 3D objects.
Please recommend a workflow involving built in Unity as much as possible. We are willing to code anything of course but need guidance as I do not want to do duplicate or redundant work that Unity is going to address shortly.
Not sure if unity is going to address mesh terrains in the near future, but i wouldn’t think so. In this case, even though you want to use built-in unity as much as possible and you probably already know about Vegetation Studio, the Pro version seems to be what you’re after. It works with mesh terrains, is quite fast and support from the developer is really good , i can recommend it.
Hippo, we are currently having the same issues and looking for a similar solution!
Here is what we are doing currently, its not perfect but it does the job:
First we use polybrush to scatter the assets. Its a bit difficult to actually scatter as many as we do as tightly as we need so you will need to fiddle with brush settings a lot.
Next we create 2 scripts, one which is a component to put on every one of those assets (I am assuming you have already prefabbed the object so can non-destructively edit all the placed objects, otherwise you want to do this step first before scattering otherwise youll be adding components to 1000s of objects!). We will call the first one “DetailObjectInstance” and the other script “DetailObjectScanner” or something like that. The scanner script we put in editor folder.
Okay so now the actual work: we basically want to use the detail object scanner script to read every object in scene at edit time that has the DetailObjectInstance component, and add all their data (that is, data relevant to rendering) in a list. We save this in a scriptable object, called “DetailObjectInstanceBindings”. Basically for each object it should have the transform details, mesh, material etc.
Now delete out all the objects in the scene, as we wont actually be using them.
Use the scriptable object that now contains all the placed object data, to render the objects using graphics.drawmeshindirectinstanced. You can pass it batches of up to 1023 (1024? - can never remember which) and it will be much faster than having them in the scene as you wont have gameobjects for each!
This workflow, while I like to think its reasonably clever solution and performant, is a pain in the *** compared to being able to just scatter details using the terrain tools, but it will be far more performant than having 1000s of GOs in the scene!
This is not a perfect solution as I said so any input on how to improve this would be appreciated!
EDIT: you can obviously set this up to be automatic at build time, so that you dont have to manually delete out the objects from the scene etc each time. You can just have it hook into the build process, use the scanner, delete the objects etc etc
EDIT 2: If anyone is wondering why go through all this, its bascially so you can place objects using a lovely scatter brush or some other mass placement magic, but still have the efficiency of not having them as GOs in the scene. The scripting + Scriptable object solution just helps to automate this a little so that you can use the fine tuned placements you did by hand using a brush or whatever else, in the build. It basically boils down to a really simple solution: save the placements and then pass them to the graphics.drawmeshindirectinstanced in batches, and enjoy nice performance. NOTE: I dont think this works / works well if you want to use GI however, which is what you probably want if your using HDRP. I dont really have a good solution around that, sorry.
Thanks Good! That’s along the lines of what I had planned sort of. I was wondering about the DMII compute shader required and culling stuff, I guess I could just use a culling group or something.