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

can spawn empty bundle from world #6424

Closed
wants to merge 1 commit into from

Conversation

mockersf
Copy link
Member

Objective

Solution

  • If the bundle being inserted is (), use world.spawn_empty() instead
  • Maybe not the best fix, but it works and it's easy 😄

@alice-i-cecile alice-i-cecile added this to the Bevy 0.9 milestone Oct 30, 2022
@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-ECS Entities, components, systems, and events labels Oct 30, 2022
@alice-i-cecile
Copy link
Member

Hmm yeah. I don't love the runtime branching, but maybe it gets optimized away. Does this regress our benchmarks?

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a regression test for this.

@cart
Copy link
Member

cart commented Oct 30, 2022

I think the only real alternative to branching somewhere in this impl is removing the Bundle impl for () and adding the constraint that Bundle can't be empty.

Note that this PR isn't a full fix. All empty bundles are broken:

// This fails in the same way
#[derive(Bundle)]
struct EmptyBundle {}
let mut world = World::new();
world.spawn(EmptyBundle {});

@cart
Copy link
Member

cart commented Oct 30, 2022

A full (still semi-weird) fix would be to check new_archetype_id == ArchetypeId::EMPTY in get_bundle_spawner, returning None in that case, and handling that with spawn_empty where appropriate.

But maybe we don't need to support empty bundles? Do they even have a purpose anymore? Only use case I can think of is that we don't have a batch spawning api for empty entities:
world.spawn_batch((0..100).map(|_| ())), which could be replaced with some world.spawn_empty_batch(100)

Also: idk if we need to hack around this for 0.9. This case fails with an unhelpful error message, but it still fails and it doesn't really have a use case. Maybe better to just hold off for a full solve.

@cart
Copy link
Member

cart commented Oct 30, 2022

world.spawn_batch((0..100).map(|_| ()))

Notably this also panics atm.

@alice-i-cecile
Copy link
Member

Yeah I think I'm fine with removing empty bundles completely. I don't like any of these fixes.

@cart
Copy link
Member

cart commented Oct 30, 2022

The core of the issue is that spawning empty bundles is framed as EmptyArchetype -> NewArchetype from an entity graph perspective, which requires (separate) ownership borrows of both. There is definitely a more satisfying solution that doesn't involve branching everywhere, but it will require rephrasing some things / revisiting assumptions. We could make it work, if we decide empty bundles are desirable. But its a non-trivial amount of work.

@cart
Copy link
Member

cart commented Oct 30, 2022

But yeah we should discuss removing empty bundles.

@cart
Copy link
Member

cart commented Oct 30, 2022

Came up with a reasonable long term fix: #6425

@mockersf mockersf closed this Oct 30, 2022
bors bot pushed a commit that referenced this pull request Nov 3, 2022
# Objective

Alternative to #6424 
Fixes #6226

Fixes spawning empty bundles

## Solution

Add `BundleComponentStatus` trait and implement it for `AddBundle` and a new `SpawnBundleStatus` type (which always returns an Added status). `write_components` is now generic on `BundleComponentStatus` instead of taking `AddBundle` directly. This means BundleSpawner can now avoid needing AddBundle from the Empty archetype, which means BundleSpawner no longer needs a reference to the original archetype.

In theory this cuts down on the work done in `write_components` when spawning, but I'm seeing no change in the spawn benchmarks.
bors bot pushed a commit that referenced this pull request Nov 3, 2022
# Objective

Alternative to #6424 
Fixes #6226

Fixes spawning empty bundles

## Solution

Add `BundleComponentStatus` trait and implement it for `AddBundle` and a new `SpawnBundleStatus` type (which always returns an Added status). `write_components` is now generic on `BundleComponentStatus` instead of taking `AddBundle` directly. This means BundleSpawner can now avoid needing AddBundle from the Empty archetype, which means BundleSpawner no longer needs a reference to the original archetype.

In theory this cuts down on the work done in `write_components` when spawning, but I'm seeing no change in the spawn benchmarks.
ItsDoot pushed a commit to ItsDoot/bevy that referenced this pull request Feb 1, 2023
# Objective

Alternative to bevyengine#6424 
Fixes bevyengine#6226

Fixes spawning empty bundles

## Solution

Add `BundleComponentStatus` trait and implement it for `AddBundle` and a new `SpawnBundleStatus` type (which always returns an Added status). `write_components` is now generic on `BundleComponentStatus` instead of taking `AddBundle` directly. This means BundleSpawner can now avoid needing AddBundle from the Empty archetype, which means BundleSpawner no longer needs a reference to the original archetype.

In theory this cuts down on the work done in `write_components` when spawning, but I'm seeing no change in the spawn benchmarks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

World.spawn(()) panics with index out of bounds
3 participants