Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to spawn particles once right after entity spawn | starts_immediately doesn't work #420

Open
Nigless opened this issue Jan 28, 2025 · 6 comments

Comments

@Nigless
Copy link

Nigless commented Jan 28, 2025

Trying to make explosion by spawning explosion entity with effect, but starts_immediately doesnt work, and nothing happens.

// on_add component hook
fn explode(mut world: DeferredWorld<'_>, entity: Entity, _: ComponentId) {
    let assets = match world.get_resource::<ExplosionAssets>() {
        Some(assets) => assets.clone(),
        None => {
            let mut effects = world.get_resource_mut::<Assets<EffectAsset>>().unwrap();

            let assets = ExplosionAssets {
                explosion: effects.add(create_effect()),
            };

            world.commands().insert_resource(assets.clone());
            assets
        }
    };

    world
        .commands()
        .entity(entity)
        .insert(ParticleEffectBundle {
            effect: ParticleEffect::new(assets.explosion),
            ..default()
        });
}
@Nigless Nigless changed the title How to spawn particles once right after entity spawn How to spawn particles once right after entity spawn | starts_immediately doesn't work Jan 29, 2025
@kim-fg
Copy link

kim-fg commented Jan 29, 2025

@Nigless Ignoring the very unhelpful AI comment, there's a similar issue (#319) that regards this problem for Spawner::once and Spawner::burst. Which spawner type are you using?

@Nigless
Copy link
Author

Nigless commented Jan 29, 2025

I've tried using Spawner::once, but it doesn't work. Now I'm using Spawner::new to see the effects.

@kim-fg
Copy link

kim-fg commented Jan 29, 2025

What are your settings using Spawner::new? Sharing the code would be helpful for the issue I linked.
And did you manage to get it working as you wanted?

@Nigless
Copy link
Author

Nigless commented Jan 29, 2025

It works, but i need to spawn particles only once.

fn create_effect() -> EffectAsset {
    let mut gradient = Gradient::new();
    gradient.add_key(0.0, Vec4::new(0., 0., 0., 1.));
    gradient.add_key(0.5, Vec4::new(0., 0., 0., 1.));
    gradient.add_key(1.0, Vec4::splat(0.));

    let mut size_gradient = Gradient::new();
    size_gradient.add_key(0.0, Vec3::ZERO);
    size_gradient.add_key(0.01, Vec3::splat(2.0));
    size_gradient.add_key(1.0, Vec3::splat(4.0));

    let writer = ExprWriter::new();

    let init_vel = SetVelocitySphereModifier {
        center: writer.lit(Vec3::ZERO).expr(),
        speed: writer.lit(4.).expr(),
    };

    let init_pos = SetPositionSphereModifier {
        center: writer.lit(Vec3::ZERO).expr(),
        radius: writer.lit(0.01).expr(),
        dimension: ShapeDimension::Volume,
    };

    let init_lifetime = SetAttributeModifier::new(Attribute::LIFETIME, writer.lit(5.0).expr());

    let rotation_attr = writer.attr(Attribute::F32_0).expr();

    let rotation = (writer.rand(ScalarType::Float) * writer.lit(std::f32::consts::TAU)).expr();
    let init_rotation = SetAttributeModifier::new(Attribute::F32_0, rotation);

    let drag = writer.lit(3.).expr();
    let update_drag = LinearDragModifier::new(drag);

    let accel = writer.lit(Vec3::Y * 0.2).expr();
    let update_accel = AccelModifier::new(accel);

    let texture_slot = writer.lit(0u32).expr();

    let mut module = writer.finish();

    module.add_texture_slot("color");

    EffectAsset::new(
        32,
        Spawner::new(32.0.into(), 0.0.into(), 6.0.into()),
        module,
    )
    .with_name("explosion")
    .init(init_pos)
    .init(init_vel)
    .init(init_lifetime)
    .init(init_rotation)
    .update(update_drag)
    .update(update_accel)
    .render(OrientModifier {
        mode: OrientMode::FaceCameraPosition,
        rotation: Some(rotation_attr),
    })
    .render(SizeOverLifetimeModifier {
        gradient: size_gradient,
        screen_space_size: false,
    })
    .render(ParticleTextureModifier {
        texture_slot,
        sample_mapping: ImageSampleMapping::ModulateOpacityFromR,
    })
    .render(ColorOverLifetimeModifier { gradient })
}

fn explode(mut world: DeferredWorld<'_>, entity: Entity, _: ComponentId) {
    let assets = match world.get_resource::<ExplosionAssets>() {
        Some(assets) => assets.clone(),
        None => {
            let explosion_effect = world
                .get_resource_mut::<Assets<EffectAsset>>()
                .unwrap()
                .add(create_effect());

            let smoke_texture = world
                .get_resource::<AssetServer>()
                .unwrap()
                .load("explosion/smoke.png");

            let assets: ExplosionAssets = ExplosionAssets {
                explosion_effect,
                smoke_texture,
            };

            world.commands().insert_resource(assets.clone());
            assets
        }
    };

    world.commands().entity(entity).insert((
        ParticleEffectBundle {
            effect: ParticleEffect::new(assets.explosion_effect),

            ..default()
        },
        EffectMaterial {
            images: vec![assets.smoke_texture],
        },
    ));
}

@kim-fg
Copy link

kim-fg commented Jan 29, 2025

Okay so I do think this is the same issue as the one i previously mentioned. Thanks for letting me have a look at the code.
I can't help you more right now as this problem stems from a bug that I and others are trying to figure out the root cause of. Hopefully we can have it fixed soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
@Nigless @kim-fg and others