Search Unity

Question Rotation of a whole sprite based on distance from player

Discussion in 'Shader Graph' started by Ranyo, Mar 25, 2024.

  1. Ranyo

    Ranyo

    Joined:
    Jul 20, 2018
    Posts:
    2
    Hello,
    I'm trying to make my 2D grass rotate based on distance from the player. I've accomplished this already with gameobjects using animators, but now i'm trying it out on a 2D tilemap (set to individual). I've developed a shader that will do this when applied to the whole scene.

    swayingGrass.gif

    However when I try to apply this affect based on distance to the player it only affects the parts of the sprite within the distance to player. For example, approaching from above the sprite only the top of the grass will be affected, and if i approach from below only the roots will be affected. From my basic understanding of shaders I sort of understand why this happens, but i do not know if this is fixable.

    upload_2024-3-25_16-22-18.png
    If i plug that floating subtract node into the Rotate node it will do the same as the grass gif.

    The end result effect is something similar to a fish-eye lens. The intended effect is an entire object rotation based on how far the player is from the object.

    Also, anyone know how i can get my "rotation power" nodes to output as more of a gaussian curve rather than a sharp peak at 0?
    -Thanks!
     
    Last edited: Mar 25, 2024
  2. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,315
    Usually noise or sine is used to sway the grass.
    By fish eye you probably mean that grass sways in circle from mid, this is probably caused by distance calucation. You are using pixel position (Position node, space: object) to calculate distance, while what you want is grass object position, so it's constant for the whole mesh.
    Not 100% sure what you mean here, gif would help.

    There are various videos about grass, for example this one is about 3D grass animated with vertex position, but the general idea is the same for 2D and if you want to use UV distortion it will be also similar.
     
  3. Ranyo

    Ranyo

    Joined:
    Jul 20, 2018
    Posts:
    2
    Thank you Qriva for the response and video. However what i'm looking for isn't a noise map applied to the whole field of grass, but instead a displacement over a smaller area. If you look at a individual object of grass (2nd gif below) you'll be able to see that my grass object is rotating at the base of the grass. However, with my current shader it doesn't apply the rotation to the whole object but instead what is located within the distance calculation sphere.
    swayingGrass2.gif
    Here is a gif of the grass being affected by the player character in the current state. As you can see from it there is a fish eye distortion around the player. I'm trying to get the distortion around the player to affect the whole model of a grass object rather than only what is located inside the distortion.

    After reading your comment I tried replacing the position node with an object node, however it didn't work. From testing it out it seems the object node is using the tilemap object as the object position rather than the grass tile object's position.

    swayingGrass3.gif
    Here is another gif of what i'm trying to accomplish. I want the whole grass object to sway away from the player (the cursor in this gif).
     
    Last edited: Mar 26, 2024
  4. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,315
    You are right, but you can't sway single grass if you don't know it's pivot. That means either you need to disable batching them into single mesh what is not efficient and probably not possible for tilemap, or somehow provide the information about offset, the point you want to use per grass.

    To be honest I don't have much experience with tilemap and I don't know how it encodes data. If tilemap is single mesh then Position: object space should return position relative to it's origin, but somehow you use it to calculate distance per grass tile, so I assume you use that player offset property to shift the player position by grass origin, however I have no clue how or if position of single grass can be retrieved.

    In any case you need to be able to retrive one single position for whole grass sprite, so the sway is the same for the whole sprite.