Tutorial: Niagara Data Channels Intro

An introduction to Niagara Data Channels. A new feature that allows communication between Game code and Niagara Systems.

DISCLAIMER: Niagara Data Channels are still experimental and all of the below is subject to change.

https://dev.epicgames.com/community/learning/tutorials/RJbm/unreal-engine-niagara-data-channels-intro

4 Likes

Š²Ń‹ ŠæутŠ°ŠµŃ‚Šµ рŠµŠŗŠ»Š°Š¼Ńƒ сŠµŠ±Ń с Š¾Š±ŃƒŃ‡ŠµŠ½ŠøŠµŠ¼ , тут Š½ŠµŃ‚Ńƒ Š¾Š±ŃƒŃ‡Š°ŃŽŃ‰ŠµŠ³Š¾ Š¼Š°Ń‚ŠµŃ€ŠøŠ°Š»Š°

Hi,
I followed the tutorial, but nothing gets spawned when using NDC.
The positions and spawning are ok if I donā€™t use NDC, but if I look at the niagara debugger, I see 0 system spawned using the NDC.

My NDC Asset:

Blueprint logic:

Niagara:
(content of the modules are same as yours, but I only set the position)


What am I missing?
Thanks!

Started to work out of nowhere without me changing anything.

Okay, but we should be able to read other systems data? Right? I tried to have two systems, reader and writer.

This is my reader in system update, it also have a ā€œget NDC scratchpad in emitter updateā€ which is just saving NDC as a emitter value.

then in my second system - writer, Iā€™m trying to use Data Channel writer to save my position.


but itā€™s end up with comilation Failded and no informations why :confused:

There is a lot of crashes but I understand thatā€™s experimental :smiley: I just want to know if my leaves can read the fire position :smiley:

Thank you for this tutorial, it saved my life!!

Yeah, Im having the same issue, cant compile the Niagara System when there is a NiagaraDataChannelWriter on ParticleUpdate :frowning:

Hello STovey,

thx a lot for the tutorial, this should increase performance a lot.
Iā€™d like to write via c++. How would I create the same NDC you created as blueprint inside c++?
I assume I have to derive from the ā€œUNiagaraDataChannelAssetā€.
Iā€™m not very familiar with the Scratch Module and I also heared about Niagara Data Interfaces. Whatā€™s the difference between Niagara Data Interface and Data Channels, apparently I canā€™t use the Spawn Conditional, is there anything else more substantially different?

My goal is to pass position and vectors from c++ to my Niagara System, and Iā€™d like to make use of the conditional spawn inside the scratch module so I donā€™t have to spawn individual systems.

would be nice if I could get some guide lines here, Iā€™m still fairly new to Unreal. Only being playing around with the engine for 1.5 years, and just started to port logic from blueprint to c++.
if I want to use NiagaraSystems especially, Iā€™ve stuck with just making use of the user.paramaters.
But via your tutorial I learned more about the scratch module and that itā€™s possible to use a more efficient approach of handling multiple impact effects via a single system.

so this is my ultimate goal. Using only one Niagara System and passing data via c++ the most efficient way.

I would be thankful for any tips and advice. (Iā€™m using 5.4)

I really donā€™t feel very comfortable to make use of this new feature via c++.
Would this be the correct way to make use of it?

inside header:

	/* DataChannel to pass data to Niagara */
	UPROPERTY(EditAnywhere, Category = "Data Channel")
	TObjectPtr<UNiagaraDataChannelAsset> NDC_Impact;

inside c++:

							UNiagaraDataChannelWriter* ChannelWriter = UNiagaraDataChannelLibrary::WriteToNiagaraDataChannel(GetWorld(), NDC_Impact.Get(), SearchParameters, 1, true, true, true, ACharacterBaseCPP::StaticClass()->GetName());

							if (!ChannelWriter)
							{
								UE_LOG(LogTemp, Warning, TEXT("data channel writer is invalid"));
							}
							else
							{
								ChannelWriter->WritePosition(TEXT("Position"), 0, Impact.ImpactPoint);
								ChannelWriter->WriteVector(TEXT("Normal"), 0, Impact.ImpactNormal);
							}

would UNiagaraDataChannelWriter* ChannelWriter cause memory leaks, if I donā€™t delete the ChannelWriter afterwards somehow, Is there another way to write to DataChannels directly. I assume this function might only be used inside blueprints and is not meant to be used inside c++.
I might just not make use of this feature right now if I donā€™t know what Iā€™m dealing with.

I tried creating the writer and storing a pointer in actor field but it gets nulled right away so doesnā€™t look like itā€™s gonna be leaking.

Anyone know if there is any way to make this work with ribbons? I have an arrow that uses Niagara to spawn a smoke trail behind it using a ribbon. I am working on a tower defense game and there will be up to 100 arrows active at a time.

In the first screenshot I have the system working with a ribbon, everything is working as expected. In the second picture I have 2 archers shooting at the same time and the ribbons end up merging into 1, because the ribbon is rendered based on particle lifetime. There is only an option to change the ribbon if its ā€œfront to backā€, or ā€œback to frontā€, but there is no other option (see third screenshot).



Ok I found a different way to do this for spawning smoke behind arrows using Niagara Data Channels. Instead of using ribbons, I spawn a mesh.

  1. Make a cylinder, I made it with 5 sides to have as little triangles as possible, a cylinder with 5 sides uses 20 triangles and still has volume, you may also be able to get away with only 3-4 sides. You can always rotate and change the scale later, then bake the transform/rotation.
  2. I spawned a mesh instead of a sprite/ribbon, and rotated it facing in the direction of the vector by grabbing it from the projectile movement component. My arrows follow a curve so I need to rotate each mesh individually on spawn, if your arrow goes in a straight line then you could probably save a little bit of performance there since the rotation will always be the same. The rotation is also set on the initialize step and not in the rotation solver that updates every tick, this saves performance.
  3. I spawn the mesh at 48 fps, I just enable tick on the arrow actor and set the actor tick rate to 0.02083s (which is 1/48). When the arrow hits something, disable the actor tick.
  4. Scale the mesh down over its lifetime to make it look nicer. No opacity needed. Do not scale down the long side, only the 2 short sides.
  5. You can play around with the values, you could spawn them more often and scale the mesh to a smaller size, this would spawn more meshes however and may affect performance. So far with my values the performance has been great.
  6. Could probably play around with it a little bit more and save on performance, but if I dont see it in the profiler anymore, theres no reason to optimize it more. In that case you could probably make the meshes a little bit smaller and spawn them more often to give the smoke a smoother feel.

My video file size was too large to upload on the forum, so put it in an unlisted youtube format instead: https://www.youtube.com/watch?v=lqW4wUrPj0s

Edit: Tried by scaling down opacity instead of mesh scale and it looks a lot better, but havent tested the performance difference. Also the meshes overlap each other and it looks weird at certain times with the opacity. Youd have to take your input velocity vector, get the vector length, and scale your mesh length based on that X a number, gotta play around with it. It looks pretty good at a long distance, but up close you can see its separate meshes.