Create interactive grass with Unity is not too complicated, but there is not lots of information online about how to achieve this, and more important, nobody is explaining at all. In this Article, I will try to show you how to do interactive Grass shader in a simple way.

  • We’re going to use Shader graph and C#
  • We’re going to use URP, this is also Works HDRP or LWRP
  • You need basic knowledge about C# and shaders programming


First, we’re going to create the geometry and textures of our foliage, you can use any software you want for modeling like Maya, Blender, 3Ds Max, etc. But you have to be careful with the next thing:

You have to paint the mesh vertices, black vertices on the root of your foliage (this mean that the root is not going to move) and another color for the rest of your mesh (RGB or just White), these are the vertices that are going to move and interact with the player. Here we are just telling to our foliage what part is going to move and which none.

NOTE: It is pretty important that your 3D mesh have a FBX extension, OBJ files have no vertex Color information.



When you already have your foliage mesh, you have to import it to Unity and create a shader with Shader Graph.

We’re going to determinate the distance between the player and the grass, we need to know this to tell the grass to move only if the player is close enough. 

We’re going to add a variable, this will allow control the interaction radius between the player and the grass.

Let’s start getting the distance between our foliage and the player position, for this, we’re going to use the node POSITION in WORLD SPACE (This is going to determine the position of the grass vertices), and we’re going to create a VECTOR3 and turn it into a property called “trackerPosition”, it is really important that you call the reference of this VECTOR3 with a appropriate  name, we’re going to use that name reference later.

And finally, add a 'DISTANCE' node to get the distance between both objects.

Let’s proceed to divide the result by a float variable that you can call as you want, in my case I will call this “RADIUS”, and I will convert this into a property that I could manipulate from the inspector.

Saturate the result with a SATURATE node, Create a SUBTRACT node with a value of 1, we’re going to subtract the previous result, this will allow us to invert the value. 


Now we have to create a SUBTRACT node to subtract the foliage position from the player’s position,  and when we have this result, we’re going to multiply it by our previous result to obtain a unique value. 

We’re about to finish, create a “SPLIT” node to plug the result of our multiplication, this is going to split the result into RBGA or XYZW.

Create a ‘POSITION’ node in WORLD SPACE and we’re going to plug it to a ’SPLIT’ node too, now, let’s create 2 ‘ADD’ nodes and plug the corresponding vectors as the next picture shows:

This means that our vertices are going to receive a value that will add “force” in the X(R) vector of those vertices, of course, only when the player is close enough. The same thing is going to happen to the same vertices in the Z(B) vector, but in our Y(G) vector we’re going to keep those vertices in their original position.  This means that our grass is not becoming taller or shorter, this is only going to move in the X & Z position.

Finally, we are going to merge the result with a ‘COMBINE’ node:

Let’s create a ‘TRANSFORM’ node,  plug the previous result to this node. This will allow us to transform all the operations did it here from ‘World Space’ to ‘Object Space’ and let’s plug the result to the Output Position in the Vertex Shader.


With this we have finished in a way our shader, but we don’t know yet the player position, to know this, we have to write a quick C# script. This Script will find our player by its name and will send the position information to the shader, precisely to the VECTOR3 defined as “_trackerPosition”.

For this script to work, your object or player have to be called “tracker”, cause the code will find it by its name, and it’s really important that inside the shader your variable ‘trackerPosition’ is named in the reference  in the same way as in your C# code, without this, the script will not be able to find the variable to send the information of the player’s position.

Once you have the script, material and your player object called “tracker, you can assign that script to your foliage object and this will start to work, if you see that your grass is not moving enough, you could adjust the interaction radius in the material inspector of your grass object.

Remember to push the “Play” button for the script to work.

Our grass is already working! However, we have a last aesthetic problem, the root of our foliage is moving too when it should remain clinging to the ground.

Solve this is pretty simple, just add a “VERTEX COLOR” node and we’re going to ‘SPLIT’ it, this is going to get  the colors we defined to the vertices of the mesh foliage, where black (0 value) will not be affected by the movement or the player, and any other color will be affected to a greater extent as they approach the value 1 (or completely white).

Create a ‘LERP’ node and plug in the ‘A’ input the ‘POSITION’ node in ‘World Space’ , this means that we’re going to keep the original position of our vertices while this have a 0 value (or black), and in the ‘B’ input, plug the result of our node ‘COMBINE’, this will move the vertices as long as the LERP node receives values greater than 0. 


Done, we have finished our interactive grass shader, we can add wind movement eventually, but I will let that for another article.

Remember this is only a way to do it, you can try many other ways based on this example.


If you are interested in trying this shader you could download it for free in my Ko-fi account:

You are free to use them for any project you want when you got it

For any kind of doubt, just let me know in the comments or send me a direct message here. If you want to make a donation for the site you can do it in my Ko-fi account, this will help me a lot to continue creating content for you!