bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.66k stars 3.61k forks source link

Meaning of the `EnvironmentMapLight` component is unclear #15751

Open alice-i-cecile opened 1 month ago

alice-i-cecile commented 1 month ago

Definitely unfortunate that the EnvironmentMapLight component is also used on camera entities. Looking at the examples it feels like that should be merged into the Skybox component. We could then require LightProbe for EnvironmentMapLight, but alas.

_Originally posted by @tim-blackbird in https://github.com/bevyengine/bevy/pull/15737#discussion_r1792320077_

JMS55 commented 1 month ago

You can have a EnvironmentMapLight without a Skybox though. It's just a source of light. It's meaning is contextual. On cameras, it's a global light for the environment. On light probes, it's a local source.

This is exactly the downside I feared with required components tbh. It ties components together too much sometimes, and starts ascribing more behavior to components instead of keeping them further to the "pure data" side of things.

cart commented 1 month ago

You can have a EnvironmentMapLight without a Skybox though. It's just a source of light. It's meaning is contextual. On cameras, it's a global light for the environment. On light probes, it's a local source.

If the meaning is contextual (as in, it has drastically different behaviors based on where it is), I think that is a very strong argument to have different components. Components == data + behaviors that key that data. If we muddy the waters too much on "what behavior you get based on context", that makes it harder for users (and bevy developers) to understand how the system works.

On cameras, it's a global light for the environment. On light probes, it's a local source.

This right here is already confusing to me and hard to document. If we continue down this path for EnvironmentMapLight, imagine trying to describe how it behaves if there are 10 different permutations with very different behaviors? Imagine trying to write the internal (or 3rd party code) that ensures queries for EnvironmentMapLight get the "right" one for the behavior you're building (and also taking into account whatever arbitrary 3rd party use cases happen to exist, given that we're treating EnvironmentMapLight as "just data" in this world).

Components are not "just data". They are data + behaviors. The easier we make it for people to predict the behaviors associated with a given component, the better.

This is exactly the downside I feared with required components tbh. It ties components together too much sometimes, and starts ascribing more behavior to components instead of keeping them further to the "pure data" side of things.

Required Components are not "required", in that if we identify a context where the component should behave like an arbitrary context-free holder of data and not a "driver of specific predictable behaviors" (I don't think EnvironmentMapLight is one of those, but we can discuss that), then the author of that component can just not define required components for it and not build systems that produce behaviors that "force" it into a particular mold. We only need to use Required Components where we think they make sense. I personally think they are the right default / recommended tool for spawning most classes of entities, as the majority of people are thinking in terms of "I want to spawn a Player" (and the other components required by Player) or "I want to spawn a Tree" (and the other components required by Tree).