#archived-networking

1 messages · Page 53 of 1

jade glacier
#

Personally from my experience with this stuff, you should get a full stack happening as soon as possible, so you can connect your game to something

#

that is going to expose a zillion flaws in your whole networking plan and force multiple refactors of all kinds of things anyway

#

Which is really annoying if you overengineered some part of the stack and it ends up needing major changes.

weak plinth
#

Apparently when you allocate memory, it's not empty

#

Could have saved myself about 2 hours knowing that beforehand

#

Makes sense in hindsight....

#

(With empty I mean, zeroed)

#

Could you (once again) suggest me how I can make network placeholders in my game for my inputs @jade glacier

#

I was thinking of making blittable structs for inputs, and storing them locally in a 1-deep queue or something and immediately using them again in the same update

#

Then once I add remoting, I can use that queue for network IO (indirectly)

jade glacier
#

Do inputs need that kind of blitability for what you are doing?

#

Typically I just pack them and unpack them normally into wherever you are keeping your buffers

#

The one deep queue sounds bad though

#

I would worry not so much about that structure of them so much for that, but rather the actual handling of your buffers, that's going to be way more critical to things actually working

#

When you say Queue I assume you mean an actual Queue container type, which I dislike for this, since it has terrible handling for missing and out of order packets

#

Though its not unheard of, you just end up tossing any out of sequence packets, since they will break your entire container mechanism

#

For the non-zero memory - for all of my stuff with the ring buffers I try to avoid clearing memory, so I rely a lot of my BitArray and masks to keep track of if a buffer is valid or not, since with ring buffers all of your old data is still there when you comes back around. @weak plinth

weak plinth
#

If I'm sending inputs over network, I want them to be blittable, yes

#

I'm totally unfamiliar with handling out of order packets and such, I have no clue how to handle lost or out of order packages currectly

#

As for my bitstream, it's almost finished. I have a few ideas up my sleeve to make serialization go more smoothly still

#

I also don't know if I should handle all packets in one place, or segmented across the app where they are consumed and created

#

What's your advice on this??

#

Also I will post you my code when I have a first version. Maybe parts of it are useful for you.
I solved my non-zero alloc by simply setting the ulong to 0 if the localoffset is 0. Aka the first time a new long is used. With overflow, the ulong is set to the value anyway

#

I'm working with a ulong* btw. Not managed memory

#

I used a mix of Fholms bitbuffer, FSE's bitbuffer and some stuff from the internet, and added my own as I needed

jade glacier
#

The reason I am wondering about blitable for inputs, is inputs largely tend to be things like key states, buttons states and possibly other commands

#

which all are going to become masks or bitpacked single bit entries

#

Joystick axis and mouse will be the rest of it. Joysticks you will likely want to compress way down, to like only a byte per axis... or whatever. So its not going to line up with your raw memory unless you are aligning all of that already as cast down values and masks.

#

and yeah, once you go with pointers for your byte[]... then may as well work with ulong*, lets you avoid multiple passes for writes that cross over the byte line.

weak plinth
#

@jade glacier
I also don't know if I should handle all packets in one place, or segmented across the app where they are consumed and created
What's your advice on this??

Have any tips on this?

jade glacier
#

Do a the opposite of what mirror does. Don't produce your serialization ad hoc. Create a primary update manager and have that generates callbacks for every timing step

weak plinth
#

I don't follow?

jade glacier
#

Too hard to explain typing on mobile, sorry

weak plinth
#

No problem

solar garden
#

How would you go about client side but for the other players ? picture this for the client on his view its eazy just use the same inputs you sent to the server but for the other players in this same simulation how do you predict their movements so that you dont shoot at where the enemy was ? because when you ask to shoot to the server it will go back in time to see where you were at that time but if your simulation is wrong anyway you will just shoot someone that isn't there right ?

#

do you even ask the server to shoot if you send inputs ?

#

yes of course you do because else you will have delayed gameplay but still what about the client side prediction ?

vernal relic
#

Could anyone help with a problem regarding collision detection latency in PUN 2?

weak plinth
#

@solar garden I think you can interpolate if you send along the tick at which the input was made

#

But I'm no expert at all on this. I could very well be wrong

jade glacier
#

@solar garden All depends on how you decide to structure your authority

solar garden
#

I went with server authority with clients catching up to the server

jade glacier
#

"Favor the shooter" is the typical practice... how you enforce that and with how much hack-proofness comes down to the level of complexity and CPU drag on the server you are willing to accept

#

Then the server sends out states of reality, and if it doesn't match the clients history of what it thinks it did, the client has to get back in agreement

#

typically that is done with a rollback and resim on the client

#

Client collects inputs and stores those in a buffer and sends that input buffer to the server as well

#

both simulate using those inputs

#

The server sends out its resulting state and frame ID to all

#

if that resulting state is different than what the client had gotten, you are desynced and the client needs to correct

solar garden
#

Uh you mean you dont set the position each frames but only if there is desagreament with what the server sent ?

jade glacier
#

You set the position on all non-authority versions over the network... EXCEPT the owner

solar garden
#

But the other players in your simulation dont have a input buffer you will suffer lag for other player in your sim

jade glacier
#

the owner is predicting, so you don't directly apply server states to it

#

The player lives in the future

#

So your current state as a player is always different

#

What you are checking is for agreement on history

#

You don't know if what you are doing currently is legal because you have some 100ms before you will know

#

The entire system involves inputs -> prev state -> new state

#

So if you detect a disagreement in previous state results locally vs the server... you have to rollback that many ticks... change your state result values to the servers... and then resimulate back forward to get where you most likely are now

solar garden
#

Ok so thats for shooting but what about other players in your sim you dont have input buffers for them so you will only apply what the server sent you for their position right ?

stray scroll
#

Is it sufficient to send a random uint as token to the client to be able to connect in a lets say 10 sec timeframe? x) Asking for a friend. No, but I have a login that finds a lobbyserver that is empty, asks it for a slot, and then tells the client to connect to it.

vernal relic
#

How should I handle collisions between projectiles and players effectively in PUN 2? I have tried letting the player who gets hit determine if he was hit and then telling the projectile to destroy itself through PhotonNetwork.Destroy(). The problem is that only the client who owns the projectile can do that which creates a lot of latency since I need to call an RPC or transfer ownership.

weak plinth
#

@jade glacier Could you, if you have time, elaborate on what we were talking about earlier?

#

And if you can, an example? I'm having trouble visualizing it properly

#

Suppose I have a Player GO, that "creates" inputs. I make structs from those inputs, buffer them, apply them

#

Do I create and consume the structs/buffers all within the Player GO?

#

Or do I use some centralized System that does this?

#

Also, I assume I need some network ID to determine which networked object is making the input/consuming the input?

jade glacier
#

Basically just make an update manager, and break down the timings a bit more finite than just Update and FixedUpdate

#

The player GO creates inputs?

#

Inputs can be a couple things, but generally your connection creates inputs, unless you have multiple players of course

#

So your update manager creates the timings... PreSimulate, Simulate, PostSimulate, Snapshot, Interpolate, and such

#

The idea is to defer everything into very specific timings, and do all operations in response to that timing callback

#

rather than everything trying to do a bunch of shit in Update and Fixed

#

The master manager will say "Capture all of your current states"... and "Serialize your objects to this frameId" etc

#

Trying to explain it all is more than I care to do here, but that is the whole of what is going on

#

just make more discreet timings than just Update and FixedUpdate, and make your own callback system for them

#

@vernal relic There is no easy answer to that, since that kind of thing in a relay environment is one of the harder to really make right. I handle that personally by having the shooter still call the hits. Hitscans and projectiles on the shooter side produce a NetHit that I send, and that carries info about who the shooter says it hit, and other info like collider indexes or hitgroups (for things like crits etc)

#

The owner of the hit object then applies that NetHit to its vitals when it gets that message

#

Since the one getting hit has authority over their health, but the one shooting has authority over the projectile/hitscan

#

I'm actually working with Exit right now on a Beta of a whole drag and drop component system for PUN2 that handles that stuff. This was a test connecting through a tethered phone in Mexico to EU servers, so you can see how the latency from hits to the targets takes a bit to show the health change to the shooter.

#

Ignore some of the movement bugs

#

@weak plinth What you are asking about I think depends on what your inputs are. If they are actually events that are generated by specific owned objects, then you will need some kind of ID yeah. For most inputs you want to avoid that abstraction if you can.

An input though is any non-deterministic thing that is applied to a simulation. It is anything that the simulation needs to know in order to produce the next state tick.

weak plinth
#

How so? I need to also apply this input back to there it comes from, no?

#

If I have a deterministic model, and I tell the player to "go forward"

#

I will need to apply both input and network it both

#

And in the case of multiple players, you'd need to know what player entity created the input

#

@jade glacier Perhaps you know of a term I can google? Or some schematic that explains it?

#

That would really help

vernal relic
#

@jade glacier Ahh yes, thank you. That way the latency influences the updating of health rather than the actual collision.

#

Quick follow up question: Right now I use RPCs to send data from an instance of a PhotonView to the owner, is there a better way to do this?

jade glacier
#

@weak plinth Its just an Update manager

#

but you use it to produce more specific timings as you need them

#

You won't have an immediate need, because as you start you won't notice the need for deferring actions. Its when you start getting tied in knots because of order of exec that you will want to start manhandling everything in very specific timings.

In this conversation, its more about producing one call that kicks off all serialization.

#

For example, you have one chunk of memory, and you want everything to bitpack into that...

#

Its nice to be able to call one "SerializeEverything(byte[] myBuffer)

weak plinth
#

I'm not so worried about the serialization/network IO

jade glacier
#

than have them all at oddball times trying to do that

#

but it applies to all parts of having a simulation

weak plinth
#

More as the handling of the packets, network messages formatted in struct form

jade glacier
#

Its sounding more complex than it is

#

you want an update manager

#

and from that create more detailed timings

weak plinth
#

So to give an easy example with this update manager

#

Player clicks shoot

#

Then what? I ask my update manager for the correct input ?

jade glacier
#

so you areNT stuck with arbitrary Update and FixedUpdate calls all over firing in random order

weak plinth
#

Or does my player create it and send it to the update manager?

jade glacier
#

Player clicks shoot... nothing happens

#

At the stop of every update in your update manager, you have a "Capture Inputs" callback

weak plinth
#

🤔

jade glacier
#

anything that captures an input into a struct buffer responds to that by capturing inputs

#

Player clicking would actually just be a Queue'd event

weak plinth
#

How would I "capture" an input?

#

Queued event?

#

Why not a queued input?

jade glacier
#

if you are doing it yourself, and we aren't talking using Input.xxx

#

the input isn't complete yet

#

the input struct is EVERYTHING that player has for an input for that tick

#

so if I click... and move forward with w on that same tick....

#

I don't want to try to create an input struct twice

#

the input struct is the collection of all inputs for that tick

#

So all of the inputs queue up as the user produces them

#

UnityEngine.Input already is doing that for you

#

at the start of update you can poll all of the keys for events and produce a struct from that

weak plinth
#

I am so confused by this

jade glacier
#

The player hitting the W doesn't "make" anything happen in your code

weak plinth
#

What's wrong with creating 2 input structs?

#

I can serialize them to one buffer and network them, no?

jade glacier
#

you are going to create a struct for every key and every mouse axis?

#

Its pointlessly messy, but sure

weak plinth
#

For every input to the sim, yes

#

That was my idea

jade glacier
#

you can do whatever you want... this is programming 🙂

weak plinth
#

I know, but I want to know what works

jade glacier
#

The struct is the definition of what is being sent to the server every tick

#

You populate that ideally in one shot... on your "Capture inputs" callback

#

that struct is what you store locally for local simulation and for rollback simulation as needed

weak plinth
#

But aren't these queued events essentially going to be the same?

jade glacier
#

Sure

weak plinth
#

I have a Move input with a "forwards" flag

jade glacier
#

But the point is to produce sanity

weak plinth
#

Or something

jade glacier
#

and not madness

#

adhoc timings of things always turns into a buggy mess

#

so best to have your input generation separate from your input capture

#

inputs can be generated at oddball times, so you just add them to your collector or whatever you want

#

and when "Capture Inputs" fires prior to each Simulation...

#

you convert all of that queued up garbage into a pristine input struct

weak plinth
#

So I queue "inputs" to the update manager

jade glacier
#

That struct is what goes into your simulation

weak plinth
#

Once per frame collect all of them

#

And apply/network?

jade glacier
#

Collect them wherever and however you want

#

you can make that as messy as you like

#

but what you want is a clean and simple resulting struct once order to produce one

#

So it may collect Input from unity, some queue'd events from timers... god only knows what

weak plinth
#

But how can I keep any form of order to the input structs if the input struct is any random combination of "input events"

jade glacier
#

But you want/need to produce before your simulation one definitive "input struct" for that tick

#

"CaptureEvents()" as a callback that fires right before Simualtion will tell any of your code that is accumulating inputs to put all of their values into that new struct

#

There is no hard rule on how to do this, the only thing that matters is that you are producing a buffered input struct

#

that you can send to the server, and that you can recall later for resim

#

Inputs[X] -> State[X] = State[X+1] is the backbone of everything

#

So you just need your inputs to be sane

#

Whatever they may be

weak plinth
#

I'm really trying to wrap my head around what you are explaining

#

But I don't see how you can "collect" various of these input events into ont input struct

stray scroll
#

Anyone got any input on this? I have a client that connects to Login server that forwards it to a lobby server. I authenticate the client when connecting with username password, and then want it to connect to a lobby. The login server connects to a lobby and asks for slot for client, which replies with sure/no and a connect key (uint). The login server then forwards this and IP, port to the client. Now the client has X seconds to login until it becomes invalid. Is this ok enough? Or how many bytes of a key would I need for it to be ok? 😛 Or how would a better approach be?

jade glacier
#

A CaptureEvents() callback just is the way to close the door on the last set of inputs and say "Whatever has happened, is now the inputs for frame X, anything after this is frame X+1"

weak plinth
#

As you can have dozens of these input events that can all come within various combinations

#

I mean, are you sure you aren't talking about a buffer that contains these inputs serialized?

jade glacier
#

It can be whatever sure... the main thing really is just that you collect them into a buffered in such a way that you can network it, and reuse it for resimulation later.

weak plinth
#

I'd see Inputs[X] as a collection of all inputs that occured within the last frame

jade glacier
#

yeah

#

How that is structured is totally up to you

weak plinth
#

So, hear me out here

#

If I have a Move struct

#

And a Shoot struct

#

I can "generate" them both, send them off to the input manager

#

Throw them both into one buffer, and send them off

jade glacier
#

What if you shoot a second time in that same tick?

#

Or you don't shoot at all?

#

As long as the manager is handling that when its time to produce a final "this is what gets sent to the simulation"... its all good

weak plinth
#

The latter wouldn't generate this input, nor serialize it

#

But the first, I don't know 🤔

#

How can you shoot twice in the same tick?

#

And what IF you do that?

#

Do you apply the latest one only?

#

Or what?

jade glacier
#

Up to you, the only point is to make it sane

weak plinth
#

Ok, ok

#

I think I'm getting a mental picture of this

jade glacier
#

you want a resulting struct that isnt a timebomb of cross logic and shit

weak plinth
#

And how about "prepping" for multiplayer. I have SP now and I want MP in the future

jade glacier
#

If missing this, then use that, but dont do that unless this other thing

weak plinth
#

Do I just apply what comes out of the input manager to my own sim?

jade glacier
#

yeah, that is the goal

#

you produce an input struct that you feed to the sim

#

its the same struct the server feeds to its sim

#

You record the state results locally in your buffer

#

The server produces its state results and sends that out...

weak plinth
#

And one last question (I swear), how does the input manager know where to send the state results?

jade glacier
#

and the owner checks that incoming state later against its history to ensure the server and it are in sync

#

The player in this case isn't sending state results

#

But if you want to, it would be when you send that frame out

#

My stuff I just put my input struct at the front of my packet write

weak plinth
#

No, I mean, locally

jade glacier
#

Since I have mixed authority

weak plinth
#

When I get back the state

#

How does it know where to send the state?

jade glacier
#

You don't need to store that really

#

but it should have a frame number

weak plinth
#

I need to apply it somehow

jade glacier
#

that you can corelate to your local frame number for that tick

#

I personally send out two frameIDs from the server on each pack

weak plinth
#

This state can be a lot of data, no?

#

Every change to the sim is in there

jade glacier
#

OriginFrameID and ServerFrameId

#

its an extra 6 bits

#

for a lot of ease

#

The player sends the tick with its local frame ID

#

and the server sends back the state with that local players frame ID for the frame state being sent

#

So I just check when it comes in for any objects I own, and do a check of those states against my history using that frame id

#

owner -> frame 6 inputs -> server buffer -> server simulate consume players frame 6 - > server state -> state sent to player with originFrameId = 6 -> owner

#

Sever states can get pretty big yeah

#

@stray scroll I have done like zero work in regards to that stuff, so I got nothing for you on that front.

weak plinth
#

And a state contains everything that changes due to the input, yeah?

#

So stats changed, like hp

#

Or positions changed of enemies/players

jade glacier
#

yeah, the state is the result of the simulation

#

PhysX in unity is a good way to think of things

#

FixedUpdate = PreSimulation

#

You put in all of your inputs to PhysX there before the next sim tick. AddForces and such

graceful zephyr
#

s' = f(s, i)

jade glacier
#

There is no PostPhysX tick... cuz unity suck

graceful zephyr
#
s' = new state
s  = old state
i  = input
f  = simulation logic
jade glacier
#

That would be the more techy and correct way of saying my Inputs[X] -> State[X] = State[X+1]

#

morning @graceful zephyr

#

late evening

graceful zephyr
#

zup

#

@jade glacier whats up

#

@weak plinth if your sim can not be expressed in this format, u gonna have a bad time networking it

#

or well, you can do it different ofc

#

but if you look at like classic fps networking sorta suff

#

you need this, or some variant of it

#

to make it tight

jade glacier
#

Finally rolling on turning all of my stuff into a beta for Exit, seems Christof actually had given the go ahead a while back, but I thought we were still waiting on paperwork and approval. Doh.

#

@graceful zephyr

weak plinth
#

I'm going to have to really think about this and draw some basic designs I think

jade glacier
#

Simulation architecture is everything really

weak plinth
#

I'm not sure how to apply this principle to a local game

jade glacier
#

Which is why I forehead slap so much on people jawboning "the perfect transport" or "perfect serialization" so much

weak plinth
#

Perhaps I shouldn't do anything more than create states and consome them until I go networking with a remote state

jade glacier
#

You can write your entire networked game before adding a single line of actual network messaging

#

Start clean and simple

weak plinth
#

I'm not sure where I'd get my sim logic and state from locally

#

Should I even bother with this?

jade glacier
#

Define your input struct(s), define your simulation, and define your state result struct(s)

weak plinth
#

Locally that is

jade glacier
#

The sim is your game

#

Player hits keys -> The way things were -> the way things now are ... your entire flow ideally doesn't become too much more complex than that

graceful zephyr
#

i should write a book

jade glacier
#

The numbered ticks are what keep that sane

#

and deferring like mad

#

defer everything

#

A proper networking book would probably sell reasonably well

#

Everyone is always looking for a good new "Bible"

graceful zephyr
#

ehhh

#

maybe

weak plinth
#

I should see if I have time tomorrow to draw some designs

#

To get this straight in my head

graceful zephyr
#

there's very little to draw

#

tbh

jade glacier
#

start super basic is all

graceful zephyr
#

your simulation is a function, your state and input are the parameters for the function, and the function produces the new state

jade glacier
#

Make a very basic tick based simulation

graceful zephyr
#

each state is assigned a tick number

jade glacier
#

Just use FixedUpdate() for your timing for starters

#

Later that will be replaced by your networking update manager

#

But the concept is the same

weak plinth
#

your simulation is a function, your state and input are the parameters for the function, and the function produces the new state This is really helpful information

jade glacier
#

That ties back to why your own update manager is important

#

You need callbacks for pre and post that simulation, and Unity timing will fail you for that

#

With your own update manager you would only have one FixedUpdate in your whole system....


public class MyUpdateMan : Monobehaviour {
     FixedUpdate(){
          PreSimCallback();
          Simulate();
          PostSimCallback();
     }
}```
weak plinth
#

What what does pre and post exactly do?

graceful zephyr
#

nothing

#

really

jade glacier
#

Those are your calbacks where you will do things like capture your input structs, or serialize and such

#

Your simulation's job is to produce and consume inputs and states

#

Messaging <-> Buffers <-> Simulation

#

Messaging and simulation never touch

#

Messaging "transports" inputs and state buffers between clients.... Simulation produces and consumes those inputs and states

#

The idea is to keep that nice an separate

#

There are other parts to this, the nitty gritty stuff that fholm makes a career of - in dealing with all of the mess the internet makes of the simplicity of this

#

There is a lot that goes on in the <-> above, which is the magic of networking

#

Prepare for incoming knowledge bomb

gleaming prawn
#

Lockstep:

input[n + delay] = localPoll;
send(input[n + delay]);
receive_inputs; // either from server or others in P2P
if (has_all_input[n])
  s[n+1] = f(s[n], i[n]);
#

Deterministic Predict rollback:

#
i[n] = localPoll + prediction; // prediction is for remote players
send(local_i[n]);
receive_input_confirmations; // either from server or others in P2P (let's assume we received tick k < n)
if (confirmed_i[k] != predicted_i[k])
  rollback_and_resimulate(s[k] to s[n]); // this should start over from k, resimulating every tick until n to fix, and prepare for...
// now simulate next without the IF
  s[n+1] = f(s[n], i[n]);
#

Might need some editing...

#

Let me think snapshot interpolation and state transfer

weak plinth
#

How do you know which one to choose

#

Especially considering my limited knowledge

gleaming prawn
#

It's the game that tells you which one to use... Not your preference... (more or less)

#

Fighting games, (most) brawlers, twitchy games with lots of shared physics = predict rollback
RTS, Tower Defenses = lockstep (general rule)

#

competititve FPS, with small modifiable state = snapshot interpolation (simple, efficient)

#

survival, battle simulation = state transfer (normally)

#

I'm being VERY VERY simplistic here...

weak plinth
#

How about action rpg games?

gleaming prawn
#

Of course you can build a twitchy game with snapshot interpolation (but with a lot more work than with det predict rollback)

#

And opposites are also valid...

weak plinth
#

these things like diablo?

#

Do those fall under the "twitchy" category?

gleaming prawn
#

These are normally good with either det predict rollback or state transfer

#

being deterministic predict rollback easier for the game developer (and it comes with more "tooling" for "free"), I'd choose that

graceful zephyr
#

diablo is a weird mix of determinism and non-determinism AFAIK

#

or well 2 and 3 are

gleaming prawn
#

state transfer is also a lot more expensive to maintain

#

yeah, but I'm saying IMHO I'd today choose det predict rollback to do something like that...

weak plinth
#

Ok, I will keep that in mind

jade glacier
#

The choice as far as I understand it comes down to how deterministic things will be, and how you have to sweep latency under the carpet for the different types. Like a fast moving FPS is going to feel better if you let the player just predict and work around the desync with giving the shooter special privileges. Deterministic systems are going to involve a lot of resim, extrapolation or induced input latency to hide the internet.

gleaming prawn
#

Let me see if I can define the functions for snapshot interpolation (there are several variants of things you may add, like local prediction or not, lets stick to the old old Quake 1 version of it):

jade glacier
#

If your game is all non-deterministic stuff.. like its ALL about flinchy player movements, deterministic is going to probably be more work than benefit.

weak plinth
#

I mean, I suppose it's also about quality of sim right?

gleaming prawn
#

flinchy player movements has nothing to do with being determinstic or not

weak plinth
#

In non-pvp games there's less requirements for accurate sim?

jade glacier
#

The player movements though will always be mis-predicts though no? meaning constant resims?

gleaming prawn
#

Determinism has to do with the algorithms/data types you use and the machines you run

jade glacier
#

All for no benefit

gleaming prawn
#

Yes, there are constant resims, yes

#

That's the nature of predict rollback

#

but YOU as a game developer doesn't need to be aware

#

That's the MAGIC

#

🙂

jade glacier
#

for sure, I am saying if your game isn't loaded up with deterministic stuff, like a tower sim with 100s of AI... and its mostly just twitchy players...

gleaming prawn
#

It's NOT more work

jade glacier
#

then there isn't much determinism there to really make that worth it

gleaming prawn
#

It's A LOT less work for you as a developer

#

IF you have a deterministic framework

#

I think you are confusing things

jade glacier
#

yeah, what you guys have with Quantum makes it pretty easy for devs from what fholm describes

gleaming prawn
#

Determinism has NOTHING to do with the player making random inpiuts

jade glacier
#

I get that

gleaming prawn
#

You are confusing two different concepts

jade glacier
#

I think you might be misreading me

gleaming prawn
#

Twitchy games are all about Random input

#

Do you know that even engines that use state transfer and snapshot interpolation are trying to move to determinism (to a certain degree)

#

and this is completely unrelated to

jade glacier
#

For sure, I use it all the time where I can find it

gleaming prawn
#

player input being "predictible" or not

#

This is misleading:

then there isn't much determinism there to really make that worth it

#

determinism is YOUR code + data, not what the player does

#

It's exactly in crazy twitchy games that deterministic predict rollback shines

jade glacier
#

By that I mean you are changing your entire system to an extrapolative deal to get the player into the same timeframe as the world around it, and go in into regular resims and such to make it happen

gleaming prawn
#

Well, ALL networking system do that now

#

EXCEPT lockstep

jade glacier
#

Put the player into the present?

gleaming prawn
#

All modern solutions use a form of prediction/extrapolation

jade glacier
#

For all of my traditional stuff, the player always lives in the future

gleaming prawn
#

otherwise they would be waaaaay too slugish

jade glacier
#

The player is predicted locally, so they are out of sync with the world around them

#

The world the player sees is history

#

Or some hybrid

gleaming prawn
#

And you also extrapolate other players

jade glacier
#

since like Overwatch does blend a bit

gleaming prawn
#

The different between determinstic and non deterministic is VERY simple:

  • det: with confirmed inputs, rollback and resim (low bandwidth);
  • state transfer: correct with confirmed state
jade glacier
#

How much do most of the modern major titles actually extrapolate the world state on clients?

graceful zephyr
#

generally for overwatch style games you show the other players in past time, and your predicted state in future time

#

it's a weird thing

jade glacier
#

My impression was little to none

gleaming prawn
#

And this is why everybody is pursuing determinsm (in case of state transfer, local prediciton is more accurate)

graceful zephyr
#

where SOME things, will be at say tick 100 , but some of the OTHER things will be at tick 105 (like your player, the grenade you just threw, etc.)

gleaming prawn
#

But you extrapolate other things @graceful zephyr like Projectiles

graceful zephyr
#

depends in what context

jade glacier
#

From the OW video it definitely sounded like they blended and blurred the lines as needed

graceful zephyr
#

its not which thing it is, its if its something you should predict or not

gleaming prawn
#

Yes, the reality is a lot more nuanced

graceful zephyr
#

mostly you predict your player + your rockets/grenades/abilities/etc.

#

but not the remote players or their stuff

gleaming prawn
#

what I said is modern solutions all use prediction/extrapolation (at least partially)

#

AFAIK, current unreal networking does send remote player inputs for local prediction of others as well (not sure how much of it they do)

jade glacier
#

I personally for the PUN2 stuff I am making and doing zero attempts at extrapolating the surrounding world as a whole. I am only taking advantage of deterministic stuff like projectile vectors to blend as needed.

#

Other players and such are purely interpolated right now. Might try to introduce some extrapolation options though, but this is PUN2 still... so not dealing with the most robust environment for that without server logic.

gleaming prawn
#

With PUN2 you need to use one of the clients as authority anyway

#

Most common I see is the shooter...:)

jade glacier
#

Its all mixed authority, I only use the Master as authority over world items

gleaming prawn
#

because it somehow resembles favor the shooter mechanics, in that you use what the shooter saw as the decision

#

master for world

#

maybe the target machine for rockets, etc

#

Glad that's exactly the kind of thing I don't have to worry about...:)

jade glacier
#

but like if you shoot someone... the projectile has the authority of the shooter. On impact it generates a NetHit event from the shooters side. The Shotee applies that hit to its vitals once it gets that hit message... Not at all hacker resistant.

#

its PURE favor the shooter

gleaming prawn
#

yeah

#

Do you know battlelands Royale?

jade glacier
#

I haven't played it, but am familiar

gleaming prawn
#

mobile 2D top down shooter

#

It was originally made with PUN (40M downloads game, etc)

#

Devs are super good, made an excellent work with network culling to make it play fine with 32 players, etc

jade glacier
#

Oh god... the hackers must have been like mosquitoes on that

gleaming prawn
#

But then after 1.5 years, they started to hit the walls

#

Hackers are less prevalent than you might think (it's something like 0.5% of players)

#

but that was ONE of the concerns

jade glacier
#

Mobile I am sure makes them less common

#

But you can man in the middle that so easily

gleaming prawn
#

But these kind of things you are doing, they had to come up with solutions, etc

#

And you always have the undesired effects of: I turned the corner, why did I die

#

etc

jade glacier
#

I find it kind of fun to work on, the relay really makes you purify your thinking since everything is a one way convo

gleaming prawn
#
  • difficult to implement physics based weapons (like a grenade that bounces walls)
#

THEN, lol...

#

THey re-wrote the game... In Quantum...

#

And now you can dodge rockets in the game...

jade glacier
#

I am talking with Tobi about adding Relay Owned Objs to the PUN relay model for some of this

gleaming prawn
#

We also discuss some crazy ideas for making an "advanced" relay system

jade glacier
#

Yeah, I can totally see for a 32 player thing Quantum making way more sense

gleaming prawn
#

server based culling, lightweight validation, etc

#

Battlelands Royale is now past those basic concerns. Now it's all about:

  • custom matches,
  • tournaments
  • new weapons
    THis is the kind of thing determinism lets you concentrate on...
jade glacier
#

The PUN2 stuff I am doing is purely based on the perspective of UX. Being able to just start, drag in basic stuff like vitals, pickups, hitscans, animator and transform syncs and such... and they all just "work"

gleaming prawn
#

I understand

jade glacier
#

There are definite limitations to PUN2 and I am not going to try to even fight them.

gleaming prawn
#

Although I'm a fan of the opposite approach

#

by opposite I mean: targetting programmers (although at the same time giving a good foundation for them to build tools for non programmers)

#

But not really being able to create an online game with drag and drop .

jade glacier
#

I've tried to make that possible as well. What is going on behind it all is that I have a pretty well defined timing segment system.

#

The components all use that, so I can fart them out pretty quickly

#

So the components can also just be used as examples of how to make use of the callbacks and base classes

gleaming prawn
#

@graceful zephyr I envy your asset store publisher role... lol

graceful zephyr
#

bwhahaha

jade glacier
#

He gets the SUPER green name

graceful zephyr
#

cos copenhagen 2019 unite

gleaming prawn
#

I got lost and never tried to write the definitions of state transfer and snapshot interpolation

#

But it's cool stuff, you can start from Fredrik's math expression and define all these models, and their small details, etc

#

Mind exercises

#

Good if you try to write a paper about it

#

lol

graceful zephyr
#

too much effort

jade glacier
#

Oh bother

#

I love the whole topic, I just wish I was a better coder.

jade glacier
#

If you ever make that book, I'll buy it 😛

gleaming prawn
#

The effort to write:

  • documentation
  • papers
  • reports
    Is enough to make me not want to write one
jade glacier
#

I think that is why they just don't get written. Good net devs are generally pretty swamped these days.

gleaming prawn
#

I always wondered how a guy like Jason Gregory could write his book

jade glacier
#

Good time management? LOL

#

Or just turbo

gleaming prawn
#

He probably had no life in work/life balance

#

Probably nitro/turb type of guy

jade glacier
#

That is a pretty rare thing

#

its odd talking to Tobi and Chrstof... for being ground zero in networking they take going home in the evening and for weekends very seriously. Being from the US that is totally not the norm for devs.

gleaming prawn
#

Tobi does enjoy excellent balance

#

It's always our choice here.

jade glacier
#

You really have to kind of make it yourself - because yeah - networking jobs will take any and all the energy you have to give if you let them.

#

the todo list is endless

gleaming prawn
#

well, you plan for the year, for the month, for the week and for the day

#

execute, stop when its time

#

evaluate, plan again... and then it goes

#

I admit I do extrapolate here and there for 30min (lol)

jade glacier
#

Its very odd for me, because I am digital nomading, so I basically have a laptop on my hand any time I am not out doing something where we are visiting.

#

I have no concept of work day/end... I just work when I am not (insert something else)

gleaming prawn
#

Anyway, again I'm not aware of server rules... But for the sake of utility for other, we could stick to networking...:)

jade glacier
#

Ah yeah, I forgot we are on Unity's chan here

gleaming prawn
#

Anyway, what is your guys opinion on Streaming games?

#

I have a hardball here

jade glacier
#

I would have to play one to really see how it feels - if you mean streaming like Stadia?

gleaming prawn
#

I read a bit about google giving another name for input prediction (they call it negative latency - lol)

#

yes

jade glacier
#

I really can only judge it based on playing it and seeing how it feels

gleaming prawn
#

so they do input prediction, render ahead of time... they must need to use MASSIVE amounts of power to be able to render several COMBINATIONS of inputs

jade glacier
#

but I suspect your experience is going to be greatly dependent on your location and quality of your ISP

gleaming prawn
#

Beause if you only predict ONE possible combination, what happens IF prediction is off

#

?

#

forget about that

#

The topic is how to fight the latency (that exists)

#

So they came up with this idea

jade glacier
#

I guess if their AI gets really good it might get pretty amazing at predicting you LOL

#

That would be a bizarre form of prediction... an AI that actually starts to mimic you

gleaming prawn
#

There are two problems with it IMHO:

  • because there IS latency, and the rendering happens on server, there's no chance a rollback/fix can be used (the fixed frame would take ages to arrive, ruining the streaming)
  • if they need to predict several possibilities, this is MASSIVES amounts of power, because it includes Rendering (our predict/rollback is just for the ECS simulation
jade glacier
#

I assume they will constantly be in a state of rollback and interpolating you back, because its going to need to blend in its misses

gleaming prawn
#

AI can greatly predict a few things, but say it gives you this:
85% chance the input will be X

#

then it is not, BANG the stream is gone

#

I assume they will constantly be in a state of rollback and interpolating you back, because its going to need to blend in its misses

#

THIS is the problem

#

Blending in OUR case is seamless, because we have a VIEW, and we can interpolate the view towards the CORRECTED sim

jade glacier
#

It sounds like a fun problem to try to solve, but I am not sure the answer will ever feel right

gleaming prawn
#

But what they will have are TWO views

#

Two rendered frames

#

Blending is blurring

#

I'm curious

jade glacier
#

yeah, without any client CPU or sim... that blending is going to be interesting

gleaming prawn
#

I mean, I'm not a streaming-denier... lol

jade glacier
#

Or they just won't, and misses will just become reality

#

But not sure how you would even try to predict like say a trigger pull

#

since you can't

gleaming prawn
#

What I believe is that there will be niches in which streaming will be great

#

like RTS, Tower defense

jade glacier
#

If I pull the trigger, RTT HAS to come into play as input latency

gleaming prawn
#

And (if streaming gets enough success to stick for a little longer) eventuall there will be a whole generation of kids whose first gaming expwerience is with streaming

jade glacier
#

It might be able to guess my positions pretty well, but it can't see a trigger pull coming

gleaming prawn
#

So they'll get used to

  • gaming is this
  • 4k gorgeous
  • a bit less reactive
jade glacier
#

I suspect it will just feel like old quake 2 and 3

#

You got used to weapons firing late

gleaming prawn
#

But this whole thing about action games... I think it's just red herring to calm down the media

jade glacier
#

I suspect its going to mostly be for slower moving games

gleaming prawn
#

and gamers who don't have a clue where the industry is going to

jade glacier
#

They will lean on audio cues to give the sensation of immediate feedback

gleaming prawn
#

I'll wait

jade glacier
#

is audio also streamed?

gleaming prawn
#

yes

jade glacier
#

Or can they add in audio to that?

gleaming prawn
#

there's nothing simulated locally

jade glacier
#

like for a weapon fire... would be helpful if it could locally play an immediate "bang"

gleaming prawn
#

it will be like playing old quake online

#

quake 1

jade glacier
#

yeah, that is how I expect it to be, but better since the internet is better

gleaming prawn
#

like for a weapon fire... would be helpful if it could locally play an immediate "bang"
There's no concept of a local code

jade glacier
#

I was a tourney Quake 2/3 guy

#

so I was used to playing to your ping

#

I can see that coming back

gleaming prawn
#

yeah, that is how I expect it to be, but better since the internet is better
Bandwidth is WAY better
Latency is same or WORSE

#

Quake 2/3 are GOOD

#

I'm talking Quake 1

jade glacier
#

Quake 2 still would withhold your rockets until you get server confirm

gleaming prawn
#

Quake 1 had no local predcition, pure client server snapshot interpolation

jade glacier
#

defintiely the rail held

gleaming prawn
#

3 arena is the first very fast one, you are right

jade glacier
#

you could tell the quality of your connect by how long between clicking and "pewt"

#

I never actually minded that

gleaming prawn
#

You will

#

just try streaming

jade glacier
#

as a competitive player, I liked "feeling" my connect so nothing was hidden

gleaming prawn
#

You'll miss pew

jade glacier
#

I am curious

gleaming prawn
#

I mean, you'll mind, a lot

#

BUT, may work

jade glacier
#

since as a digital nomad, I don't have a gaming system... so we will be trying it out

#

I suspect it will just end up with more games that are not flinch dependent

gleaming prawn
#

As I said, I expect it can succeed, if targeted right, and with a good business model

jade glacier
#

I think they would be wise to give the device a small amount of memory and CPU

#

For things like "click" and "flash"

gleaming prawn
#

Yeah, but that would be against everything

jade glacier
#

Basically cheap immediate cues

gleaming prawn
#

The whole point of their model is that the dev don't have to do anything complicated

#

You could be talking about stuff similar to smartwatch web-apps

jade glacier
#

As a player I need haptic feedback that my button registered... though they could just vibe the controller or some dumb shit

gleaming prawn
#

THat will live in the controller

#

depending on the game being played

jade glacier
#

Then I can see the controllers getting more and more features

#

I just know how this stuff usually works in reality

gleaming prawn
#

As an optional thing the developers can ADD to their games

jade glacier
#

the concept is simple...but devs will be like "this is nice, but we need the client to at least do X"

gleaming prawn
#

Can you imagine one thing for a moment?

#

Just imagine

#

Just imagine if you could have a device, in the player's house... Something you could connect to his TV...

#

That would be powerful enough to do local computation...

#

LOL

#

This would "solve" streaming, right?

#

seriously, I laughted so much when I read a comment with this on Ars Technica...

#

Obviously, the guy was smart and being sarcastic, that's the joke

#

But can you think as a game developer? Streaming would be GOOD

#

No more cheating (there's no local memory, no local rendering for aimbots to work on)

#

there's no cracking (expect account steals)

#

full DRM control

jade glacier
#

yeah, the basic concept is great

gleaming prawn
#

For the game developer this is full control of your content

jade glacier
#

but this ping pong has been going on my entire computing life

gleaming prawn
#

yep

#

I tried Onlive for a brief moment

jade glacier
#

1970... everything should be server

1980... not good enough people need CPU power on the client end

1990... Server only cloud!!

2000s... Clients need power for fun apps, internet too slow

2010 CLOUD ONLY!

gleaming prawn
#

when I was in Boston

#

2010/2011

#

it was horrible

jade glacier
#

If I was a betting man, I would say that Stadia and such evolve to have some client overlay stuff to give immediate feedback.

gleaming prawn
#

If I was betting, I would say stadia is not for gaming... It's a test before they apply the tech to a less demanding target

jade glacier
#

Or that yeah

gleaming prawn
#

Gamers are demanding... If it half-satisfies, and tech is put to the test, battle hardened

#

then use it for remote desktopping your digital life

jade glacier
#

I think though it will continue to exist if they create it, even if its as a plague like flash games where

#

I pity anyone who lives in shit internet areas if everything goes that way

gleaming prawn
#

possibly

#

about flahs

#

arguably, for experienced hardcore game programmers, Unity is the Flash of modern days...:)

jade glacier
#

LOL, VERY true

gleaming prawn
#

All this stuff about building "games" with drag and drop, visual programming

#

It's cool

jade glacier
#

Its middleware on top of middleware still

gleaming prawn
#

I wonder if you can make something like that for Online Networked games...

jade glacier
#

I would think for sure

gleaming prawn
#

Well, making games is hard, online ones 10x harder

jade glacier
#

The server only Stadia type thing would certainly simplify that

gleaming prawn
#

But yeah, can be tried

#

It's a cool concept

#

yeah, it would blur the boundary

#

although it still doesnt solve if you need to play with people far from you

jade glacier
#

you just won't get to I suspect

gleaming prawn
#

then the two close proximity servers need to communicate (with normal networked stuff like quantum, unreal, etc)

jade glacier
#

The entire stadia concept I suspect involves matching you up with a local server and thus local players

gleaming prawn
#

you just won't get to I suspect
certain games can live without that

#

But any game you play with buddies in duos, squads, clans, etc

#

competivie stuff, you NEED

#

so it needs to have the server instances communicating

#

Which would make the whole prediction thing even more complicated

jade glacier
#

Fast competitive games may be the last to come to that type of system for that reason?

gleaming prawn
#

yeah

jade glacier
#

The server is going to break trying to deal with all of the individual resims and blends and such

gleaming prawn
#

but any online game nowaydas also has duos, etc

#

What are the top grossing games?

jade glacier
#

I can see like a hearthstone right out of the gate on Stadia

gleaming prawn
#

They're ALL competitive games

#

hearthstone is no brainer, yeah

jade glacier
#

I haven't looked into Stadia... does it have anything out that is playable on it? Or is it just a convention talking point?

gleaming prawn
#

next month

jade glacier
#

so it must be reasonably far along. Very interesting.

weak plinth
#

I wonder what Stadia is going to be like

#

There's already enough problems with FPS games as is, due to latency. Nevermind that you are streaming

#

Is it even possible to create a system where you favour neither the shooter or the person that takes damage? Because in almost every game I've played, either of the 2 gets favoured

gleaming prawn
#

Pretty much all FPSs favor the shooter (regardless of being state transfer or snapshot interpolation, it's more or less a requirement)

#

Deterministic Predict Rollback in general favors who has good latency (players on bad latency, above a threshold, start to pay a penalty - to be more accurate)

#

Lockstep "penalizes" everyone, based on the worst ping + worst CPU (game runs on best possible input delay + speed based on worst case).

gleaming fossil
#

Are there any good character controller optimizations to do? Having issues where the character controller that's built in becomes less and less accurate

First is predicted client, second transform is from the server

#

Using input buffers aswell to ensure the same input is being handled...

#

Crazy annoying that the built in character controller is so unstable

gleaming prawn
#

You mean having something like this?

#

@graceful zephyr 🙂

graceful zephyr
#

@gleaming prawn nice

gleaming prawn
#

Butter smooth with the latest improvements...

graceful zephyr
#

sorry i ended up having massive back pain around 1.30PM and went to bed 😦

gleaming prawn
#

Don't worry

somber drum
#

Wow that's almost unbelievably smooth 🙂 glad i switched over to the photon environment

#

I'm wondering though how difficult it would be to upgrade from Pun to something like Quantum? Is it all based on the same backend?
Working on a fps heavily reliant on this kind of sync for it's sniper gameplay

gleaming prawn
#

@somber drum being honest, Quantum is a gameplay engine, so moving from PUN to Quantum pretty much means a re-write of the gameplay logic.

#

Being on the same backend means matchmaking, connecting, etc, uses the same codebase, so you reuse whatever you already have in that.

#

It's also possible to reuse a lot of the Unity side of things:

  • models, animations, UI, etc
  • you'll need to strip it out, so there's no gameplay logic in there (just view code)
  • possible, yes
somber drum
#

Ok thanks i'd always wondered about it

gleaming prawn
#

One more video of that KCC test:

#

Calibrating some mellee attacks

sterile dagger
#

any networker that want to help make a game ? it is a bit bigger game

weak plinth
#

I think that, aside from the professionals in here, everyone is trying to find out for themselves how any of this works 🙂 @sterile dagger

weak plinth
#

Almost done now. Just need to add an option for custom types, and a whole lot of cleanup

jade glacier
#

Excellent @weak plinth Once you get out of this stuff you get to the fun voodoo.

agile steppe
#

So, coming back from the dead here... I wanted to fiddle with a non production multiplayer game, but wanted to do it with the non depricated connected game stuff... is the beta far enough along to do that? or do i still need to wait a little longer?

weak plinth
#

@jade glacier I'm stuck with some stupid issue though

#

I figured it would be a good idea to allow people to throw in callbacks for their own structs or override structs

#

But I'm using generics for the writers/readers limited to an interface

#

This is going to cause boxing :/

jade glacier
#

I have two delegate definitions basically

#

one for objects and one for structs

graceful zephyr
#

<rant> @weak plinth you're overdesigning something nobody is going to use, just try to network your game instead.

#

</rant>

jade glacier
#

Yeah, you are trying to solve problems that we deal with to make these things "just work" for others - unless you are making an asset I wouldn't get this deep into this stuff

weak plinth
#

^

jade glacier
#

The highway of networking is littered with overengineered transports and serializers stuck at the starting line... and only a couple actually become a finished full stack that people use.

gleaming prawn
#

You could also call it highway to hell...:)

jade glacier
#

to the danger zone

weak plinth
#

Ok, on good advice I'm aiming this for what I need it to be 🙂

jade glacier
#

To your question though, I have two different handlers for objects and refs, since they delegate out differently. I DON'T allow managed structs, didn't want to go down that path.

#

So I handle classes with a reference in the delegate, and structs with an IntPtr

weak plinth
#

But you can cheat with codegen 😄

jade glacier
#

yeah, the codgen basically creates the codeset required for ref vs value

#

But you can make two delegates and leave the non-applicable one null

weak plinth
#

Aside from possible compression, my serializer just keeps cascading down until it's all primitives

jade glacier
#

yeah, that's the baseline

#

you should make it so you can define other types that have their own serialization rules

#

like Vector3 register as a known type with your system

weak plinth
#

Yeah, but I don't know how

#

My Serializer is constrained to an Interface

#

And that causes boxing if your serializer is a struct

jade glacier
#

I had to put interfaces on my attributes, and attributes on those interfaces... it was a bit dense, but got the job done

weak plinth
#

I don't know. I don't see a way to easily add types via delegates

#

Not without forcing the serializer to either be a class

#

Or boxing

jade glacier
#

I use IntPtr and my calling code converts it to a pointer first for structs

weak plinth
#

Or, without forcing the use of 1 pre-defined serializer

jade glacier
#

I have to pin, thus why I don't allow managed structs

#
public unsafe static void Copy(IntPtr src, PackFrame trg)
{
    var t = trg as PackFrame_TestStruct;
    t.myHealth = (*(TestStruct*)src).myHealth;
    t.floaterBloater = (*(TestStruct*)src).floaterBloater;
    t.floaterBloater22222 = (*(TestStruct*)src).floaterBloater22222;
}```
weak plinth
#

If I use a predefined serializer, and get rid of the interfaces, there's no problem

#

But that means it's locked to 1 serializer

jade glacier
#

There is no super clean why I found

#

without boxing, so I just have the two delegates, and only use one of them based on if the thing being serialized is a class or a struct

weak plinth
#

So yours does boxing

#

?

#

If you use a struct?

jade glacier
#

shouldn't, unless I fucked things up

#

I have two delegates, and one is just null

weak plinth
#

How is your serializer defined?

#

As an interface?

#

Or do you have read/write methods directly in your lib that are called?

jade glacier
#

Nope, as a base class that gets cast for classes, or a struct that uses an intptr for the cast

#

but either way, its a cast... which I am not sure you can make happen sans code gen

#

are you struct only?

#

struct only makes things a lot easier

weak plinth
#

My serializer is an interface

jade glacier
#

interfacees on structs tend to lead to boxing - where is your interface?

#

On the object you are marking to be serialized?

weak plinth
#

No?

#

The serializer literally is an interface

#

There is no explicit serializer defined

jade glacier
#

I would have to see the code involved to really comment, but you know this side of coding as well or better than me

weak plinth
jade glacier
#

yeah, that will be a little painful I suspect

#

Trying to come up with a generic way to get to delegates has eluded me

weak plinth
#

I don't know how to call a delegate from this signature...

#

Not unless I box the TWriter if it's a struct

#

Or just drop generics there all together

jade glacier
#

Not sure you can, but there are better C# people than myself

#

But I don't think generics will play nice with the mix of things you are after here.

weak plinth
#

But for your lib, I can throw in any serializer I want?

#

I can use my ByteStream with your lib?

#

I'm even considering taking a look back at Cecil....

#

Setting up serialization with IL is almost too easy

jade glacier
#

I put mine all in the attribute itself

#

like [PackRangedInt(0, 100)]
contains the serialization method

weak plinth
#

So, your library takes structs and spits out memory?

#

Basically?

#

My library currently takes structs as input

#

And spits out the data contained in a struct

jade glacier
#

this takes a byte[] and bitposition ref, and passes it through the whole tree of the class/structs [Pack] fields

#

Each item that is marked with [Pack] (or any field that is public if that switch is enabled) gets codegen'd into a whole serialization method for that Class/Struct type

weak plinth
#

Yeah, but ok

#

That means the serialization is happening within your lib

#

I can easily allow usage of self-defined types if I switch from a generic serializer to a strict one

jade glacier
#

yeah, the actual per field serialization handling is part of the [Pack] attributes

#

For mine, you just create new attributes

weak plinth
#

Maybe I shouldn't mess about with generics and such with this

#

I should keep that to IL

jade glacier
#

just make [PackSomeDumbThing]

#

The attribute has interfaces that indicate what types it supports, and those interfaces enfore including the Serialze.Deserialize methods needed for that data type

weak plinth
#

I'm going to remove the separation between serializer and the reflection stuff

#

That'll make things a whole lot easier

#

Then I need to remove a load of overhead still

#

Apparently creating an instance of an unmanaged struct takes 43ns

#

While stackallocating it is like 0.5 ns

#

I had no idea about that....

jade glacier
#

My codgen creates an entry in a dictionary for Dict<Type, TypeInfo> .... and TypeInfo contains all of the delegates used for that type

weak plinth
#

All the delegates?

#

I only had read/write

jade glacier
#

Copy, Serialize, deserialize, interpolate, extrapolate... etc etc

#

Mine isn't just an object to object, it creates a Frame class for that type

weak plinth
#

Btw, it's probably worth storing an ID to your TypeInfo somewhere

#

Instead of by type

jade glacier
#

since I have a whole ring buffer thing to work with

weak plinth
#

That's going to be a lot cheaper

jade glacier
#

its a one shot cost for the lookup

#

its only there for startup

weak plinth
#

Ah ok

#

I'm using it constantly

#

Still need to improve it

jade glacier
#

My NetObj checks all components for the [PackObj] attribute, and any that have that it pulls the delegates for it from the library

#

I have a very specific use case here mine stems from, which is a very UNet like attribute system on MonoBs

#

This is not recommended for non-asset store makers

#

as fholm was saying... lot of work for something no one will ever use if its for your personal use. Just make a serializer that is easy, and stick to using it how it needs to be used. Which likely means struct only in your case.

weak plinth
#

Yeah, I'm sticking to structs because I will only be using those for inputs and states

jade glacier
#

can you not just use IntPtr and offsets then or something? I saw offsets already in use.

weak plinth
#

I am

#

I'm just a bit iffy about some of the performance and custom delegates

#

I mean, the thing works already

#

But only with a set of predefined types (which are currently only primitives)

#

And I had to exclude bools because they fuck with offsets

jade glacier
#

even when you explicit layout?

#

are you trying to blit OVER the network?

weak plinth
#

No?

jade glacier
#

your serialization code should be hiding any system differences

weak plinth
#

Blit > Pack > Network

jade glacier
#

it just needs it to be the same each time on the same machine

#

You will have to do some of that offset finding at startup, rather than build time for that

weak plinth
#

Each system keeps track of its own struct layouts

#

As long as they are sequential, it's good

jade glacier
#

Since yeah, those offsets will change on different machines

weak plinth
#

Which they are by default

jade glacier
#

But if you gather the offsets at game start, that shouldn't matter

weak plinth
#

Yeah, I am

jade glacier
#

Then seems like you are done no?

weak plinth
#

Missing some attributes for compression (like half floats or floats/doubles)

#

Also missing deserialization of min/max values (should be done soon)

#

No custom types via delegates

#

Performance, cleanup

#

I benched direct handwritten serialization vs what I had

#

2.5ns vs 140ns

#

Biggest oof ever

#

So I definitely need to optimise

#

After stackallocating the return value, it went down by more than half

#

So, trying to remove the dictionary

#

And use lists for a faster lookup

jade glacier
#

you are pinning and unpinning that struct like mad I assume to do this?

weak plinth
#

No? You don't need to pin structs

jade glacier
#

yeah, if you are hitting your dictionary every time, I am sure that is the culprit

weak plinth
#

Question is also, ref vs non-ref

jade glacier
#

Can you not cache the delegates somewhere in your serialization process?

weak plinth
#

Large structs will probably eat time for copying

#

And you can't get the ptr of a reffed struct :/

jade glacier
#

not sure how you have any ref types in that system... doesn't that break pinning?

#

you have to go down the path of marshalling no?

weak plinth
#

No, why would you need pinning?

jade glacier
#

I pin for my structs, since you can't "cast" a struct

weak plinth
#

without ref, structs are copied to the stack

jade glacier
#

But not sure how you are handling that

weak plinth
#

So you can directly get the address

jade glacier
#

yeah, you were talking about refs above

weak plinth
#

In case of refs, it's pretty fucked...

jade glacier
#

not sure where they fit into what you are doing, because they will break it as I understand what you have going on

#

yeah, refs are a whole mess without codgen... that was where I started and I gave up on that

#

The amount of code you have to create to predict all of the marshalling results gets ugly

weak plinth
#

You can stackalloc and copy the ref to the new one I think?

jade glacier
#

For your case, I just wouldn't go there, make this part of the system strictly structs only

weak plinth
#

But then again, that's no different than just leaving ref

jade glacier
#

but you still have no idea where "things" are in that memory without reflection

#

which leaves bulk copying all of the data

weak plinth
#

I know the type

#

And from a type I know the layout

jade glacier
#

I thought this was all stemming from making a system where the Types aren't hard coded in?

#

I just don't fully know what you have going on. Sounds like you know what is involved already though.

weak plinth
#

All the calls to the serializer are hard coded in

#

Which is primitives currently

#

Exl bool/IntPtr

#

But if I'm using a fixed serializer, I can change that

#

Everything is written to a ulong anyway

#

Btw, if you constraint a generic to an Interface

#

And throw in a value type explicitely

#

It doesn't get boxed

jade glacier
#

I haven't found a way to create a generic delegate that I can make use of for my lookup though

#

It may be possible, but it would require voodoo above my paygrade

#

Pain in the ass I am dealing with right now is creating a hashcode generator for types that is determinstic and limits itself to just the stuff I am interested in

#

GetFields order isn't deterministic, so you have to capture them, sort them, and then hash them at eash recursion

vernal relic
#

What's the most effective way to transfer information from one networked object to another's owner? Right now I call an RPC on the other object that only the owner of the Photon View executes, though it does seem a bit unoptimized since every instance of the Networked Object will call it.

jade glacier
#

You can target your RPCs if that is what you are asking

vernal relic
#

Yeah, but how do I target them to be just the owner of the photon view. Aren't all target options stored in the enum RpcTarget?

jade glacier
#

you can look up the actorId from the photonView, though I believe there is some uncertainty about it being accurate for late joiners.

#

I don't recall the actual implementation off the top of my head though sorry

vernal relic
#

In my case buffering is not needed so that's not a problem.

#

No worries, just wondering

#

The problem with sending the information through an rpc is that it seems as if you can only limit who to send it to using the enum:

#

It just seems a little overkill to send it to every instance of the object instead of just transferring the information directly to the owner.

jade glacier
#

I don't think that is the "RpcTarget" meaning you are after

#

you may have to go through raiseevent to get use of target actors

#

I only ever use RaiseEvent, so I actually know very little about the RPC handling

vernal relic
#

Ok, I haven't really read that much about RaiseEvent, but with it would I be able to more effectively transfer information to photon view owners? Say if I told a gameobject to lower its health I wouldnt need to call an rpc that eventually makes the owner lower the synchronized health, instead I could tell the photon view owner directly?

jade glacier
#

Its what RPCs use behind the scenes

#

as far as I know, RaiseEvent is as low level as you can get with PUN2

#

You are getting into bigger questions about properly setting up a networkable simulation there

#

I can't really endorse any of what you are doing, because its all adhoc state syncing with no deferment or tick... so any advice I give you will be bad along those lines.

#

I'm actually working with Exit right now to create a system of components for all of that, so I am dealing with this stuff atm too

weak plinth
#

One day I will have an idea what is going on in here.

jade glacier
#

yeah, welcome to networking... we are all in a constant state of wtf

vernal relic
#

Okay, cool. I think I will read up on RaiseEvents and decide afterwards what to roll with, thanks!

jade glacier
#

np, its a bit more work, but gives you a lot more control

vernal relic
#

Yeah I just began learning networking some days ago and I'm don't even understand why some things work sometimes.

jade glacier
#

That comes back to why I stress simulation over messaging so hard

#

its easy to tie yourself in knots throwing around messages adhoc

#

but the race conditions pile up fast

#

all the real systems out there defer everything into buffers

#

messaging should NEVER touch your simulation

vernal relic
#

What is the difference between simulation and messaging? I haven't really learned that much theory about it all yet

jade glacier
#

Messaging <-> Buffers <-> Simulation

#

Simulation is your game logic, it should fire on a fixed tick... every tick it collects inputs and applies them and the previous state to the simualtion logic... and a new state comes out

#

[Player hits W at tick 1] + [PlayerState was at 0,0,0 at tick 1] -> Simulation -> [PlayerState now 0,1,0 at tick 2]

#

Inputs and prevstate = new state

#

that is networkable

#

because now you just store those inputs and states in buffers... message then is responsible for "transporting" those buffers as needed

weak plinth
#

I need a way to get a hash from a type faster

#

There's is either that option

#

Or storing the replicatemodel with the type itself

#

Then it should be pretty fast

#

Wobes does the latter

#

And I will probably as well in my game

#

Then again, I'm STILL thinking about using Cecil

#

Because that's faster

#

And less spaghetti

#

And so much more abstracted

jade glacier
#

Even with cecil you still want to hash your types for changes

#

otherwise you end up doing a whole codegen over and over

vernal relic
#

Okay, I think I get the gist of it, will read into it a bit more.

weak plinth
#

Don't need to hash anything with cecil

#

You can do anything whenever

jade glacier
#

When does cecil do its work?

weak plinth
#

Before build

#

So you'll need to do build pipeline stuff

#

Or just make a button in the UI that makes it do stuff

jade glacier
#

I really need to dig into cecil, because my codegen I can't get to be included in the build

weak plinth
#

The manual loading and saving of dll's is what pisses me off though

jade glacier
#

the build pipeline fails me for codegen, its gens but doesn't make it into the build

#

my codegen fires, writes the CS.... the build gets made... and THEN my cs gets compiled

weak plinth
#

I should finish at least some version of what I'm doing now

#

Then look at Cecil

#

So I have at least a fallback

jade glacier
#

yeah, really you are stuck on a hamster wheel to nowhere with this stuff

#

this is like shit people do after making a few games

#

not as step one in networking

weak plinth
#

I had the serialization stuff done within a day with IL

#

Tbh I just wanted to experiment with this stuff

#

No thanks to your and Wobes' talk 😄

jade glacier
#

if you are doing it for fun, for sure

#

but if you want to actually produce... just rough it up to working and move on

#

refactor later once you have a real thing to build to

#

Making Pong is WAY more interesting IMO

weak plinth
#

I have a project in mind

#

That's probably way too big and ambitious

jade glacier
#

the actual challenges of hiding latency/loss/etc is far more interesting than serialization

weak plinth
#

But, plenty of failing and standing up later

#

I'm sure I'll manage

jade glacier
#

I'm not kidding about Pong, its so simple yet so hard

weak plinth
#

I believe you

jade glacier
#

You will learn more in a week of trying to make pong feel right than you will in half a year dicking around with cecil

weak plinth
#

:O

#

Cecil for me is solely for serialization though

#

But eh

#

On one hand I really want to start on the game

#

And on the other hand

jade glacier
#

Its just the shitty end of networking to be stuck in for so long

weak plinth
#

I'm a dumbass perfectionist

jade glacier
#

You are allowed to refactor

weak plinth
#

That keeps sifting through the same shit day after day

jade glacier
#

just compartmentalize your stuff

#

your serializer only needs to be good enough to get you to the next layer for now

weak plinth
#

I mean, it is pretty abstracted

#

I don't even really need to use attributes

jade glacier
#

Take a break, go make pong with what you have

weak plinth
#

I have a TypeResolver.Resolve<T> that takes any unmanaged type

jade glacier
#

It will give you perspective

weak plinth
#

I can throw Vector3's and Quaternions etc in there

#

No compression out of the box though

#

Maybe I can use VLC 🤔

#

Just to hurry this up

jade glacier
#

That is so seriously the wrong thing to be tackling just yet

weak plinth
#

Hey, I never claimed I had a good plan 😂

jade glacier
#

It just can't be very fun

#

Networking isn't fun until you have things moving

weak plinth
#

It's fun exploring these possibilities

#

And truthfully

#

The fact that I still don't have a clear idea of what I'm supposed to do in networking probably keeps me finding excuses to not do it

jade glacier
#

If you are enjoying it, and have no pressure to finish anything - then do what you feel for sure

#

Its a super common problem

#

the networking channels are full of people over engineering things going nowhere

#

Its what devs do

ripe maple
#

Hello I am using Photon Unity Networking and when i try to build my project, i get these errors: . However, when using the editor, it works fine. What makes this error happen is this :

PhotonView photonView = PhotonView.Get(this);
photonView.RPC("OnEndTurn", RpcTarget.All);
jade glacier
#

Are you connected (firewall not blocking you) and are you set in PhotonSettings to not be running locally?

#

And are you calling those things AFTER you have gotten the OnJoin callbacks?

ripe maple
#

It is called via a button

#

also, i dont know why it does that since i have 2 rpc but only this one causes this.

#

it is not in the same class and file tho

jade glacier
#

dunno, at face value it looks like you aren't connected when you try to RPC

ripe maple
#

but it is when i try to build my project

#

so it looks normal that i am not connected

jade glacier
#

I got nothing

ripe maple
#

:c

#

oh yes, also, the rpc that causes this error is called in an other scene/level

weak plinth
#

Eh, I've pushed the overhead of the deserialize functions down quite a lot

#

From a juicy 150ns to about 20. Or even 3.5 if I supply the StructInfo

vernal relic
#

Apparently PUN 2 destroys my gameObject locally and then complains about it whenever I yield in a coroutine on the gameobject. Is there any way to get around this or can't I use coroutines with PUN?

jade glacier
#

What's going on in that coroutine?

vernal relic
#

This is what is supposed to happen

#

I have debugged it and noticed that it is the yield that causes Photon to locally destroy the object.

#

Even if I remove the PhotonNetwork.Destroy() call altogether it still destroys the object.

jade glacier
#

Nothing about a coroutine itself should matter

vernal relic
#

Went back and checked only to find that the guy I collaborate with had set the particle system's stop action setting to "Destroy"

#

nice

weak plinth
#

How do i make a game multiplayer? i want to be able to use a server and networking but i cant figure out how

#

if anyone could give me some info about multiplaye games, id appreciate it!

weak plinth
#

I need help on networking on my mmorpg game. I dont have any idea how to make char select menu

jade glacier
#

@weak plinth if you are just starting from nothing, you can try a few of the HLAPIs like PUN2, Forge, Mirror, MLAPI or Bolt - and look up tutorials for them.

weak plinth
#

ok

#

ill try that

somber drum
#

@weak plinth Vis2k runs Mirror and is using it for his well received assets "uMMORPG" 3d/2d, i would definitely recommend checking it out, it's a great learning experience and comes with all you need to start out

weak plinth
#

Thanks for reply.

weak plinth
#

Yeah, the performance is quite bad though. Don't expect any actual MMO-scale networking from Mirror

thick peak
weak plinth
#

@thick peak This reply might sound silly

#

But pretty much everything is possible in programming

#

Are there libraries that offer p2p networking? I'm sure there are. I think Lidgren is one of them

#

But if you design it yourself, you can make it as pure p2p as you want

#

The question is more, why would you want such a thing?

#

In most cases you work with a client-server model. Either that server being a pure, dedicated server, or another peer

#

Many old games (like older Halo and CoD games) work with a peer2peer model where 1 client acts as the server (the "host")

#

And many games still use this model

thick peak
#

awesome

#

but what libraries would speed/help me out for this. It is important that there is no host (so isn't one player acting as a server), each acts like a server for one randomly assigned.

weak plinth
#

I don't know about that specifically

#

But the question still remains, why are you choosing for this model?

thick peak
#

because I don't have a server for the game and I don't plan to have one. If there is any chance to have players play multiplayer without a server, that's awesome!

#

and I avoid the "host" model to prevent cheating so each player is checked by another one.

weak plinth
#

Sounds like you are making an overly convoluted system

thick peak
#

So my best option is to start from scratch?

weak plinth
#

No, that's not what I'm saying. I don't know if there are libraries available for your specific use-case

#

I'm saying that I think it's overly-convoluted what you are trying to achieve

#

Depending on your specific use-case, it might not be required at all

#

Don't forget that very popular games like Halo and CoD used 1-player host systems. Doesn't mean it's a good thing. But it's apparently good enough for a majority of people

#

Also, there might be the option to let people host servers for themselves. Games like Minecraft, Factorio, Space engineers etc etc have these options

drifting folio
fossil sapphire
#

Hey there, I want to turn my local multiplayer game into an online multiplayer game. How would I go about doing that? What tools/libraries can you guys suggest and what tutorials can you recommend?

weak plinth
#

@fossil sapphire Did you keep remote multiplayer in mind when designing your game?

fossil sapphire
#

Not really, I will probably have to change some stuff, but it's still a rather simple prototype