• General Chat
  • Changing Particle System Properties via Script in Realtime

When I change the properties of a particles system (ie. root, material) they don't always seem to take. I've tried calling the particles Reset() method but that doesn't have any effect.

Is there something I'm missing?

Has anyone made a simple demo of a particle system being throttled up and down in output via GDScript that they wouldn't mind sharing? ;-)

I'm wondering, since particles are created in the GPU via a material, are they not changeable thereafter?

@marty said: I'm wondering, since particles are created in the GPU via a material, are they not changeable thereafter?

That is a good question. I know you can pass data to the GPU in real time (that is how new mesh data can be loaded in during run time) but given that Godot has it's own shader language, which I presume the particles use, I wonder if it is statically complied into OpenGL code or something right before run time...

Tomorrow, I'll see if I can get particle settings to change during run time and will let you know the results, as now I am curious :smile:

Thanks, TT. ;-) Here's a possible angle on it: I did some experimenting and it looks like every time you reset particle system properties (ie. amount, lifetime), the particle system is apparently reset. At least that's how it appears.

It's interesting, I can't find any demo anywhere that show how to set dynamically alter particle system emission values. Such a common practice and yet nothing out there.

To elaborate on my last post with a c ode example, the following code, placed in ready() will appear to work fine but placed in process() will not - due presumably to the continual reset of the particle system in the latter.

$particle_system.amount = thrust_factor
$tparticle_system.lifetime = thrust_factor

I did some experimenting with a Particles2D node, and it seems that only changing amount resets the particle system. I was able to change the lifetime, color, scale, and texture during run time without any resets or special code needed, all I did was change the property.

Here is the code I used:

extends Control

export (NodePath) var path_to_particles;
var particle_system;

var IMG_ONE = preload("res://spark_particle2.png");
var IMG_TWO = preload("res://fire_particle.png");
var current_image = "two";

func _ready():
	particle_system = get_node(path_to_particles);
	
	get_node("HSlider_Vel").value = particle_system.process_material.initial_velocity;
	get_node("HSlider_Scale").value = particle_system.process_material.scale;
	
	get_node("HSlider_Amount").value = particle_system.amount;
	get_node("HSlider_Lifetime").value = particle_system.lifetime;
	
	get_node("Button_IMG").connect("pressed", self, "change_texture");
	
	get_node("HSlider_Vel").connect("value_changed", self, "change_value", ["particle_velocity"]);
	get_node("HSlider_Scale").connect("value_changed", self, "change_value", ["particle_scale"]);
	get_node("HSlider_Amount").connect("value_changed", self, "change_value", ["particle_amount"]);
	get_node("HSlider_Lifetime").connect("value_changed", self, "change_value", ["particle_lifetime"]);


func _physics_process(delta):
	particle_system.process_material.color.h += 0.03 * delta;


func change_texture():
	if (current_image == "two"):
		particle_system.texture = IMG_ONE;
		current_image = "one";
	elif (current_image == "one"):
		particle_system.texture = IMG_TWO;
		current_image = "two";


func change_value(new_value, value_type):
	if (value_type == "particle_velocity"):
		particle_system.process_material.initial_velocity = new_value;
	elif (value_type == "particle_scale"):
		particle_system.process_material.scale = new_value;
	elif (value_type == "particle_amount"):
		particle_system.amount = new_value;
	elif (value_type == "particle_lifetime"):
		particle_system.lifetime = new_value;

Yeah, I played with it a bit and noticed the same thing: it seems limited to changing the particle count. Also, turning emitting on then off resets the particle system, but arguably, that's to be expected.

For what it's worth, I'm doing it in 3D but that shouldn't matter, in theory.

Still, strange to see this, eh? Do you think it's a bug?

@marty said: Yeah, I played with it a bit and noticed the same thing: It seems limited to changing the particle count. Also, turning emitting on then off resets the particle system, but arguably, that’s to be expected.

Good to know it is the same on your end. I did not try changing emitting, but it does not surprise me that it resets the particle system.

For what it’s worth, I’m doing it in 3D but that shouldn’t matter, in theory

Right after I posted I wondered if you were using 3D particles, and I meant to test with them, but time got away from me. Though as you said, theoretically it shouldn’t matter.

Still, strange to see this, eh? Do you think it’s a bug?

I dunno, good question. I didn’t play much with particles in other game engines I’ve used, so I don’t really have anything to compare it against. I can see how not being able to change the particle count seamlessly could cause some issues for certain effects, but as I said, I’m not sure if this is common among other game engines or not.

Regardless of whether it is a bug or not, the results were certainly not what I was expecting! I thought some of the changes wouldn’t be possible due to having to convert the particle data into OpenGL code, but I guess Godot handles it. Interesting stuff all around!