Closed rj00a closed 1 year ago
I think this could technically be achieved already if you use multiple instances, but there would definitely be some double serializations.
Perhaps we could have the visibility layers be per instance. What if we had a builder-like api to be able to specify what layers are allowed to see which packets?
For example, spawning a particle effect (taken from the particle example):
instance.play_particle(particle, true, pos, offset, 0.1, 100); // global to instance
instance.layer(0b1).play_particle(particle, true, pos, offset, 0.1, 100); // local to layer 1, parameter is a bitmask
Alternatively, we could have the parameter not be a bitmask, and limit users to only apply changes to layers one at a time, which would be a little easier to implement and harder for users to mess up.
Also, I think we should limit the scope for now and leave blocks and block entities out, at least for the initial implementation.
64 layers might be too few for certain applications, for example, if you had a game where you have players in parties of 3-4 and parties have a trail of particles to follow, etc
64 layers might be too few for certain applications, for example, if you had a game where you have players in parties of 3-4 and parties have a trail of particles to follow, etc
Yeah imo 64 might not be enough for uhc, battle royale or open world mmorpg where there could be many parties. Maybe we should use a hashset (hashmap for cache) instead of bitmask?
The solution described doesn't fully account for scenario (2). Because "glowing" is part of the entity's metadata, you'd need to create two identical entities and put each on a separate layer to get the desired behavior. Can we fix that?
Maybe we could use an EntityLayers component:
#[derive(Component)]
pub struct EntityLayers(Vec<Entity>);
When processing an entity with EntityLayers
component, it will iterate the Vec<Entity>
with LayerMask
component (Maybe 0b1 if LayerMask
is not attached) and combine components (add/replace) with the base entity on that layer mask. Here's an example using EntityLayer
to glow teammate when the game starts.
#[derive(Component)]
pub struct Team {
layerMask: u64,
color: i32,
}
fn glow_teammate(
mut players: Query<(&Team, &mut EntityLayers)>,
mut event: EventReader<GameStart>,
mut commands: Commands,
) {
for _ in event.iter() {
for (team, mut em) in players.iter_mut() {
let mask_entity = commands
.spawn((LayerMask(team.layerMask), GlowColorOverride(team.color)))
.id();
em.0.push(mask_entity);
}
}
}
Describe the problem related to your feature request.
Sometimes it's necessary to limit what information sets of clients can receive. Here are some example scenarios:
What solution would you like?
Create a new component called
LayerMask
(name up for debate)LayerMask
is simply a bitmask where each bit represents a layer and whether or not it is active.LayerMask
s are attached to entities and determine what layers the entity is active on.Next, we have
ClientLayerMask
(name up for debate)This is also a bitmask, but it determines what layers a client can see.
ClientLayerMask
s are attached to clients only.Entity visibility is not the only thing we want to control with layers. For instance, if an entity is meant to emit a particle effect, the particles should probably follow the same visibility rules as the entity. So a hypothetical API for emitting particles (or sounds, block events, etc.) should look something like this:
Implementation Details
We want to continue to cache packets in per-chunk and per-instance buffers. Therefore, we need one packet buffer per layer wherever we previously had just one.
(Instead of a
[T; 64]
, we could useSmallVec<[T; 4]>
. The smallvec would grow on demand. But maybe there's an even better way...)When clients go to read the packet buffers, they use their
ClientLayerMask
to determine which buffers to read from.Questions
u64
limits the number of unique layers to64
. Is that enough for everyone?LayerMask
andClientLayerMask
be?1
seems reasonable.What alternative(s) have you considered?
You can sometimes send packets manually to achieve the same effect, but that's fraught with inefficiencies and errors.
Additional context
Unity's documentation on layers: https://docs.unity3d.com/Manual/use-layers.html?