Home Unreal Engine

[UE4] ~ Interactable grass, how do I make it react to every PC and NPC?

triangle
Offline / Send Message
Steamy_Steve triangle
So.
I managed to make a material setup that makes grass displace away from the player's character, which is great, but now I have some doubts.

The game I'm working on will have some wild life, which is supposed to interact with foliage too.
But the displacement method I've implemented is directly fed only one actor's location, which is obviously the player's character.
With multiple actors moving around in the scene, each foliage material would need a number of streams, each one calculating the displacement related to one actor.
Impractical to say the least!!

How may I make grass displace for all actors (all the ones that are supposed to make grass displace, of course)?

I've read that using physics is not a good way, because it's too heavy on the CPU.
Also, nodes like SpeedtreeColorVariation dont work with non-static meshes.

One way could be making a local displacement hot-spots array that has the player character's position as its [0,0] and and a limited range.
The character would work as a radar, feeding its own position and the ones of the other characters as an array of values that the material could go through to generate its displacement.
Probably not feasible, though.

Then how? =p


The method I'm using systematically (by using a tick node) stores the character's position into a parameters collection, which then gets read by the foliage material and used to generate a spherical area of influence that pushes the grass away.
I guess feeding each actor's position into the same parameters collection could seem logical, but unless they're processed at different moments it would only make a real mess.
I would need the actors to store their location at deferred intervals so that they wouldnt override each other.
Anyway, I've read that using ticks is bad too, because, well, they basically generate an event at every engine cycle, so I'm not sure giving every actor a tick node would be a bright idea.

Again, maybe I'm overlooking something.... =p

Help. -.-'

Replies

  • Obscura
    Options
    Offline / Send Message
    Obscura grand marshal polycounter
    You could have a dynamic 1d texture storing the character locations relative to the player, and then loop through them so the interaction logic works on all of the characters. Why 1d texture and a loop? because you don't want to hand place the logic with nodes 500 times and because a 1d texture is an effective way to store a relatively small amount of coordinates and can be looked up for fairly cheap. The texture would be refreshed every frame to update the coordinates.
  • Steamy_Steve
    Options
    Offline / Send Message
    Steamy_Steve triangle
    Obscura said:

    You could have a dynamic 1d texture storing the character locations relative to the player, and then loop through them so the interaction logic works on all of the characters. Why 1d texture and a loop? because you don't want to hand place the logic with nodes 500 times and because a 1d texture is an effective way to store a relatively small amount of coordinates and can be looked up for fairly cheap. The texture would be refreshed every frame to update the coordinates.

    @Obscura ; Sounds promising, my mistake not reiterating that I'm a complete newb.... ^^'
    So...what's a "dynamic 1d texture"? (I know what a texture is, of course)
    And how do I setup the loop? A blueprint? What kind of instructions?

    Thank you. ^.^
  • Obscura
    Options
    Offline / Send Message
    Obscura grand marshal polycounter
    the 1d texture is a texture that has 1 pixel on one of the axes. So a texture with resolution of 700x1 for example. The dynamic 1d texture would be a render target that you would write on tick event in blueprints, assigning a color corresponding to a world coordinate to each pixel of the texture. The loop would be in the material, in a custom node, reading the coordinate values from the render target. I would imagine in your current implementation, you have a vector parameter to feed the player location into the material. In the extended material that handles all characters, would use the 1d texture to read all the character locations.
  • Steamy_Steve
    Options
    Offline / Send Message
    Steamy_Steve triangle
    Obscura said:

    the 1d texture is a texture that has 1 pixel on one of the axes. So a texture with resolution of 700x1 for example. The dynamic 1d texture would be a render target that you would write on tick event in blueprints, assigning a color corresponding to a world coordinate to each pixel of the texture. The loop would be in the material, in a custom node, reading the coordinate values from the render target. I would imagine in your current implementation, you have a vector parameter to feed the player location into the material. In the extended material that handles all characters, would use the 1d texture to read all the character locations.

    @Obscura
    I see....each RGB pixel of the 1d texture would retain the value of one NPC. Very clever.
    Now I just need to know how to make it dynamic so that I can, what, generate it directly in the engine....?
    I've seen the blueprint editor, I've used it to capture the PC's location, but I mostly copied from a tutorial, so I have absolutely no idea what nodes to use to make such a thing.
    Also, how do I get actors' locations and feed them into the texture? There must be a function that systematically scans for spawned actors and gets their locations.....or not? =0
  • Obscura
    Options
    Offline / Send Message
    Obscura grand marshal polycounter
    Mmmm. In that case, I think you should examine blueprints further first. I think this would be a bit too complex task for your first try. Anyways, the get actor location node gets the world space location of an actor.It would be highly recommended to track characters only near the player because of float precision in the texture, and also because you can't really see the foliage interaction on very far characters anyways. So then the blueprint would get all character actors, and see which one in close enough to the player. Then put the close enough character locations into an array of vectors. Then, there would be a material that draws into the render target (1d texture). It would take the vector array, normalize it into 0,1 or -1,1 range relative to the player, and draw the pixel colors into the render target one by one, next to each other. Since only close characters would be tracked, and the render target is very small, this shouldn't really cause too much bad to the performance. There is a blueprint node called draw material to render target. This would be used on each array element to actually draw it to the render target.
  • Steamy_Steve
    Options
    Offline / Send Message
    Steamy_Steve triangle
    Obscura said:

    Mmmm. In that case, I think you should examine blueprints further first. I think this would be a bit too complex task for your first try. Anyways, the get actor location node gets the world space location of an actor.It would be highly recommended to track characters only near the player because of float precision in the texture, and also because you can't really see the foliage interaction on very far characters anyways. So then the blueprint would get all character actors, and see which one in close enough to the player. Then put the close enough character locations into an array of vectors. Then, there would be a material that draws into the render target (1d texture). It would take the vector array, normalize it into 0,1 or -1,1 range relative to the player, and draw the pixel colors into the render target one by one, next to each other. Since only close characters would be tracked, and the render target is very small, this shouldn't really cause too much bad to the performance. There is a blueprint node called draw material to render target. This would be used on each array element to actually draw it to the render target.

    @Obscura ;
    And makes perfect sense, but how do I get actors' locations?
    I mean, there's a node that is called just "GetActorLocation" (I know, I used it), but unless the actor you wanna track is the blueprint itself, you need to feed in a node that supplies a target for the get function.
    How do you track all/only the actors you're intersted in?

    Nothing is too complicated, I wanna learn, this is gonna be my job or I'll die trying.
    Possibly literally.
  • Obscura
    Options
    Offline / Send Message
    Obscura grand marshal polycounter
    Lets assume that all the characters are extended from "character" class. Then you could do it like this :
    Get all actors of class (class is character) -> get actor location.

    This would get all actors that are the class of character and/or its children.

    If you have multiple classes, you could just do a for each loop, and feed an array of classes in.
  • Steamy_Steve
    Options
    Offline / Send Message
    Steamy_Steve triangle
    Obscura said:

    Lets assume that all the characters are extended from "character" class. Then you could do it like this :
    Get all actors of class (class is character) -> get actor location.

    This would get all actors that are the class of character and/or its children.

    If you have multiple classes, you could just do a for each loop, and feed an array of classes in.

    @Obscura
    Oky, I'll study this method and eventually ask about more specific things later.

    Thank you! ^0^
  • Obscura
    Options
    Offline / Send Message
    Obscura grand marshal polycounter
    Np. In a more advanced implementation, you could have a foliage interaction component which you could just add to any actor that you want to interact with the foliage. The component would automatically know the distance to the player, and it would automatically add or remove itself from the list of actors to draw. Check out actor components too. They can be use to make reusable behavior and they can work on any actor class. So this way you could make physics actors or any other actor interacting with the foliage.
  • Steamy_Steve
    Options
    Offline / Send Message
    Steamy_Steve triangle
    Obscura said:

    Np. In a more advanced implementation, you could have a foliage interaction component which you could just add to any actor that you want to interact with the foliage. The component would automatically know the distance to the player, and it would automatically add or remove itself from the list of actors to draw. Check out actor components too. They can be use to make reusable behavior and they can work on any actor class. So this way you could make physics actors or any other actor interacting with the foliage.

    Physics is not an option, for this thing. I've watched an extensive tutorial/test and it's clear that a number of physics actors above 20 already starts affecting performance.
    Knowing the distance from the player is not a problem.....actually could be a solution!! Each actor calculates its own XYZ distance from the player and feeds it into a struct.
    The player then reads the struct and....and here I'm lost, I have no idea how to make the material read a series of coordinates to generate as many displacements.... =p
    I know how to make it read a parameters collection, but I doubt a parameters collection can be used as a dynamic array.....or can it? =0
  • Obscura
    Options
    Offline / Send Message
    Obscura grand marshal polycounter
    No. Use a texture and a loop. Looping the pixels of a 1d texture would look like this in a custom node:

    Inputs of the custom node:
    Tex - Your texture
    XRes - Texture resolution

    The actual code:

    float StepSize = 1/XRes;

    for(int i; i<XRes; i++)
    {
    float3 RawValueFromTex = Texture2DSample(Tex,TexSampler, float2(StepSize * i, 0);

    //math with the current value from the lookup can go here
    }

    return something;


    The custom node with a texture is the only way to have dynamic amount of variables and operation in a material. Also, here is a basic tutorial about the custom material node:
    https://polycount.com/discussion/182687/the-custom-node-tutorial-basics#latest
  • Steamy_Steve
    Options
    Offline / Send Message
    Steamy_Steve triangle
    @Obscura ;
    We're lucky, I do know some C and C++. ^.^
    Now I "just" have to study UE4's specific data types and functions......damn! ^^'
  • Obscura
    Options
    Offline / Send Message
    Obscura grand marshal polycounter
    You don't need c++ for this. Check out the custom material node. It allows you to use hlsl code.
  • Steamy_Steve
    Options
    Offline / Send Message
    Steamy_Steve triangle
    Obscura said:

    You don't need c++ for this. Check out the custom material node. It allows you to use hlsl code.

    Which I dont know!! xD
    C++ would've been better. x)
    Anyway, knowing how code is basically structured should help nonetheless. ^^
Sign In or Register to comment.