#lightyear

1 messages · Page 9 of 1

pine cape
#

Did you add VisualInterpolation for the predicted projectiles?

#

The hashes are based on the tick + the type of all the components present on the entity when PreSpawnedPlayerObject is added

dreamy silo
#

If I assign/insert/spawn a session id to an entity as a component with a string inside containing said id, is it somehow readable by another clever user?

#

Any tips on how I could store session ids on clients without exposing them to the game itself? Perhaps only give the game client itself a client id, which then on the server can be associated to a session id on a db lookup. And versa.

fervent karma
#

Okay, there may actually be some types I left out, I know I forgot at least one component previously, so there may be more

pine cape
#

You can also manually compute the hash by providing a hash inside the PreSpawnedPlayerObject component, if that's easier

pine cape
fervent karma
fervent karma
long marsh
# pine cape Did you add VisualInterpolation for the predicted projectiles?

what is the intended api through which i enable visual interpolation for something? my player is definitely visually interpolated just from registering interpolation_fns for the appropriate components it seems like. so i lean towards saying, "yes, they are visually interpolated" (edit: might be a frame-pacing or camera issue instead of netcode, holup)

dreamy silo
dreamy silo
#

I could be overthinking stuff for a multiplayer game lol. Perhaps the client id associated with the correct user alone is sufficient. Just need to make the db reducer code right, where all the user’s data gets read and written from.

fervent karma
#

If you only replicate it to the one user (or maybe easier to send a message to the specific user to be sure it only goes there) it can't be read by anyone else no

#

But most clients will know of client ids from other players I think, so you shouldn't use that for authentication without some form of token that you only send to the specific user it belongs to

pine cape
# long marsh what is the intended api through which i enable visual interpolation for somethi...

Interpolation interpolates (using your registered interpolation functions) Interpolated entities by interpolating between 2 replication updates received from the server.
VisualInterpolation interpolates Predicted entities (also using your registered interpolation functions) to interpolate the FixedUpdate components across the PostUpdate schedule. So yes it's a framepacing issue. Maybe there should be a way to do this automatically for all Predicted entities by setting .add_visual_interpolation() on the registry.

This will 100% fix your jittering artifacts

For now you have to add this plugin: https://github.com/cBournhonesque/lightyear/blob/main/examples/fps/src/renderer.rs#L25
and then add this component on the entity: https://github.com/cBournhonesque/lightyear/blob/main/examples/fps/src/renderer.rs#L144

fervent karma
#

But I wouldn't really bother with considering security to begin with honestly

dreamy silo
#

I don’t know how hackable netcode is lol

fervent karma
#

In theory it should be pretty simple to tack on a token system at a later stage, but security is also notoriously complicated, so who knows

dreamy silo
#

Will probably never get to that point unless game actually is fun and people wanna get ahead. I’ll just have it in mind if I think it could happen in any case

pine cape
#

lightyear uses the netcode protocol for connections which is already 100% secure. You just need a secure way (for example https) to send a private ConnectToken to a user

dreamy silo
#

Im currently writing my database columns together with their reducers. Just tryna think if there’s anything obvious I’m missing in regards to security

dreamy silo
long marsh
pine cape
#

Maybe you also have avian interpolation enabled which is messing it up?
Also is your pos/rot -> transform enabled? Otherwise I don't really know what it is

long marsh
#

seems like it works great on the character example and that's where i stole half my setup from so BlobShrug

#

oh the answer is literally explained in a comment in that example
trigger_change_detection: true,

long marsh
#

now enabling VisualInterpolation causes some duplicating / smearing during rollbacks, especially at a lower tickrate. hrm

butter smooth in the happy case tho, very lovely

pine cape
#

are you running VisualInterpolation on Position or on Transform?

long marsh
#

Transform

pine cape
#

I wonder why you need trigger_change_detection; I guess because you need to somehow propagate the transform to GlobalTransform?

pine cape
long marsh
tropic jackal
#

Is this the correct syntax for receiving a message (server-side)?

pub fn foo(
    mut message: EventReader<MessageEvent<MyMessage>>,
) {
    for _ in message.read() {
        // Do something...
    }
}
long marsh
pine cape
long marsh
pine cape
#

yeah it only works with enough input delay to cover the RTT

#

at which point it might be worth simply interpolating everything (including current player)

#

hm even with a lot of input delay there's some jitter, i'm not sure why...

unkempt sedge
long marsh
#

hmm, by default, on main, when do the avian position to transform sync systems run relative to the (network) interp systems?

#

seems like the former in PostUpdate, the latter in Update, which would make sense... edit: ohh, no avian sync uses the same schedule as PhysicsPlugins by default. so it's only syncing on fixed possibly

pine cape
#

You don't need to run physics for interpolated entities

#

And visual interpolation should already be ordered correctly with respect to avian systems

long marsh
pine cape
#

Ah yes I made a custom sync system that is a copy of avians but also works for entities that are not rigid body

long marsh
#

yeah that did it. thanks. (edit: should such a system be built in?)

i did hit one other snag. the real thing that fixed my problem was manually setting an InterpolationConfig. the default one has send_interval_ratio: 2.0 - that means it buffers two ticks, yeah? seems to...not do that. i can only get something working with min_delay

dreamy silo
#

same issue here when trying to run a second client on my windows 11 machine after spinning up the server. its def because the exe that cargo run builds and runs is already occupied by the first client/server. classic case of windows not allowing two programs with the exact same filepath, name and file extension to run at the same time?

#

not really a concern, server wont run on the same machine as the client anyways.

fervent karma
#

Is there a way to receive messages from the client to the server on that same client? My use-case is trying to avoid having to duplicate implementation, so I would love to be able to run the same logic on the server and client (one example is that I use a message for spawning minions, and currently I send a message to the server, but on the client I just create it immediately). This is probably causing them to be created on different ticks (which is probably why I'm struggling to get PreSpawning to work actually), but maybe if there was a way to combine the message logic it would be easier to get them running in the same tick on both the server and client?

pine cape
pine cape
pine cape
fervent karma
#

I mean like a remote Client sends a message to the Server to spawn a "minion", but now I want the client to prespawn the minion, so I need to somehow capture that message on the client that sent it.
Also just to confirm, but messages arrive on the server in the same tick as they are sent from the Client, right?

pine cape
#

Normally you would have some game Event that runs in both the client and the server that you would react to in order to spawn a PreSpawn entity

#

how come the client knows to spawn a minion but not the server?

fervent karma
#

I guess I can test this by printing out the tick that the minions are spawned actually. But my true goal is to have a single system that I can run on both the server and client that accepts my Message struct and handles it

#

Oooh I just realized my minions don't work with PreSpawning because to make it easy for myself I didn't add a Name in the client one, so the components are indeed different...

#

Actually I think I confused myself, because spawning minions is handled with the Input, so that's already good I guess. But I have some other logic that is handled through Messages, specifically updating the target location for minions to move to, that's a good chunk of logic I'd want to consolidate, and it'll obviously grow as the game grows

pine cape
#

I think the tools you can use are:

  • PreSpawn: spawn an entity on the server and on the predicted timeline on the client. You need to run the same system in both client and server.
  • PrePredicted: spawn an entity on the predicted timeline on the client, and give the authority to the server. This is used when only the client knows about the entity that needs to be spawned, i.e. you cannot run the same system in both client and server
#

In your case of the client 'spawning' a minion, I think you need PrePredicted, not PreSpawn

#

(the naming is confusing but I don't have any better ideas)

fervent karma
#

Ooh, I hadn't heard of PrePredicted before, I'll give that a shot

pine cape
#

It's not super straightforward:

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

long marsh
pine cape
#

you're right that's pretty bad...

unkempt sedge
#

wow

#

such a cool bug check it out

long marsh
#

on a single entity, can i take a component that has add_prediction(ComponentSyncMode::Full), but then stop syncing it? for example with a projectile, i can deterministically predict it's position perfectly once the server confirms its location once, i don't need the confirmed entity's position sync'd after that

ComponentSyncMode::Once is basically the behavior i want, but i want it at the entity level. i thought e.g. ReplicateOnceComponent::<Position> might do it, but it seems like the client is still trying to sync the confirmed entity's Position that is no longer being updated by the server when i do that

pine cape
#

I don't think that's possible right now; would being able to override the ComponentSyncMode on the entity level work?

long marsh
pine cape
#

And how are you stopping the replication btw? Are you just removing Replicating

long marsh
long marsh
#

it’s kinda awkward in the case of remote clients. i really don’t want to replicate position data for projectiles, but if if the remote clients’ projectiles are in the predicted timeline and the remote players are in the interpolated one, it is gonna look bad. like they are shot from positions the shooter hasn’t reached yet

i can’t just stop replicating projectile position data and then set predicted to true for all projectiles for all clients. remote clients’ projectiles need to be correctly fired in the interpolated timeline. their position data, however, still needs to be extrapolated from that point on

pine cape
#

But if the projectile's trajectory is deterministic, why not PreSpawn it on both client and server then?

  • then the projectile moves via physics (or just linear velocity) on the client, and gets despawned on collision, etc.
  • damage computation are still done exclusively on the server
    that's what i do
long marsh
unkempt sedge
unkempt sedge
pine cape
#

Why does ReplicateOnceComponent::<Position> not work? Does your confirmed entity's Position still get updated somehow?

long marsh
long marsh
pine cape
#

You're predicting your own player and interpolating other players?

pine cape
#

Option 1

  • client 1 presses Fire and spawns a local bullet
  • server receives the input and spawns a non-replicated bullet
    • The client/server bullets should be fired from exactly the same spot thanks to prediction on the client 1's player
  • server sends a message to other clients saying that C1 fired a bullet, and those clients fire a bullet upon receipt of the message.

The issue is that there's no guarantee that the remote player will fire the bullet from the interpolated character's position.

Option 2:

  • client 1 presses Fire and spawns a prespawned bullet.
  • server spawns prespawned bullet at the same time and adds Replicate with Predicted = C1, Interpolated = AllExceptC1. Also ReplicateOnceComponent::<Position>
  • You add ComponentSyncMode::<Position> = Once on the client 1 (either on the Confirmed or Predicted entity, to be determined)
  • the Position is only replicated once to C1, but since you have ComponentSyncMode::<Position> on the C1's entity we don't check for rollbacks based on Position.
  • the bullet is spawned at the right interpolated position on the remote client C1, but it doesn't receive any more updates. You run a system on clients that still moves interpolated bullets so that you can keep moving bullets without any server updates

Option 3:

  • same as option 2 but you write every predicted position in the PredictedHistory to avoid rollbacks?
  • Theoretically this is not required because the way rollback works is that we only check for rollback if we received any update for any entity in the ReplicationGroup. So even if you don't send any more replication update for a bullet we would not check for rollback at all anymore.

So it looks like a combination of:

  • ReplicateOnce<Position> on the server
  • on the client, run movement systems for interpolated entities too
#

I will still open an issue for this because the current solutions are definitely not ideal, it would be great to have more flexibility on how Prediction/Interpolation works

long marsh
# pine cape **Option 1** - client 1 presses Fire and spawns a local bullet - server receives...

i had considered option 1, the biggest problems being

  1. i am sending a message to do replication which is a primary feature of lightyear, pretty dirty
  2. projectile should be in the interpolated timeline (message should say what tick to fire on) but since it’s not network interpolated via lightyear it doesn’t get visually interpolated

option 2 is my preference right now just because i know sync mode: once works. but again, i can’t use lightyear’s visual interpolation here without faking the network updates, because the objects aren’t in the predicted timeline (despite their positions being extrapolated)

option 3 makes me wonder if i have a bug, though? when i do that, the shooter’s projectiles are fine until the prespawned entity confirms. then the location of the projectile forever bounces back and forth between the first confirmed location and the first predicted one after that. constantly trying to roll back to the position where the prespawned entity was confirmed

#

the history faking is non trivial too, seemingly. i need to dissect some lightyear code to figure out what order of operations i have to do.

pine cape
#

For option 1: you would then move the remote-client bullet yourself on the client, you don't need Interpolation. VisualInterpolation is independent from replication, it can be applied to any component that gets updated in FixedUpdate. You can totally use visual interpolation without receiving network updates

#

I think option 3 should work in your use case, i would need more details to see why it doesn't work. Do you have a branch?

long marsh
#

idk why i thought Predicted was a requirement for vis interp, great if i can just add it to whatever

#

i'll set something up in a sec

long marsh
# pine cape I think option 3 should work in your use case, i would need more details to see ...

once branch in my repo

i am guessing based on your wording that i am causing problems by having one replication group per client / that client's entities? so that group still gets updates, even if that individual object does not.

so i tried giving each projectile a dedicated replication group, which has the hilarious behavior of all future projectiles shooting an additional projectile from the spawn location of every past projectile that hasn't despawned yet.

pine cape
#

That's a possibility, but why are any of your projectiles receiving a replication update? What other component besides Position is receiving updates?

long marsh
#

because of prespawn maybe?

pine cape
#

Maybe, if you enable debug logs it could tell you which component is causing the rollback

long marsh
#

ooh okay i was on the wrong track at first, here's something i think

i am getting rollbacks when the spawn command for my projectile is split into two messages.

here is an example of where the spawn message fit in one message

EntityActionsMessage { sequence_id: MessageId(0), group_id: 
ReplicationGroupId(12114142938702618892), actions: [(34v1#4294967330, 
EntityActions { spawn: Spawn, insert: [b"\r", b"\n", 
b"\x05\xc6\x17\xebA\0\0\0\x80\xd8\"\xc1\xc0", b"\x04d\0\x9a\x99\xcdA", 
b"\x06\xd0\xeb\x89?gff@e\t%@", b"\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x80?", 
b"\x08\x01\xfd\x0c!\xad\xbb\xd1\x14\x1e\xa8"], remove: [], updates: [] })] }

all good. no rollback. there is no other message for tha treplication group.

here is an example of where the spawn message was split into two:

EntityActionsMessage { sequence_id: MessageId(0), group_id: 
ReplicationGroupId(12114142938702618943), actions: [(35v1#4294967331, 
EntityActions { spawn: Spawn, insert: [b"\r", b"\n", 
b"\x05\x17\x17\x94\xc1\0\0\0\x80\xf8\xdc\xbc\xc1", b"\x04d\0\x8f\xc2\xd5A", 
b"\x06\x7f\xf6\x9d\xbefff@V\xb4IA", b"\x08\x01\xfd?!\xad\xbb\xd1\x14\x1e\xa8"], 
remove: [], updates: [] })] }

// The prespawned entity’s predicted entity is created and sync'd here, before this next message comes in.

EntityActionsMessage { sequence_id: MessageId(1), group_id: 
ReplicationGroupId(12114142938702618943), actions: [(35v1#4294967331, 
EntityActions { spawn: None, insert: [b"\x07\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x80?"], 
remove: [], updates: [] })] }

THAT causes a rollback. the insert, which is really just completing the original spawn command, is causing the rollback.

pine cape
#

Do you know what that extra component is?

long marsh
# pine cape Do you know what that extra component is?

golly. yes it is because of that specific component. i wasn't explicitly specifying a Rotation on the server-spawned entity, merely relying on it to be passively added from required components of the other physics components

need to add it explicitly right when i spawn the entity

#

i might be good now 👀

pine cape
#

Hm normally required components should add it at thr same time

#

But avian doesn't use required components for rotation I believe

#

I think they have specific systems to add missing components

long marsh
#

does rolling back to correct one object roll back the entire client simulation? seems like my primary problem now is that if any rollback happens (from a natural cause like cpu lag, packet loss, switching too quick between windows, etc), any projectile in flight gets reset to its starting position

unkempt sedge
#

Question, why we disable the colliderhierarchyplugin, when utilizing avian? Just curious, I guess is something with how the propagation works

pine cape
#

You don't need to disable it; i just disabled it because i didn't need the plugin

pine cape
#

Sorry that this hasn't been straightforward!

long marsh
# pine cape Sorry that this hasn't been straightforward!

equally sorry i’m causing so much trouble 😅

so if i spawn the predicted bullet and don’t replicate it to the shooter at all, it LOOKS fine, but the projectile can’t get server-sent despawn updates because i don’t replicate it

if i do replicate it, but don’t use prespawn, i just get projectile duplication. or if i don’t fire it on the client at all, i get firing lag

maybe per-entity sync mode is still gonna be the way 🤔 just using ReplicateOnce (now that i fixed all my other bugs) is good enough for me to move forward with experimenting though.

pine cape
# long marsh equally sorry i’m causing so much trouble 😅 so if i spawn the predicted bullet...

but the projectile can’t get server-sent despawn updates because i don’t replicate it
that might be fine, because i assume you would still run collision detection on the client for projectile VFXs

Another solution might be to remove the Predicted component on the pre-spawned bullet to stop it from being affected by rollbacks, but that's not super straightforward either.. Maybe a DisableRollback component could work?

Per-entity sync mode is not super straightforward because currently I add systems based on the component sync mode.
So the rollback systems are only added for the ComponentSyncMode::FULL components.
Being able to change syncmode means that I would have to add rollback systems for all replicated components, and then apply runtime filtering inside the system based on the OverrideSyncMode component.
Maybe just allowing overriding from Full->Simple or Full->Once but not the other directions would work

long marsh
#

or i suppose i could lag comp

pine cape
#

If you use interpolated enemies, you would lag comp on the server for accurate hit detection; but on the client you wouldn't do any lag comp, you would show VFX on actual collisions between predicted/interpolated

long marsh
#

yeah that’s what i’m saying. realistically since comp isn’t perfect i’d probably do a small local vfx and then a big confirmed vfx+sfx

but i am hoping to avoid lag comp entirely (or to have very generous / lazy comp) with big slow projectiles with generous hit boxes and a decent connection. but i truly don’t know if that is tunable into something that feels good or not. that’s part of the whole exercise im doing here i guess

unkempt sedge
#

Has anyone ever encountered an issue where sometimes when a client connect, one gets a massive amount of rollbacks? It seens to be correlated to system ordering, as it sometimes occurs and it doesnt. The issue is truly very crazy, as the cause is totally a mistery to me dont even know how to start debuggin

#

It give me this panic from time to time no idea why
overflow when subtracting durations
Encountered a panic in system lightyear::client::prediction::rollback::run_rollback!

stone osprey
#

Does this crate expose an abstraction to connect to sockets over either normal TCP or websockets (I want to use the former for native builds and the latter for web builds)? I added auth based on the auth example, but tokio's net feature doesn't compile for wasm.

#

Oh, I think PacketSender and PacketReceiver is what I need

stone osprey
#

Is there a way to get a WebSocketClientSocket? WebSocketClientSocketBuild is pub(crate)

pine cape
#

WebTransport doesn't fix your usecase?

pine cape
unkempt sedge
#

Unfortunately closed the terminal. I was just wondering, how would one go about fixing rollback loops issues? Like what metric can give me the component that is the root cause of those rollbacks. Perhaps them I can at least know where to start

pine cape
#

If you have visualizer feature enabled, type 'rollback' to find graphs that will tell you which components are the cause of the rollback

unkempt sedge
#

hmm it seens the rollback loop overcharges my machine, any diagnostics info that may be usefull here?

#

the visualizer becomes very stale

long marsh
pine cape
#

yep, or lightyear::client::prediction::rollback=debug

lyric badge
#

hi im having some trouble connecting with the client when the host is in a different machine
im connecting using Netcode, and the server is set to localhost on the port 5000

pub fn get_server_net(config_data: &ConfigData) -> lightyear::prelude::server::NetConfig {
    NetConfig::Netcode {
        config: server::config::NetcodeConfig {
            private_key: config_data.private_key,
            protocol_id: PROTOCOL_ID,
            ..default()
        },
        io: IoConfig::from_transport(ServerTransport::UdpSocket(SocketAddr::new(IpAddr::V4(config_data.server_ip), config_data.server_port))),
    }
}

pub fn get_client_net(config_data: &ConfigData) -> lightyear::prelude::client::NetConfig {
    lightyear::prelude::client::NetConfig::Netcode {
        auth: Authentication::Manual {
            server_addr: SocketAddr::new(IpAddr::V4(config_data.server_ip), config_data.server_port),
            client_id: config_data.client_id,
            private_key: config_data.private_key,
            protocol_id: PROTOCOL_ID,
        },
    io: lightyear::prelude::client::IoConfig::from_transport(ClientTransport::UdpSocket(SocketAddr::new(IpAddr::V4(config_data.server_ip), config_data.server_port))),
        config: NetcodeConfig::default(),
    }
}

to connect from the client i use the actual ip and the same port
is that configuration correct?

pine cape
#

Set the server to 0.0.0.0 instead of localhost

lyric badge
#

how come?

#

im guessing that sets it to its actual ip?

#

hm

#

didnt know that

pine cape
#

It makes the kernel choose an IP address for routing

#

i'm not too clear on the details

lyric badge
#

okok

#

regardless, thank you

fervent karma
#

The general gist is that picking the ip for the socket is a local OS concept completely unrelated to your public ip

long marsh
# lyric badge how come?

when you choose an ip you are implicitly chosing a network interface. when you choose 127.0.0.1 you are choosing the loopback interface which only accepts connections originating from the same machine.

stone osprey
pine cape
#

Ah i see; no lightyear doesn't provide this; you can make a PR to make WebSocketClientSocketBuilder pub, but the Transports currently have some extra stuff that is only needed by lightyear

lyric badge
long marsh
lyric badge
#

yes, i tried it with both the server and client on my machine

long marsh
#

youre on LAN?

#

like not remote over the internet, just local network

lyric badge
#

yes

long marsh
# lyric badge yes

ok so the true correct setup is

  1. client listen address is the client host’s local IP as assigned by the router
  2. server address (on the client) and server listen address are both the server host’s local IP as assigned by the router

you can usually cheat both listen addresses by choosing 0.0.0.0, which is why you’re getting that advice. it accepts connections on all network interfaces

lyric badge
#

is the local ip the same as the public ip?

long marsh
#

if you list network interfaces for your OS it should be listed in there

lyric badge
#

and this setup wouldnt work when doing it over the internet, right?

long marsh
#

over the internet you need the public IP, right

#

but you’ll still listen on the local IPs, the router uses those IPs to know which computer to forward to

that’s why you have to set up port forwarding in your router when you expose something to the internet from home. the router has to know, when a connection comes in on a certain port, which computer on the local network do i send it to?

#

once you are production deployed in some cloud it’ll be different again probably, depending on your setup

lyric badge
#

ok i think i understand

#

well, i understand the local ip and public ip + port forwarding

lyric badge
pine cape
#

The server specifies 0.0.0.0 for its own server_addr, but the client needs to use the server's public ip as server_addr.
Same for client

lyric badge
#

sorry what do you mean when you say "Same for the client"?

#

i understand the first part, i think
in lightyear it would translate to the server NetConfig io using 0.0.0.0 and the client NetConfig auth using the server's public ip
do you mean that the client NetConfig should also be 0.0.0.0?

pine cape
#

I think the client should specify their own address as 0.0.0.0, but the server would specify the client-addr as public_ip:port

long marsh
lyric badge
#

okok

#

thank you guys for your patience

#

ill try it out tomorrow

#

🫡

stone osprey
#

I migrated to main and the player can't move anymore. There aren't any new warnings/errors in the logs

pine cape
#

are you using leafwing inputs or native?

stone osprey
#

native

#

I'm checking to see if the same issue happens in the examples, but I have to figure out why steamworks isn't compiling

pine cape
#

simple_box works fine in main

unkempt sedge
#

our building system is being held back because version 0.19, does not support avian 0.2.1. I saw it had something to do with "issues" what they might be? Perhaps we can help

stone osprey
#

Ok, sometimes when I run my game, the player can move. Attacking causes the player to despawn, though, which I suspect is an issue with hierarchy stuff, bc that spawns an attack that's a child of the player

#

I think I'll just make my changes off 0.19 for now

pine cape
#

hm i'm unsure of what could be wrong

pine cape
# unkempt sedge our building system is being held back because version 0.19, does not support av...

Here's the issue I created: https://github.com/Jondolf/avian/issues/643
there seems to be a problem with how the ColliderAABB is computed

GitHub

Something in avian 0.2.1 is breaking the way my ColliderAABB is computed. My flow: after Solver but before SpatialQuery, I update the Position/Rotation/Collider of an entity that is a child of a pa...

#

The way you can test it is use avian 0.2.1 and run the fps example. The ColliderAABB for lag compensation are in the wrong position

sly ibex
#

Super dumb question, but what crates do I need to import to make the simple startup work? Downloading the full repo works fine, but recreating it throws six or so errors

#

Sorry if this is a dumb question 😓

unkempt sedge
#

no such thingy as dumb questions

unkempt sedge
#

Just chec my mre cargo should be more than enough to get you starrted

sly ibex
#

also it worked, tyvm king!

unkempt sedge
#

oh my jebus

pine cape
#

that's fine, you just have higher jitter so you're receiving old updates

wet kelp
#

i'm beeing stupid right now. havent had this problem on an older version:
When running in HostServer mode, the client connection needs to be of type Local

i'm using the build_client_plugin() and build_server_plugin() from the simple box example.

#

alright, discordd was eating parts of my message, the when running in hostServer mode.... is the panic message i'm getting when trygin to connect to the server i started before in the same app

stone osprey
# stone osprey Ok, I will soon, thanks

I'm having to make a lot of internals public, and it's kind of contrived to make this work for my use case, so I think I'll just write my own websocket stuff for auth

primal cargo
#

What's the best way to let a server send replication updates to a client, for the purposes of spawning an entity, but give the client authority such that it can despawn the entity and replicate that update to the server? I tried giving the entity client authority on the server side (on initial spawn), but then the client never receives the spawn replication update from the server

pine cape
#

I don't think that's possible. You could have the client send a message to the server to despawn the entity

primal cargo
#

Hmm, okay. I'm thinking of attaching some sort of ID to each of these entities through the server to solve this. Is there a better way of telling the server which entity to despawn?

long marsh
unique plover
#

I'm currently splitting off my complex sim systems so they're not running in rollback and I noticed that gizmos are cleared out during rollback and are not rendered when set during the regular FixedUpdate. It results in gizmos flickering when some rollbacks occur. I can definitely set the gizmos during rollback too to fix this issue, or swap so I'm not using gizmos for these systems (since they'll be actual rendered models in the future), but this does point to a complex issue of Bevy and library provided FixedUpdate interactions with the rollback of the entirety of FixedMain. I'm wondering if a configurable rollback schedule might be better, but I think that would have to happen during one of the fixed schedules and would have to ignore Bevy's fixed loop when more than one FixedMain needs to happen in a frame.

#

Ideally for me rollback systems are "opt in"

unique plover
#

I could probably solve this with my own implementation of a fixed sim schedule, but that seems like overkill.

unique plover
sonic citrus
#

I'm using 0.19.0, and I get this error when sending a message. This seems like an oversight, since lightyear now uses varints for encoding fragments?

pine cape
sonic citrus
#

looks like it

#

also thinking about it

#

if FragmentIndex is a u64, how does this work on platforms where usize is 32 bit?

pine cape
sonic citrus
unique plover
pine cape
pine cape
unique plover
pine cape
#

Maybe a Rollback schedule could be added which runs roughly at the same time as FixedUpdate?

#

Main should work

unique plover
#

I think letting the user decide (optionally) where to put the schedule is the best setup personally, but yeah parallelizing the rollback while FixedMain goes through its own loop could be a solid architecture for me.

unkempt sedge
unkempt sedge
#

Well according to the logs, when my client disconnects and quickly reconnects it seens server didnt have the time to despawn it is old entities. Which causes rollbacks right on the get go. Because he still tries to replicate his previous entitties to client itself, this was my bug I wonder how I could fix it, guess I just need to wait or make despawn more immediate as server despawn seens very slow for some reason

#

the bug might also occur when one, has network-relevance manager enabled with replicate target and sync target all entities. As it seen that the sync target component applies it is logic before the room manager (sometimes, system order non defined) actually applies, causing rollback as he will receive replicate from entitites in other rooms yet he has no information on them

#

Guess the "get started" system from sync target is a little faster than network relevance manager, which makes sense when I come to think of it

#

The fix make replication targers unique to client id, as room manager logic self increases both sync target and replication target

#

Which is appreciated

pine cape
#

Can you open an issue?

unkempt sedge
# pine cape Can you open an issue?

I will first refactor my mre to check my theory and a continous sample, but from what I see yes it occurs first, in my bullet logic, when you make them consider rooms. You get constant "trying to despawn entity error" even tho that bullet shouldnt even be on that room.

pine cape
#

Ah I see, yes a mre would be helpful!

long marsh
#

i have some non-sync’d predicted projectiles with VisualInterpolation<Transform>.

when those projectiles undergo a Position misprediction as they spawn (since they were not prespawned), the correction function is properly applying the correction to Position.

i cannot, however figure out when to extract that corrected Position to Transform in a way that does not break the Visual Interp somehow. any thoughts? it’d be easy if corrections were applied in the fixed schedule, but looks like they get updated in PostUpdate

#

like, in the normal, non-corrected scenario, i don’t need to extract those positions manually at all, it just works. but the corrections are getting swallowed by vis interp somewhere if i don’t manually copy them over

pine cape
#

You're right

#

you might have to run a sync system (from pos to transform) again in PostUpdate, after correction

#

And i guess we could either disable visual interpolation if the component is being corrected

#

Or order correction to happen after visual interpolation

wet kelp
#

how can i change the netcode to be local? i'm trying to understand the lobby example, but having a hard time following the "common" folder 🙂

wet kelp
#

alright, i got it.... lol

wicked tulip
#

vast improvements on current main compared to the 0.19 release.

A lot less jitter, even with cubes and jumping it feels really good when predicted.

Still the interpolated other player seems to be jittery when changing direction under the provided networking conditions:

latency_ms: 50,
jitter_ms: 1,
packet_loss: 0.03,

Is there a way to modify how the interpolation of other controlled entities work?

Like adding a little bit more lag but having it smoother for the interpolation?

long marsh
long marsh
#

hm

when the predicted projectile fires on the remote player's screen (right player shoots on the top screen), a rollback happens since there was no prespawned projectile. this (correct) rollback causes the predicted player (top screen, left) to jitter even though they were correctly predicted.

the addional jitter is there even when i disable all my interpolation and correction copying. it's like the rollback of the predicted timeline is spitting out a slightly different result for the player. struggling to understand how it could be different though..

pine cape
#

Can you open issues for this? I'm at a ski trip now so I might forget about them when I come back if they're not on the github

pine cape
long marsh
#

realize it's a pretty vague ask

pine cape
#

You would need to log the values for each tick to see if they are really diverging

long marsh
#

ill fiddle with an example and see if i can repro

pine cape
#

Do you use gizmos? Someone was saying that rollbacks can cause them to flicker

long marsh
#

not in this case but i definitely have that issue when i do. is that why the box that encloses the spaceships example constantly flickers while a remote player is moving?

pine cape
#

I think so yes

unkempt sedge
#

As in sole clients that doesnt occur

#

Hmm interesting just found out that if a bullet has a different rigidbody definition than my player rigidbody. When I have a bullet rollback it expects lineardamping on it, something solely applied on my character physical rigid body

#

man debug has truly unlocked some good shit

molten socket
#

I'm trying to add a singleplayer mode in my game. I chose to use the LocalChannel client transport with Netcode.
But when I simulate a crash from the internal server app or even when I stop the server normally (commands.stop_server();), the client spams error in the console (even after exceeding client_timeout_secs):

2025-02-16T21:23:24.153303Z ERROR lightyear::connection::netcode::client::connection: error updating netcode client: Transport(Io(Custom { kind: Other, error: "error receiving packet: Disconnected" }))
2025-02-16T21:23:24.153407Z ERROR lightyear::client::networking: Error updating netcode: netcode error: error receiving packet: Disconnected
2025-02-16T21:23:24.153958Z ERROR lightyear::client::networking: Error sending packet: netcode error: error sending packet

Switching to UdpSocket transport don't cause these problems (even after a crash from the server)

pine cape
#

LocalChannel, so 2 apps in the same process? Could you please open an issue?

molten socket
#

Yes 2 apps in the same process. The internal server app is launched in a seperate thread

long marsh
#

i think client error handling might just need some love in general

long marsh
# long marsh hm when the predicted projectile fires on the remote player's screen (right pla...

it was disguised by other bugs, but this ultimately was due to my correction-copying system. idk why the player is getting corrected tho. logs are fine, rollback simulation sync is fine with previous frames.

excluding the player from the position_to_transforms_after_correction system fixes it, so that must be the problem. but if there weren't any mispredictions, why was there a correction?

overall it is fine because i am treating "predicted and fully replicated" differently from "predicted and fully extrapolated", so i'll just only extract corrections for the latter...just can't clock why the player is getting corrected at all

long marsh
#

we are in business tho. with all of my known bugs fixed this feels great and doesn't need me to do lag comp. 🙂 maybe a little silly looking with the sped-up projectiles on the target

unique plover
#

Gizmos are cleared in FixedFirst

wicked tulip
long marsh
long marsh
pine cape
# long marsh we are in business tho. with all of my known bugs fixed this feels _great_ and d...

Awesome, so the problem is that during rollbacks some things are corrected even though they don't need to be? Yes I think that's the current behaviour, currently I rollback everything without tracking which entities didn't need to be rollbacked. Great find, thanks!
I would appreciate if you could send me your test repo
It would also be nice if we could just rollback the prepawned entity and nothing else.. maybe during check rollback I can add a ToBeRollbacked marker on the Predicted entities that are mispredicted, and leave the rest. That's a bit risky though

#

This sounds like the same issue maybe? You see them being rollbacked visually because of correction, if we disabled correction for correctly predicted entities your projectiles would not move even during rollback

long marsh
#

i am sitting here trying to decide if my entities are considered “correctly predicted” by lightyears systems if the confirmed entity only gets updated once

#

probably not, right, because the confirmed tick will be way too old relative to the prediction window of “when projectile spawned until now”

pine cape
#

Also can you tell me more about your approach? If I understand correctly your enemies are interpolated, and you replicate a bullet with both Interpolated and Predicted? Or are you using prespawning? I saw something about spawning a bullet on the interpolated timeline, and then fast-forwarding it to the predicted timeline. How do you achieve that?

pine cape
long marsh
# pine cape Also can you tell me more about your approach? If I understand correctly your en...

my repo is up to date if you wanna go poke around. you can repro just by lowering the shoot cooldown and spamming shots with two clients open (cooldown is above my player component declaration)

enemies are interpolated but enemy projectiles are predicted. i don’t prespawn them, i just let them rollback into the predicted timeline from the confirmed one. this makes them “fast forward” kinda via the correction function.

the idea is to have enemy projectiles be more in the interpolated timeline when they are close to the enemy (so it looks like they shot from the right position) but more in the predicted timeline when close to you (so you can dodge it). since the local player is predicted you want to be able to dodge things in that same timeline

long marsh
#

but uh. say i fire a projectile on tick 100. on tick 120 i fire another one, causing a rollback of, say, 5 ticks. when all my systems run for tick 115-120, where during those executions is the original tick 100 projectile in the simulation? just at its historical predicted location?

#

bc otherwise how could you resimulate its position starting from 115 when your confirmed data is stale from tick 100

long marsh
pine cape
long marsh
pine cape
#

Ah I see, you could interpolate everything including the current player, then

long marsh
#

gotta predict player movement or it feels like crap, which causes all the downstream problems haha

#

less bad in a click to move game; with wasd it’s truly unplayable to have unpredicted movement

#

i’ve been using a lag injector to check how some games work so i can steal it, and this setup seems to be the consensus

unkempt sedge
wicked tulip
pine cape
long marsh
pine cape
#

Nope it's off by default

#

But you're right that they have it as an option

#

I never thought of having prediction on just for the movement, but not for sprlls

long marsh
#

i rejected it the first time i came across the solution and didn’t revisit it until i studied Battlerite with my lag simulator, hah

#

i think some mmos pull the same trick

pine cape
#

battlerite does this?

#

But also you said that other players shoot projectiles which are sped up into the predicted timeline

#

but that doesn't work for projectiles from interpolated player 1 to interpolated player 2

#

in that case you want the projectile to remain interpolated no?

long marsh
# pine cape in that case you want the projectile to remain interpolated no?

well ideally sure but if you’re gonna give up visual consistency, rather it be between two players you are not interacting with

i think ideally the way the projectile might work is to have it be more predicted the closer it is to you (the dodger), and more interpolated the further it is away. sounds tricky

long marsh
# pine cape battlerite does this?

idk about the projectile fast forwarding, just the predictive movement with lagged abilities

their melee is crazy, the visual is just a lie. attacker’s visual in predicted timeline, but the hitbox in confirmed 😬

pine cape
#

that's good to know, i'd love to have a resource that lists examples of how other games do this kind of stuff

#

it's funny that your predicted players shoots projects in interpolated timeline, and interpolated players shoot projectiles in predicted timeline

long marsh
unkempt sedge
#

Question, what would be the ideal use, of a pseudo client?

#

My case scenario -We have a tower space, which is basically a room. That has it is own kinda lobby/room. we ideally always want that room to exist but for a room to exist it must have a client id connected to it

pine cape
long marsh
pine cape
#

I didn't check the settings carefully; but I think correction is enabled?

pine cape
long marsh
#

yeah i did

long marsh
unkempt sedge
long marsh
#

ahhh, remember my issue where i said visual interp was blowing out corrections? it's that

#

i didn't port my fix for that

pine cape
#

i thought this would fix it

#

but for some reason it doesn't seem to work

#

ah maybe that's it

#

Could you make a PR with your fix to lightyear? Is it just a system ordering? or is it an avian-sync issue

long marsh
# pine cape Could you make a PR with your fix to lightyear? Is it just a system ordering? or...

i wonder if that PR you just linked fixes the problem i am about to describe (edit: it doesnt) but, i don't have a general solution atm. what i'm doing...

app.add_systems(
    PostUpdate,
    (
        position_to_transform_for_corrections
            .before(TransformSystem::TransformPropagate)
            .after(InterpolationSet::VisualInterpolation),
    ),
);

pub fn position_to_transform_for_corrections(
    mut query: Query<(&mut Transform, &Position), (With<Correction<Position>>, Without<PlayerId>)>,
) {
    for (mut transform, pos) in &mut query {
        transform.translation = pos.f32();
    }
}

but since i keep getting inaccurate (?) corrections put on my player i need to explicitly except them, so upstreaming would break me

long marsh
#

but idk to the extent that different games / users want to configure that differently. although i do believe there should be one "blessed" avian setup out of the box without the workarounds

long marsh
#

refactored my protocol into it's own crate. incremental compilation time to the common crate 33s -> 7s. 🎉

#

can't tell you how much time ive wasted compiling

wicked tulip
#

I know there is Host mode, but it’s more challenging to reason about compared to server/client mode.

Is it possible to run an android app with client/server?

Or would you need to spin up a server for an android app if you don’t want to use Host Mode?

pine cape
#

I have no idea, are android apps single threaded?

wicked tulip
#

Small request for docus update on the

    /// Percentage of packet loss
    pub packet_loss: f32,

For the package loss, I think adding that the value is between [0,1] would make it clearer, as I though 1.0 would mean 1% package loss, and got confused why I couldn't connect to the server...

unkempt sedge
#

Hmm the hashsets keys, inside entity to rooms. Never get cleared is that an expected behaviour?

#

Ought to think just repopping the entities would be the same time, and wouldnt cause excessive memory storage here

unkempt sedge
#

Btw if you dont clear client from a room and he reconnects to that same room some very weird shit happens

wicked tulip
#

Just to confirm, if a pre-spawned entity, then receives the server confirmed entity, both will still exist (one makred with Predicted the other with Confirmed, but they will not merge. is that correct?

pine cape
wicked tulip
#

I tested main and the new skip-correction branch, but I still have very visible stuttering for physics objects.

I am doing the same as is done in the 2d spaceship example, but in 3d something seems to be different.

pine cape
#

Stuttering like that can be due to one of 2 things:

  • visual interpolation is not setup properly so your objects move in FixedUpdate, but not in Update schedule
  • you have constant rollbacks
    I think you should first try to see which one it is
unkempt sedge
#

If that little guy is going banana, well it is gonna look like shit

wicked tulip
# pine cape Stuttering like that can be due to one of 2 things: - visual interpolation is no...

ClientInterpolation is added through the ClientPlugin (also If I try to add it on the client, I get an error that is has already been added).

I also tried to modify the parameters to see if that would improve the stutter but not really any success.

What is a good way to check for rollbacks?

Comparing the confirmed and predicted positions per tick, or is there another way to check if a rollback occured?

wicked tulip
unkempt sedge
#

this is how

#

Go to your egui, and open this guy

#

Another way is enabling rollbacks debug on log plugin

#

I dont know how to do that tho using the setting setup? Mayber overriding but seens unecessary

wicked tulip
#

I have thousands

unkempt sedge
#

Yes as you can see not good

wicked tulip
#

Its basically every tick

unkempt sedge
#

yes it is

#

I think I will refactor that sample.

#

@pine cape Is it necessary, for all samples to follow the "low-code" approach utilized with the predispose settings file?

#

I believe it would be a good idea to split them into portions. For example: Avian 3d character makes a character that moves physically.

#

Not a character that moves physically both in host mode and in separate mode. And is friendly with edgegap

pine cape
pine cape
unkempt sedge
# pine cape it's convenient for me to be able to test all examples in all modes

Hmm I see, but alas It seen maintenance will become overbearing at same point (my impression is that most sample are already unstable). Also most games just follow one "style", never heard of a game that transitions, between host mode to separate mode according to servers. Perhaps we can make most samples using the common separate mode and one general testing one, instead of multiple different scenarios and codes.

pine cape
#

I think most examples are working fine, it's mostly just the avian samples that are having issues since I changed a lot of rollback related stuff recently

wicked tulip
pine cape
#

that's unfortunate, the rollbacks were completely gone when removing the cubes. You mean the avian_3d example right?

wicked tulip
#

by using the following conditioner:

conditioner: Some(Conditioner {
        latency_ms: 100,
        jitter_ms: 20,
        packet_loss: 0.01,
    }),
wicked tulip
#

It looks like as soon as there is any collision there are continous roolbacks afterwards (every tick)

unkempt sedge
wicked tulip
#

@pine cape the fact that we have continuous rollbacks, does that mean we have a simulation that never converges again?

Would that mean the predicted and the confirmed entities have differences every frame?

peak ice
#

Hello everyone! I am looking for someone to possibly play a game demo and then have a conversation about what kind of networking shenanigans I need to use for it to feel right. Right now my code is heavly based on the starship example, I just don't think things feel right on the client side, and when there is large amounts of latency (100ms) the client side is unplayable. I'm looking for a recommended networking setup for a PvE game that you play with friends where one friend is the hostserver.

unkempt sedge
#

Perhaps you can try using kinematic bodies (that has worked out for me) with sensor colliders as hitboxes.. Or just dont use physics at all

peak ice
#

I am using kinematic bodies, that isn't the issue right now. Its more along the lines of, do I predict? do I interpolate? have input lag? who has authorty over what?

unkempt sedge
#

Depend on your game, is it fast paced, is it slow paced? Input lag is generally utilized with predicted entities and mostly used with high ping conditions. Server most of the time should be the authority figure, he should tell who spawns, when replication occur and so on. But sometimes you can use client_replication, to avoid over using server example: Read cursor movement

peak ice
#

yeah the game is kinda fast paced, It intended for friends playing together so I don't care about cheating which opens up client side authority. I have a demo on steam I could share with anyone trying to get a better idea on the style of game.

unkempt sedge
#

fast paced, should have predicted entities. For player, and interpolated for npcs. You can make all interpolated and one sole client predicted (specially if there is no pvp) for the player scenario

peak ice
#

ok, so fast paced games should have predicted players. Im noticing input lag kinda ruins the feel on the client side, can you do predicted entities without input lag?

unkempt sedge
#

it usually should be 0

wicked tulip
# peak ice ok, so fast paced games should have predicted players. Im noticing input lag kin...

Once we figure out what is causing the rollbacks, prediction should feel really good.

We are about to release a fully networked experience in VR where we use the prediction/client/server tech (similar to what lightyear is using) it it feels very responsive.

So if it feels unresponsive its more likely related to some issue in lightyear (either on your implementation or the framework itself) rather than the networking model.

pine cape
pine cape
#

Then you could predict your own actions and interpolate everything else, which would make your own actions feel responsive but you might have to use lag compensation

#

If your game has a lot of physics-based interactions (collisions, etc) you could try to predict everything, but as you have seen in the spaceships example it mostly feels good only when there are no mispredictions. I think for things to feel good even with mispredictions you would need more tuning: maybe extrapolation using velocity/acceleration, tweak the correction parameters, etc.

long marsh
#

for the pve with friends i would just give up server authority tbh

pine cape
wicked tulip
# pine cape I would have to check debug logs to see, it could be some avian non-determinism

So it seems the controlled entity is not the issue but the other entity is (without any boxes).

From the log I don't fully understand the meaning:

Correction { original_prediction: Position(Vec3(2.1028938, 1.2499865, 0.11440856)), original_tick: Tick(3642), final_correction_tick: Tick(3657), current_visual: Some(Position(Vec3(2.1028936, 1.2499865, 0.11440855))), current_correction: None }
#

It seems to be off by a very small amount, and the current_correction is None,

Is there a way to define quantization for the synced values?

wicked tulip
#

So it seems to be related to collisions, when Gravity is set to 0, the rollbacks stop after a while.

But even then there are rollbacks as soon as the other player is moved.

#

(but only when stoppind and starting the movement, when moving continously the rollbacks stop without gravity)

unkempt sedge
wicked tulip
unkempt sedge
#

oh yeah it is

#

oh now it isnt

#

check the prediciton value and currentt value

#

thei have a 0.00001 difference

#

So a rollback yotu shall have

wicked tulip
#

but it seems not to make any difference

wicked tulip
unkempt sedge
#

HMM

wicked tulip
#

The part which I can't find up to now is why the current_visual is Some and the current_correction is None, from what I can see is that the current_correction is only None if its a new correction (but then the current_visual should be None as well.

unkempt sedge
#

My my that explains a lot of my rollback loops

#

I have no idea why it occurs my guess is it thinks it should rollbacks, but it doesnt return the correction component

#

Therefore he keeps rollbacking

#

And maybe sometimes he gets the component

wicked tulip
#

I checked the collisions, and they appear to be reported with the same values and the same order

#

After analyzing some more logs, it seems that they collisions re not identical, different point data, normal_impulse etc.

So it seems the collisions diverge between the client 2 and the client 1.

#

values are close but diverge slightly, like -0.029934 vs -0.029934008

fervent karma
#

Are you sure you're using the correct clock? I.e. Time<Fixed>

wicked tulip
fervent karma
#

I'm sorry, I missed the context, ignore me 😅

#

Actually that example does use Res<Time>, it would be worth checking if Res<Time<Fixed>> makes a difference. It did cause desyncs for me, but that was also on 0.14, so maybe the behaviour is different for 0.15

wicked tulip
# fervent karma Actually that example does use `Res<Time>`, it would be worth checking if `Res<T...

even when replacing all Res<Time> with Res<Time<Fixed>> I get continuous rollbacks.

So it still is an issue. What I'm not sure about if the corrections aren't properly applied (and we get different collisions every frame).

Or if the collisions are inherently diverging.

It looks like at the start the collisions are identical, but after I bump into the other character they diverge (ever so slightly).

I couldn't really find a place where the correction functions are used in the lightyear source, but I might just be missing it.

#

(I checked, and the functions are called which are provided in the protocol, but even when returning the target value withour interpolating I get continous rollbacks)

unkempt sedge
wicked tulip
unkempt sedge
#

that doesnt make sense, if they have the same order why would they diverge between clients?

unkempt sedge
#

is it prediction::rollback tralalal =debug?

wicked tulip
unkempt sedge
#

Perhaps it would be a good idea to leave such logs on debug and pr that

#

I would appreciate it

wicked tulip
sly ibex
#

Could I ask for some file management / module advice in here kings? Like where explicitly what kind of functions would go in which file (main.rs, client.rs, shared.rs and server.rs etc)

I read through the cheatbook and it was p good-- but I dont got the game development knowledge to extrapolate much from that

#

Doing something of a very basic 2d rpg if that helps any

peak ice
# pine cape If your game has a lot of physics-based interactions (collisions, etc) you could...

The game has a lot of colliders, sensors, but very minimal dynamic bodies in terms of how I'm using the physics engine. The main reason I'm even here is this problem:
On the server side the client player moves smooth, on the client side the server player (and other client players) seem to overcorrect for inputs and they jump around, but only when there is latency (set to 100ms, similar value to live testing with a friend).

I'm not sure why this is happening. The code is based on the spaceship example so I know its server authoritive were everything is predicted, which is something I could give up on because of PvE. But why does the server side's client player still look smooth? I feel like I should be able to get better results without moving from prediction to interpolation or changing who's the authority of the player.

peak ice
sly ibex
#

Dedicated, yeah. Trying to avoid crossing everything up and making a MESS without knowing the whys n wheres

#

Something simple, tile based, probably simpler than a roguelike even

peak ice
#

lol i might be in that situation haha

sly ibex
#

I will take a look, ty homie
When I last looked at this guys stuff I found it very uh, daunting 😅

peak ice
#

yeah it took me like 2 weeks just to get a main menu with a hostserver and client button working lol

#

I personally found getting an example "working" without his lightyear_example_common library was a good place to start. It abstracts a lot of the setup of lightyear making the examples easier to read and harder to copy.

sly ibex
peak ice
fervent karma
#

That link 404s for me

peak ice
#

it was private my bad, is it working now?

fervent karma
#

Yess thank you, I've been wanting to get something like this set up

#

Especially the part about connecting to steam friends seems awesome

peak ice
#

Just a warning, I only tested steam connections with my actual steam game app id, I'm pretty sure it will still work with the default 480 app id but it wasn't tested.

wintry dome
#

regarding the constant rollbacks with prediction and avian integration.. presumably values are nearly correct, are we talking tiny floating point discrepencies causing rollbacks? wondering if anyone has tried quantizing the physics values (position, rotation, linvel, etc) before and after the physics step, on client and server?

gaffer suggests this so you can transmit the values using fewer bits, but it would also maybe hide any minor desync issues (See the Quantize both sides section)

i never got to properly testing this to see what the side effects are, but i just rediscovered it and put it in a gist in case anyone wants to experiment: https://gist.github.com/RJ/74e598b84dd81feb40f72407dee4ad79

it quantizes stuff before physics runs, and after physics but before physics syncs transforms etc. so the game/networking should only ever see quantized values for physics states (client & server). in this case i'm using a scale factor of 1/8192, which means ~ 0.0012 is the smallest difference in values you can represent.

unkempt sedge
peak ice
pine cape
wicked tulip
wicked tulip
wintry dome
#

i'm not sure it needs to be run twice.. i'd test by running it before physics and after physics but before avian's sync set for starters i think

#

to make sure none of your code or lightyears code ever sees a non-quantized physics value

pine cape
#

What do you mean by quantization? Which library is introducing quantization?

wintry dome
#

like rounding to a multiple of some small fixed amount, to reduce the accuracy of the floats but in a deterministic way. i think this is often done by multiplying by a scale factor, rounding to an i32, and then converting back. it limits the available accuracy for physics values, so you could transmit them as a type of integer. but i was mainly thinking of using it to paper over any small floating point disrepencies

#

from the gaffer article "In the cube simulation I found it necessary to have 4096 position values per-meter" so he's tuned the quantization so he can represent 1000mm in 4096 integers, ie 1000/4096 = 0.25mm accuracy

unkempt sedge
#

Question, does replicateoncecomponent needs to be registered in the protocol?

wintry dome
#

doesn't need to be baked into avian for an experiment. just write systems that mutates all the postion, rotation, linvel, etc. and run it before physics set and before physics sync.

#

you probably only need to quantize any physics values that are in the protocol and being replicated, ie position, rotation, linearvelocity, maybe mass or angular velocity or some others depending on the game

#

in the case of Position, instead of operating on a 2d or 3d plane represented by float coords, operates on a snap-to-grid of distinct values where the quantization scale defines the grid spacing. values after quantization will be very similar to before, but snapped to the nearest grid position.

pine cape
#

Ah you mean you want to add quantization to fix the issue?
I'm pretty sure avian is mostly deterministic, there's just loss of determinism due to:

  • entity ordering (in hashmaps, etc.)
  • ordering of contact points
wintry dome
#

yes, quantization having the added benefit of maybe making it easier to save bits on the wire, but really just to hide any small differences due to non deterministic avian shenanigans and make stuff work without constant rollbacks

#

obviously fixing the root cause would be ideal 🙂

unkempt sedge
#

Them replicate once component should be used, when you want to add a component after some server logic?

#

Intead of being right on build time like in protocol

pine cape
#

You register component C in the protocol, then you add ReplicateOnce<C> on your entity to make sure that no updates are sent after the initial update

unkempt sedge
#

Okay so it ceases the replication good to know

wicked tulip
wintry dome
wicked tulip
pine cape
#

I caught up on the determinism discussion

#

the issue is definitely in avian

#

were you able to run the avian_determinism test with randomly ordered entities and multiple contact points and get a passing test?

young prawn
#

yeah determinism_2d is fully deterministic with shuffled entity spawning order (but without joints)

pine cape
young prawn
pine cape
#

good to know, thanks!

unkempt sedge
#

2025-02-19T15:55:21.572718Z DEBUG lightyear::client::prediction::rollback:247: Rollback check: mismatch for component between predicted 77v1#4294967373 and confirmed 72v1#4294967368 on tick Tick(161) for component "avian3d::dynamics::rigid_body::LinearVelocity". Current tick: Tick(267) predicted_exist=false confirmed_exist=true
I believe there is a condition missing that should check, if predicted history exist before rollback on current main

#

oh just saw the todo

wicked tulip
#

if I schuffle the columns (as suggested):

    let mut cols = (0..COLUMNS).collect::<Vec<u32>>();
    cols.shuffle(&mut rand::thread_rng());

    for col in cols {
        let x = x_root + col as f32 * delta_x;

The results produce different hashes every time.

pine cape
young prawn
wicked tulip
#

(and I also tested with latest main, which has the replication changes merged in, but with the same results)

long marsh
# pine cape <@158726638144585728> this should help improve the correction logic; https://git...

this does correct the interaction between corrections and vis interp, but there's something funky going on with corrections now

i just confirmed with the logs, that sometimes i see the (visual) correction being applied a tick late. the object will spend 1 tick at its final predicted position, then the correction kicks in and it teleports back to get corrected the rest of the way.

when it works, this log is showing up on the same tick that the predicted object is created (https://github.com/cBournhonesque/lightyear/blob/3748543999b82f9bd74e8ae9b9f27e4404da9ed5/lightyear/src/client/prediction/correction.rs#L72)

when it doesn't work, that log shows up a tick late

long marsh
#

the actual Correction component is there on the first tick in both cases and seems to be in the same state 🤔

pine cape
#

Hm, the sync plugin needs to run after Correction, that might be why

#

So that visual interpolation has the correct Transform values to interpolate between

#

When there's 2 FixedUpdate in one frame (which is most of the time), then the sync plugin gets applied

#

but if there's only 1 FixedUpdate in one frame, then Position is corrected but Transform isn't

#

I'll try to move it to FixedPostUpdate instead of FixedLast, and add the required orderings

peak ice
unkempt sedge
wicked tulip
#

At least I have the simplest sample now:

  • 1 cube (dynamic rigidbody)
  • 1 Floor (static rigidbody)

even without player inputs produces continous rollbacks and never gets to rest.

The server also has continous movement (due to no sleeping), but for some reason, even without any player input we have continous rollbacks.

wicked tulip
#

One think I don't understand is why:

correction=Correction { original_prediction: Position(Vec3(-1.0952371, 0.99995565, -0.17343313)), original_tick: Tick(19399), final_correction_tick: Tick(19400), current_visual: None, current_correction: None }

the current_correction is always None. Its as if the correction is never applied?

as inside the get_visually_corrected_state system, the value should always be Some...

unkempt sedge
#

I expect so

wicked tulip
unkempt sedge
#

He is quite troublesome

wicked tulip
#

The goal is to find out what causes the rollbacks, so this is a very good setup

unkempt sedge
#

Oh okay

wicked tulip
#

Can’t make a game with lightyear if you can’t use physics 😅

wicked tulip
#

when I enable debug for lightyear I get the following outputs for the rollbacks:

2025-02-19T21:49:44.012479Z DEBUG lightyear::client::prediction::rollback: Rollback check: mismatch for component between predicted 66v1#4294967362 and confirmed 64v1#4294967360 on tick Tick(896) for component "avian3d::dynamics::rigid_body::LinearVelocity". Current tick: Tick(897) predicted_exist=true confirmed_exist=true
2025-02-19T21:49:44.012496Z DEBUG lightyear::client::prediction::rollback: Rollback check: mismatch for component between predicted 66v1#4294967362 and confirmed 64v1#4294967360 on tick Tick(896) for component "bevy_transform::components::transform::Transform". Current tick: Tick(897) predicted_exist=true confirmed_exist=true
2025-02-19T21:49:44.012578Z DEBUG lightyear::client::prediction::rollback: in prepare rollback
2025-02-19T21:49:44.012585Z DEBUG lightyear::client::prediction::rollback: in prepare rollback
2025-02-19T21:49:44.012586Z DEBUG lightyear::client::prediction::rollback: in prepare rollback
2025-02-19T21:49:44.012625Z DEBUG lightyear::client::prediction::rollback: in prepare rollback
2025-02-19T21:49:44.012628Z DEBUG lightyear::client::prediction::rollback: in prepare rollback
2025-02-19T21:49:44.012603Z DEBUG lightyear::client::prediction::rollback: in prepare rollback
2025-02-19T21:49:44.012656Z DEBUG lightyear::client::prediction::rollback: in prepare rollback
2025-02-19T21:49:44.012650Z DEBUG lightyear::client::prediction::rollback: in prepare rollback
2025-02-19T21:49:44.013438Z DEBUG lightyear::client::prediction::rollback: Rollback between Tick(897) and Tick(897)
2025-02-19T21:49:44.013454Z DEBUG lightyear::client::prediction::rollback: Rollback tick: Tick(897)
#

is it expected that the rollback happens between the same ticks? (897)

pine cape
#

Nope; are you testing with very little latency?

pine cape
wicked tulip
wicked tulip
#

(Unless you use joints, but that will be solved at a later point)

wicked tulip
#

So it seems from the experiments I ran that avian (and the contact points or entity ID order) is not the cause of indeterminism.

unkempt sedge
#

Question what is the difference between server conditioner and client conditioner?

pine cape
pine cape
wicked tulip
wicked tulip
unkempt sedge
unkempt sedge
#

I believe

#

If prediction extrapolates what shall occur why would it is extrapolation tick ever be equal to cureent tick

pine cape
sly ibex
#

hello bros, i have another foolish question;
coming from the setup in the cheatbook i believe i have made an error, not entirely certain why but this is what im getting with a copy of what's in the cheatbook protocol.rs

unkempt sedge
#

Question when using the simple setup, where is the field in each I can disable confirmed entities

#

I have just so many of them my egui is bvecoming clustered

pine cape
unkempt sedge
#

when using interpolated entities, who are predicted in their client but interpolated in others into whon should i station the collider? In the interpolated i assume

pine cape
#

You should probably put physics components like colliders in the predicted entity

unkempt sedge
#

but them my other client wouldnt have the collider if they share a room would him

unkempt sedge
#
fn add_physics_to_player(
    physical_entities: Query<
        (
            Entity,
            Has<Predicted>,
            Has<Interpolated>,
            Has<ReplicationTarget>,
        ),
        (Added<PlayerMarker>, Without<Confirmed>),
    >,
    mut commands: Commands,
) {
    for (entity, is_predicted, is_interpolated, is_replicated) in physical_entities.iter() {
        if is_predicted || is_replicated {
            commands.entity(entity).insert(CharacterPhysics::default());
        }
        if is_interpolated {
            commands
                .entity(entity)
                .insert(RigidBody::Kinematic)
                .insert(Collider::cuboid(1.0, 1.0, 1.0));
        }
    }
}```
#

Shoudl i do something like this?

#

Another question, how would a client know, the action my interpolated entity is making. It seens there is no input buffer in interpolated entities?

fervent karma
unkempt sedge
#

There is no direct message to client if separate mode correct? One cannot send a message from one client to another

#

If they are not hosts I mean

pine cape
#

Correct, all messages go through the server

hexed ruin
#

Is it a good idea to mix TCP and UDP? One of the features of my games is modding and I’d like players to be able to download the files through a TCP connection. But I’d like them to actually play the game through a UDP connection when going against players. Is such a thing a good idea?

pine cape
#

Yes I think that's fine! The "auth" example mixes TCP and UDP

wintry dome
sonic citrus
#

is it possible to unit test code which uses ConnectionManager?

pine cape
fervent karma
#

How do you get logs that show the PreSpawnedPlayerObject hash and stuff? I tried the vizualiser, but that doesn't seem to have the logs

pine cape
#

Bevy_inspector_egui should be able to show the component value, right?

fervent karma
#

But the object disappears once the replication comes through, so it's gone in an instant

#

I'm trying to debug a prespawned object not being replaced as I'd expect, I check that I'm using all the same components, but I might be missing something

unkempt sedge
#

@pine cape Mr Peri when it comes to ai, what would your approach be? I want to make it both for player and npc. As if a player ragequits the other at least have a bot to play with them. Would you make it entirely server side?

fervent karma
#

Hmm, turns out the issue with PreSpawnedPlayerObject was just because I was still using Time instead of Time<Fixed> in some places 😅

pine cape
#

Time is equivalent to Time<Fixed> in FixedUpdate. PreSpawnedPlayerObject should only be used in FixedMain schedule

pine cape
fervent karma
pine cape
#

FixedMain contains FixedPreUpdate, FixedUpdate, FixedPostUpdate, etc.

peak ice
#

Hello again! I'm trying to create a menu system that runs a server in a separate thread. So far I'm trying to spawn the server thread using https://github.com/EkardNT/bevy-tokio-tasks, in a bevy system. I have the code here https://github.com/SueHeir/lightyear-menu. I believe the issue is that the crossbeams channels aren't working with bevy-tokio-tasks, but im not confident on that. The setup should start the server when you click the button and stop the server when you exit, not sure how else to accomplish this without the bevy-tokio-tasks plugin.

#

maybe the server needs spawned at the beginning, and then somehow told to start when you click the button, not sure

pine cape
#

Maybe a simpler option would be to start the other thread with the server and leave it always running, but then use a run-condition/state to enable/disable it

peak ice
#

so the thread would be spawned in main, and the server would always be running, but wouldn't let people connect until the host client is connected?

#

This might be a option, but then if I run two instances of the game on the same computer while testing it we'd have servers trying to use the same ports

pine cape
#

The server wouldn't always be running; the thread would.
You could use a channel to let the thread know to call server.start() and server.stop()

peak ice
#

oh snap I messed up the server address, should have been LOCAL_SOCKET!!

pine cape
#

@wicked tulip @young prawn I have 0 rollbacks without collisions. I believe the main issue with rollbacks when collisions are involved is that
I need to rollback the Collisions resource to the server-state at tick T. Currently I do a non-networked rollback, meaning that I rollback the resource to its state at rollback_tick in the client-history. This doesn't necessarily match the state of the resource on the server at rollback_tick, which is why we see a discrepancy. This would mean that to completely avoid constant rollbacks we would need to replicate the Collision resource through the network, which might be expensive. I wonder if there is a way in avian to compute collisions from scratch from a given tick using all Positions, etc. without requiring the Collisions resource?

peak ice
pine cape
#

Awesome, I'll try it!

peak ice
#

some of my fixes are questionable, but its just a first pass, a minimally viable menu if you will... Looks at handle_disconnections system

peak ice
#

works on mac os, no idea why

peak ice
# pine cape The server wouldn't always be running; the thread would. You could use a channel...

switch it to spawn the server thread at the start seems to fix my windows issues, the only problem is when I try to control it with a channel message my server doesn't work. I've pinned it down to having a system request a resource that is the channel receiver. Everything is working until I add this one system https://github.com/SueHeir/lightyear-menu/commit/df6e72dc7ef62fce78a1c50c30026b3091037f77

peak ice
#

I think i got it fixed now:)

wintry dome
#

and i suppose when a client joins, they don't have the collisions from the previous frame stored in Collisions, which the comments suggest it would be on the server version "..contains collisions from both the current frame and the previous frame". perhaps that has a subtle knock-on effect too.

unkempt sedge
#

Impl very nice, from the ai crate i saw yours is the most intuitive one just wanted to let you know

wintry dome
wintry dome
#

could you ask in #game-ai don't want to go too offtopic in here

wicked oak
#

i have two workspace server and client, does lightyear support dedicated server?what i want rn is on main from server workspace start the server and on client main workspace connect to the server

wicked tulip
#

(also headless server)

peak ice
long marsh
#

i ended up with one crate for server, one for client, then additional shared crates, all in one workspace. client and server each their own binary. that was good for pure dedicated server

then when i wanted client host, i just also made the server crate a lib and made it an optional / feature flagged dependency on the client

wicked oak
wicked oak
#

can i see your examples?

#

like how do i start the server

long marsh
wicked oak
#

thanks piefayth

wicked oak
#

yeah no, the example is old @long marsh

long marsh
wicked oak
#

wydm

#

i need add serde dependecy

#

i see

#

this seens not a dedicated server example

#

i mean i just think lightyear doenst support different workspaces

pine cape
unkempt sedge
#

I think periwink made a few games that are subidivided in workspaces

wicked oak
#

well iam trying but i cant somehow

unkempt sedge
#

I think brianh was developing a shooter of sort in conjunction with mr peri.

#

I am not sure tho, perhaps you could take a look into it

long marsh
wintry dome
wicked oak
#

like the example also build players and bots, why bro, i just want connect, they should make simple examples

#

guess i will do via https

#

with rust api

long marsh
wicked oak
#

but i did

#

welll

#

i will try use https rust protocol

#

since there is not a reliable plugin for bevy rn for it

long marsh
wicked oak
#

Separate mode works

#

cool, hwo do i check when a player connected on server? @long marsh

#

nvm

#

i saw the tutorial

wicked oak
#

questions guys, how do i generated the private_key and protocol_id?

wicked oak
#

guys why the event is not firing ?

#
impl Plugin for ServerConnectionPlugin {
    fn build(&self, app: &mut App) {
        app.add_plugins(setup_server_connection()).add_systems(Startup,start_server).add_systems(Update, handle_connections);
    }
}
#

and yes i start the server / client workspaces

#

i see

#

wich can be the cause?

#

nvm

#

i fixed

#

the api is very clear now

young prawn
#

I'm pretty sure disabling warm starting should be enough to prevent contacts from previous frames from affecting the simulation though

wicked oak
#

Iam curious ,what is the problem he is facing? Since iam using lightyear and avian too @young prawn

young prawn
#

rollbacks when objects collide

wicked oak
#

I wanted to know how the replication works for players controlling a character and how safe its, iam making a battlegrounds game,open map everyone vs everyone, will have powers and movement abilities and even teleport skills, usually how i do is:

1-Player move on client instantly
2-it tells the server the movement and the reason of the movement
3-Server checks if he can move on that position taking in consideration the reason of movement, Example: If he is just walking it will take the player speed as consideration, if he used a teleport skill it will check if the teleport position distance is correctly basead on the max distance of the skill, etc etc
4-if the serve thinks its invalid so it will teleport the player back, or where the player should be

So how does lightyear handle the replication, is similar ?

#

@pine cape since you are th owner i wanted to know

wet kelp
#

@wicked oak there is the avian3d example in the repo which pretty much should explain your questions

wicked oak
#

the example show how setupt it, doenst explain how it works

wet kelp
#

it implemented the movement and server client logic. isnt that what you asked for ?

#

sry if i misinterpreted your question

wicked oak
#

well try read again

#

xd

wet kelp
#

you wanted to know how lightyear handles the character movement and replication,right?

wicked oak
#

yes

wet kelp
#

in that case, you have the answer in the avian3d example. it implements a simple scene with 3d character movement. You have leafwing as inputmanager wich gets reprocessed by the server and transported back to the clients

#

hang on, i'll link it to you

#

its the one i started with and its working pretty well so far. sometimes soemthing breakes, but thats normal for an engine/lib in this state

#

clone the repo and start the example, this way you shoud see if its what you need to start with

#

from there, just build up on it

#

if you have any specific question, don't hesitate to aks, i'm happy to help you with it since i was having some trouble at first too 🙂

#

so i know the feeling and struggles

wicked oak
#

@wet kelp hm

#

look i created a plataform on server for example

#

how would i replicate for client

#

this

#

its becuase i make a plataform on server and its not replicated when the player join aftr

#

yes it doenst get replicated for the client

#
 commands.spawn((
            RigidBody::Static,
            Collider::cylinder(50.0, 0.1),
            Mesh3d(meshes.add(Cylinder::new(50.0, 0.1))),
            MeshMaterial3d(materials.add(Color::WHITE)),
            Replicate::default()
        ));
#

just appear on server

#

there is no clear simple examples of how do it

wet kelp
#

have you tried to do it the same way the example handles floors, boxes and the player?
it should work the same way, create a marker, and call a function if it got added

#

give me a sec

#

i'll give you an example

wicked oak
#

bet

#

thaks

wicked oak
#

so? @wet kelp

wicked oak
#

they are not going straight to point

#

it calls a lot of others mods to do a simple stuff, making it messy

wet kelp
#

sry, i'm at work right now, will do it as soon as i have a bit of time. got surprised with a meeting, sry for that, the examples are fine tho. look in the example i linked you how they do it with the floor and just follow that

wicked oak
#

i did but they are messy, i would need copy all others 4 rust files it calls for just spawn one part? lol

#

it should be straight to point

#

like just here is 3 new rust files, like why, make it simple bro

#

FloorMarker

#

FloorPhysicsBundle::default(),

#

REPLICATION_GROUP

#

like lmao

wet kelp
#

if you don't need physics, just dont add it. its just components

#

the marker is fort the query

wicked oak
#

wich query, where

wet kelp
#

did you follow the marker?

wicked oak
#

what do you mean by follow the marker?

#

iam brazilian

wet kelp
#

hello from Berlin ❤️

the marker is really just a component, if you look into the renderer.rs you have the add_floor_comsetics function which gets triggerd by the added floormarker and adds the meshes

#

it really is that easy

#

sry, have to go afk again for a bit

wicked oak
#

like this ProtocolPlugin i cant even find where its begin added

#

nvm

#

let me try

wicked oak
#

yeah bro, i tryed, no sucess

#

protocol plugin

#

the renderer

#

= nothing

#

it just dont replicate

#

this info never prints

wet kelp
#

i know it can be frustrating, don't give up, we will figure out whats going wrong.
as soon as i finished work, i can help you better

wicked oak
#

that is it, nothing works

#

xd

#

gonna use the whole day to figure out, if the examples were straight to point .

unkempt sedge
#

congratulations

long marsh
# wicked oak this info never prints

are you using bevy_inspector_egui? it might help to use that look at the state of the components on the server and client. especially making sure that

  • The FloorMarker actually exists on the server
  • The ReplicationTarget component on the floor on the server is set to All
  • FloorMarker for sure isn't on the client at all

etc

i would also verify you are actually registering the ProtocolPlugin

wicked oak
#

ReplicationTarget

#

let me check

wicked oak
#

the ReplicationTarget is all as you can see

#

floormarket is on client yes

#

and yes protocol is registering

#

on client too

#

all checks out

wet kelp
#

did you add the Protocolplugin to your shared or main plugin, wherever you call them?

wicked oak
wet kelp
#

alright....

long marsh
wicked oak
#

look let me add a print on it

#

here is supposed to floor appea

#

on client

#

let me play

long marsh
#

so i’m asking because lightyear has a TON of additional logging hidden behind the debug log level. it would give you more information about what is happening from WITHIN lightyear

wicked oak
#

idk

#

seens all correctly but doenst work

wicked oak
#

my server / net config

fn net_config() -> NetConfig{
    let io_config = IoConfig{
        transport: ServerTransport::UdpSocket(SERVER_ADDR),
        ..default()
    };

    let netcode_config = NetcodeConfig::default()
        .with_protocol_id(PROTOCOL_ID)
        .with_key(PRIVATE_KEY);

    NetConfig::Netcode{
        config: netcode_config,
        io: io_config,
    }
}

fn setup_server_connection() -> ServerPlugins{
    ServerPlugins::new(ServerConfig {
        shared: shared_config(),
        net: vec![net_config()],
        ..default()
    })
}
#

client / net config

fn net_config() -> NetConfig{
    let io_config = IoConfig{
        transport: ClientTransport::UdpSocket(CLIENT_ADDR),
        ..default()
    };

    let auth = Authentication::Manual {
        server_addr: SERVER_ADDR,
        client_id: 1,
        private_key: PRIVATE_KEY,
        protocol_id: PROTOCOL_ID,
    };

    NetConfig::Netcode {
        auth,
        config: Default::default(),
        io: io_config
    }
}

fn setup_client_connection() -> ClientPlugins {
    ClientPlugins::new(ClientConfig {
        shared: shared_config(),
        net: net_config(),
        ..default()
    })
}
long marsh
# wicked oak no

assuming you are in PowerShell or Terminal run this: $env:RUST_LOG="debug"

then do cargo run *> server_out.txt but replace cargo run with your normal command for server/client. (and for client, change it to client_out.txt)

#

then just start both, close them, and look at the output filefs

#

you can get your logs back to normal with $env:RUST_LOG="info"

wicked oak
#

shared config

pub fn shared_config() -> SharedConfig {
    SharedConfig {
       server_replication_send_interval: Duration::from_millis(0),
        tick: TickConfig { tick_duration: Duration::from_secs_f64(1.0 / 64.0)},
        mode: Mode::Separate,
    }
}
wet kelp
#

i may have an idea,. have you tried running lightyear with the main branch yet?

wicked oak
#

?

#

there is one main rust file per workspace

#

just on shared that is a lib

#

this is my workspace

wet kelp
#

sry for beeing unclear, still at work ^^

lightyear = { git = "https://github.com/cBournhonesque/lightyear.git", branch = "main", features = [
"avian3d",
"bevy_egui",
"leafwing",
"lz4",
"mock_time",
"steam",
"trace",
"track_change_detection",
"visualizer",
"websocket",
"webtransport",
"zstd",
] }
put this into your Cargo.toml and comment out your version

wicked oak
#

is this a problem?

wet kelp
#

i had some issues with the non main version

wicked oak
#

but i need add the features list?

#

or it will add all features if i dont use it?

#

i prefer not need to list all lol

#

let me try

wet kelp
#

you just need to add the features you need.
after updating it, you also need to change your shared_config. i think you need to remove the Mode:Separate part.

wicked oak
#

? there is no mode now

wicked oak
#

why

#

mode is not necessary anymorew

wet kelp
#

exactly

wicked oak
#

nothing changes

#

still no replication

#

wait bro i noticed something

wet kelp
#

can you push your stuff to git and give me the link, i would love to debug it

wicked oak
#

that may be import

#

let me show

#

this on client have this entity

#

i removed the floor on server to test, and when i do this entity is not created on client

#

so seens something is getting replicated but

#

this never triggers

#

making not possible to add the collider

#

this also doenst trigger

long marsh
#

oh so the entity IS getting replicated but FloorMarker isn't, that helps

#

all you should have to do to replicate FloorMarker is

  • add it to your protocol
  • put the component on the entity on the server

that's...the whole thing

wicked oak
#

this is odne already

long marsh
#

right

wicked oak
#
use bevy::prelude::{App, Component, Plugin};
use lightyear::prelude::{AppComponentExt, ChannelDirection, ReplicationGroup};
use lightyear::prelude::client::ComponentSyncMode;
use serde::{Deserialize, Serialize};

pub const REPLICATION_GROUP: ReplicationGroup = ReplicationGroup::new_id(1);

#[derive(Component, Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct FloorMarker;

pub struct ProtocolPlugin;

impl Plugin for ProtocolPlugin {
    fn build(&self, app: &mut App) {
        app.register_component::<FloorMarker>(ChannelDirection::ServerToClient)
            .add_prediction(ComponentSyncMode::Once);
    }
}
#

protocol

#
commands.spawn((
        RigidBody::Static,
        Collider::cylinder(50.0, 0.1),
        //Mesh3d(meshes.add(Cylinder::new(50.0, 0.1))),
        //MeshMaterial3d(materials.add(Color::WHITE)),
        FloorMarker,
        Replicate{
            group: REPLICATION_GROUP,
            target: ReplicationTarget {
                target: NetworkTarget::All,
            },
            ..default()
        }
    ));
#

server spwaning

long marsh
#

that's kinda why i was trying to get your debug logs, cause i agree everything looks right

wicked oak
#

server_out.txt

#

on the execute commands

long marsh
#

oh that's a great question, try it

but it has to be *> server_out.txt

idk if they execute that command in a powershell context or not, will just have to try

#

if not you can just open powershell and do it that way

#

honestly you might even have to set the log level environment variable in that menu too

#

the RUST_LOG="debug"

long marsh
#

idk but definitely with this box somehow

#

i just do it with environment var so i can switch without recompiling

wicked oak
long marsh
#

yeah ok i kinda figured

wicked oak
#

nothing gets created

long marsh
#

you will have to do it in Terminal or PowerShell, or like, forget the file thing and just write it all to the console

#

if you dont mind scrolling through a million miles of logs

long marsh
#

the debug logs

long marsh
#

yeah

#

like verbatim what i do is

wicked oak
#

that is it?

long marsh
#

yeah but need the logs from a time where the client succesfully connected

#

looks like they have some connection error there

#

client might not have had debug logging on either, that looks like just info and error

wicked oak
#

so the last sutff is client disconnecting

long marsh
#

oh ok in that case you didnt have debug logs on the clinet

#

make sure you set the env in both terminal instances

wicked oak
#

$env:RUST_LOG="debug"

long marsh
#

yeah you had it right for the server logs

#

was just client that was missing them

wicked oak
#

this time i closed client first

long marsh
#

weird. FloorMarker is definitely in both protocols, but it looks like the server just isn't sending it thinkfused

remote_tick=Tick(2799) EntityActionsMessage { sequence_id: MessageId(0), group_id: ReplicationGroupId(1), actions: [(20v1#4294967316, 
EntityActions { spawn: Spawn, insert: [], remove: [], updates: [] })] }
#

that's the message the client gets; no components listed to insert

wicked oak
#

the system hates me

long marsh
#

like code that finds all floor markers, does something to them, then removes it?

wicked oak
#

take a look

long marsh
# wicked oak take a look

you have FloorMarker defined twice, im guessing the one in your protocol isn't the one you're actually putting on the entity

wicked oak
#

ooo

#

bro is the goat

#

bro thanks it f works

#

you are goat

long marsh
#

happy to help

wicked oak
#

iam happy that you exist bro

peak ice
#

So I've been pretty happy with how my lightyear project is coming along, runs very well most of the time. I've noticed that when the person I'm testing it with is using wifi I get incredible lag spikes when they're hosting the server. (its happened with two different people now). The person claims they never have any issues when they play multiplayer games, league, wow, overwatch, etc.

Question: Do PvP - all predicted style games need a dedicated server running from a server provider to compensate for people's bad internet?
Is there anyway to debug this issue? Or does everyone playing this game just need to buy an ethernet cord? Could it be a bandwidth issue?

unkempt sedge
#

Could be a compression issue, tho? Perhaps you are just sending too much information. Via server and so on

peak ice
#

yeah the issue always happens when I spawn in a bunch of enemies (like 10, not a lot), but sometimes it happens when we're just standing there

#

so how do I check the bandwidth usage? what is a resonable amount for a game?

pine cape
#

You can check the bandwidth usage via the visualizer feature

#

How often are you sending replication updates

peak ice
#

ok sick I'll look into that, and 20 ms

unkempt sedge
peak ice
#

yeah if the person is connected with ethernet then spawning enemies is never an issue, 100's of them is fine.

misty wyvern
#

Hmm ya could just be the bandwidth limitations but ideally the host is never on WiFi. The games mentioned your friend would have never hosted, and would have only ever experienced internet traffic from a client's perspective, as those games have dedicated servers ran only by the developers AFAIK. So I don't think they're a good benchmark for this.

If you get stuck on this, is it feasible to scatter these spawns out over time?

Could they be saturating the WiFi itself? Does lightyear have a way to customize the MTU per packet?

digital cedar
#

hey wanna ask if prespawning can work in this scenario, I have a scene (which have multiple hierarchies in it) i wanted to spawn in both server and the client. I want most of the things to be in sync with the server, can this work using prespawning? and how rould that work? (or is this a bad idea?)

long marsh
digital cedar
long marsh
#

if the scene isn’t dynamic i would just replicate a marker and use the marker to indicate to the client to load the scene

#

but if you want to pick and choose specific objects that do or do not get replicated dynamically, you can’t escape having to identify them programmatically somehow

digital cedar
#

truee, the scene is partially static and partially dynamic, which means i need to mark those that are dynamic

long marsh
# digital cedar truee, the scene is partially static and partially dynamic, which means i need t...

i get why you’re asking about prespawning though, you want to match those dynamic entities up? so you just load the scene normally on both ends and it all syncs?

that might actually work if you went through the hierarchy and put the prespawn component with an appropriate id on every dynamic entity on both the client and server

but i do NOT know how prespawning works with hierarchies; never tried that

digital cedar
#

i still think the most straightforward way is still replicating..

wicked oak
#

hey guys, how could i replicate this component to client, so client can know the combatant type

#
#[derive(Component)]
pub enum Type{
    Player,
    Npc
}
sly ibex
#

Is the lightyear cheatbook now out of date? I get errors using the example code / some from the github

sly ibex
#

Ah, gotcha homie 🙏

copper laurel
#

If someone tried both approaches, why would you pick lightyear over bevy_replicon? I'm familiar with the overview of both, but in practical terms what's "better"?

pine cape
#

Replicon has better performance and tries to provide an abstraction for messaging/replication can build upon.

Lightyear has more features (prediction, interpolation, input handling, authority, etc.)

sly ibex
#

Would you say a bevy project can be adapted to lightyear later in development, or would doing so be significantly more difficult out of interest

pine cape
#

You would just load the asset on the client no?

pine cape
unkempt sedge
#

2025-02-27T20:41:41.771954Z DEBUG lightyear::client::prediction::prespawn: PreSpawnedPlayerObject hook, setting the hash on the component entity=456v5#21474836936 tick=Tick(983) hash=2984040181942278987 2025-02-27T20:41:41.973191Z DEBUG lightyear::client::prediction::prespawn: found a client pre-spawned entity corresponding to server pre-spawned entity! Spawning/finding a Predicted entity for it 2984040181942278987 2025-02-27T20:41:41.973207Z DEBUG lightyear::client::prediction::prespawn: re-using existing entity 2025-02-27T20:41:41.973218Z DEBUG lightyear::client::prediction::prespawn: Added/Spawned the Predicted entity: 456v5#21474836936 for the confirmed entity: 457v1#4294967753 2025-02-27T20:41:41.974191Z DEBUG lightyear::client::prediction::rollback: Rollback check: mismatch for component between predicted 456v5#21474836936 and confirmed 457v1#4294967753 on tick Tick(983) for component "bevy_transform::components::transform::Transform". Current tick: Tick(996) predicted_exist=false confirmed_exist=true. Why? It is weird that even tho my pre spawned predicted entity gets spawed with a transform it says there isnt any

unkempt sedge
#

Oh found the origin

unkempt sedge
#

commands.spawn((bullet, prespawned)) it was literally this line of code, the reason I have no idea, but I believe is correlated to bad syncing

digital cedar
pine cape
#

Also prespawning wouldn't reduce the bandwidth, if that's what you're interested in. The component still needs to be replicated

misty wyvern
#

Just my two cents after finally getting a more serious look at lightyear:

I love the fact that you're mostly not (or maybe none at all?) relying off macros, this makes things more clear when looking at a protocols.rs (which I recommend having), not a fan of magic, so bravo!

However, there's a flip side to that. When I'm looking at a component's definition, for example:

#[derive(Component, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Moveable {
    pub velocity: Vec3,
    pub angular_velocity: Vec3,
    pub collision_shape: ShapecastMoveableShape,
    pub collision_mask: LayerMask,
}

There's no clear way to know if this is a replicated component or not without looking at protocols.rs

I don't know what the solution is to this, is it really a problem? ehhhh at the end of the day probably not, but just food for thought

wicked tulip
wicked tulip
wicked oak
#

? I Already fixed

unkempt sedge
#

Even go further and auto insert it for you, but seens a little overreachy

misty wyvern
#

Yeah definitely overreachy

pine cape
wicked oak
#

Xd skill

wicked oak
#

Iam Also worried about bevy update and peri abandon the project you know

#

But i made a plugin that call the others functions so If i need implement a New network i just need Deal with this plugins and not modify the wholeeee system

unkempt sedge
#

God lord, finally found out the cause of my rollback on spawn bug

#

Animation component require transform...

#

He inserted it before the prediction set could dot it is thing

#

Got rollback

wicked tulip
misty wyvern
#

Does anyone know if there is a way to explicitly exclude an entity from rollback, I'm trying to find the source of extreme jitter/corrections on a non-replicated entity, kinda shooting in the dark here

#

sorry, to be clear, it looks like they're being corrected

#

because they should be moving about 1/4 of that speed, sometimes it looks fine but its really rare

#

Or better yet, how do I know I'm currently being corrected/in the middle of a rollback? is there a resource or something I can access

long marsh
misty wyvern
#

nice, also I just found the Rollback resource

long marsh
#

perfect was typing that

misty wyvern
#

yeaaaaa this fixed it:


    let rolling_back = rollback.map_or(false, |r| r.is_rollback());

    for (entity, mut simulation, mut transform) in simulations.iter_mut() {
        // If we're in a rollback AND the moveable is not predicted, skip it
        // otherwise it will move multiple times in a frame and we dont want 
        // that for non-predicted moveables
        if rolling_back && !predicted.contains(entity) {
            continue;
        }
misty wyvern
#

Wellllll now its acting up again, oof im tired lol

#

I think its a separate issue, ignore me

#

yeah ok similar issue, timers were being ticked in rollback too, so thats fixed now

wicked tulip
long marsh
wicked tulip
long marsh
long marsh
#

i thought so

#

the status postfix on that name is not my favorite for something that has to be user-added

wicked tulip
#

Thank you, was hoping that would fix the jitteriness of my predicted pysics based bullets, but they are still very jittery

long marsh
#

or just jittery

wicked tulip
#

Its strange on the client side it looks like no interpolation is applied at all

#

(or rollback correction)

long marsh
#

yeah it just looks that way when it's constantly rolling back. i think if correction was 100% perfect and the rollbacks were due to very small differences, it would look seamless still, but i think there's some goofiness somewhere that makes it jittery in the perpetual rollback case

i would focus on fixing the rollbacks

#

or if you aren't prespawning the projectile, you will always get rollbacks when you spawn a predicted one

wicked tulip
wicked tulip
#

Do you mean you always get rollbacks if you prespawn the bullet?

long marsh
#

if you dont prespawn it (because the history needs backfilled)

wicked tulip
#

yeah I prespawn...

long marsh
wicked tulip
long marsh
#

what do the logs say about what component is causing the rollback

wicked tulip
long marsh
#

either set the LogPlugin to have a log level of debug or set the RUST_LOG environment variable to debug

#

might pipe that output to a file too, there will be a lot 😅

wicked tulip
#

Ok I get an output I don't fully understand:

Predicted entity Some(85v1#4294967381) was not found when preparing rollback for "lightyear_experiment_main::protocol::Weapon"
#

(the weapon is spawned on the player, and I would expect it would be simply synced to the client?)

long marsh
#

haven't encountered that! are you getting rollbacks before you spawn the projectile? or is it fine

#

that's confusing because, looking at the code, it implies there is a Confirmed entity with a reference to a predicted Entity that doesn't exist lol

wicked tulip
#

no, before bullet spawn all is fine

#

pretty sure I did something wrong, but not sure what yet

long marsh
#

is Weapon the only component the logs suggest need rolled back? or is it trying to roll back like everything that is sync'd?

could be as simple as the state of your prespawned entity just isn't the same as the state on the server

wicked tulip
#

I resgistered the component in the protocol, and then add it when I spawn the player character.

#

The weapon is spawned on the server (so not prespawned)

#

when the player connects I spawn the player and add the Weapon Component to it.

#
app.register_component::<Weapon>(ChannelDirection::ServerToClient)
        .add_prediction(ComponentSyncMode::Full);
#

thats how it registered in the protocol.

#

Its also not just at the beginning but constantly

#

Is there anything else needed?

long marsh
#

you get that error without spawning a projectile?

#

like it's happening as soon as you spawn your player

#

and then happens forever?

wicked tulip
#

Only once the first bullet gets spawned

long marsh
#

thinkfused just to be clear then... so after you fire your first projectile, the predicted entity for your Weapon goes missing? lol

wicked tulip
#

Yes, its very confusing, here is the repo if that might help.

#

Feels like something obvious is missing, but I just can't find it

long marsh
#

are you using main branch lightyear?

#

cargo has your local one

wicked tulip
#

Let me know if you can spot anything obviously wrong

long marsh
# wicked tulip https://github.com/Occuros/lightyear_rollback_investigation

spent some time looking through the logs. the initial rollbacks were getting triggered by ComputedMass being different, so i just took it out of the protocol (which, makes sense to me, it's computed!) and they stopped rolling back

i didn't test it too much tho; can you try / what do you think about that?

#

you are also rendering your confirmed bullets btw

#

which might be adding to the confusion here

wicked tulip
#

and THANK YOU!

long marsh
#

yeah i am not sure why replicating that is an issue since it should end up the same anyway

#

no problem

wicked tulip
#

I agree that its computed and doesn't need to be synced (unless you plan to change it freequently) but still confusing

#

Ok this is creating more questions in my head than answers, but that is really good news

#

It is finnally SMOOOTH broovy

wicked tulip
#

Ok there is one last issue remains is that as soon as there are any collisions there are continuous rollbacks.

And when that happens everything is jittery again, as it seems rollback on every frame brake it again 😭 (no matter what I use for the correction_ticks_factor).

No idea why it creates also issues with the physics mass sync, but will be interesting to see if that persists once we have resource syncing.

unkempt sedge
#

We already have rollbackable resources i think

misty wyvern
#

How can you check how often you're rolling back?

#

Curious about this

wicked tulip
wicked tulip
misty wyvern
#

Thank you, and does lightyear have a way of displaying ping anywhere?

#

you know what, i should dig at the examples first lol

#

Hmm ok so it seems like I get rollbacks every frame whenever I move

#

despite it being very smooth

#

I take it that's not intended?

#

Oh maybe it is:

Sync the component from the confirmed to the interpolated/predicted entity with the most precision Predicted: we will check for rollback every tick Interpolated: we will run interpolation between the last 2 confirmed states

misty wyvern
wicked tulip
misty wyvern
#

It looks like its not being visually interpolated

#

not saying thats what it is, but definitely looks like FixedUpdate jitter

misty wyvern
wicked tulip
#

But in theory there is the correction smoothing function which should interpolate from the rollback.

pine cape
pine cape
misty wyvern
#

iiiiinteresting, ok I can look into whats going on then

misty wyvern
#

I dont think I understand whats going on here, this should be sending updates to the client, right?

app.register_component::<CurrentWeaponIndex>(ChannelDirection::ServerToClient);
#

Then I have this query:

    mut query: Query<(
        Entity,
        &UniqueIdentity,
        &Transform,
        &mut WeaponInventory,
        &CurrentWeaponIndex,
        &ActionState<PlayerInput>,
    ),
    Or<(With<Predicted>, With<Replicating>)>>,
#

But it doesn't seem to find anything when CurrentWeaponIndex is in there

#

Is it because of the Predicted component?

#

I'm seeing two player entities 🤔 one has the CurrentWeaponIndex, the other doesnt, but both are Controlled, and one is Predicted. hmmm ok

#

ok so that means I basically need to predict everything, at least in the context of what im trying to do. Interesting

#

oh ok I know what to do

#

I get it

brain expanding noises

misty wyvern
#

@pine cape there's something really funky going on, so check this out, its working fine here (note the rollback count top left)

#

But sometimes its constantly rolling back (trying to get a video)

#

Ok I restarted the client several times and it was fine, then I restarted the server and now its not fine:

#

important to note that the link conditioner is on

#

It's like as if the server sometimes boots into a bad state, usually its continuously rolling back, but every once in a while it appears to boot into a good state

I've checked everything, I've gone back to what I know is a more deterministic movement and yet its still doing it

#

I have pushed these changes to sixdof in main (Use TAB if you want to toggle the mouse on and off @pine cape )