#archived-networking

1 messages ยท Page 52 of 1

weak plinth
#

That's what's pretty standard in networking

#

Because it works and it works well

jade glacier
#

I think everyone is on the same page, just talking about slightly different things here

amber trench
#

@jade glacier yeah, i mean protobuf and cap'n'proto are probably close enough to micro-managing your own networking serialization infrastructure, that probably what you lose in bytes you gain by actually shipping ๐Ÿ™‚

#

but it's just food for thought

jade glacier
#

please don't use protobuf for game networking ๐Ÿ™‚

#

I mean, you can

#

but there are bitpackers and such galore to borrow and use

amber trench
#

hearthstone for example uses protobufs

#

and that's even a unity client game

jade glacier
#

hearthstone could send its updates via email server though, its a card game

weak plinth
#

Bitstreams are more efficient and faster than capnproto

#

And you can automate them just as easily

#

There's no reason to use capnproto or anything alike for network serialization

amber trench
#

i think one of the challenges, for example

weak plinth
#

It's a bad idea

amber trench
#

is that your protocol, it will eventually look like cap'n'proto

#

if you do something something bitstream

weak plinth
#

No

#

Look at its protocol

jade glacier
#

all of this matter very little, that layer should be abstracted enough that it should be easy to go in and rethink your serializaiton choices later without breaking anything

#

All that matters is that you HAVE an OnSerialize and OnDeserialize and that they match up

amber trench
#

yeah

#

i guess there might be a reason people use this stuff

weak plinth
#

Yes, for local data storage probably

amber trench
#

i know for starcraft it can be controlled via a protobuf API, in real time

weak plinth
#

What it should be used for

amber trench
#

SC2

jade glacier
#

There are cases if you don't need fast and light data to make things a bit more human readable

weak plinth
#

Yes, business applications

amber trench
#

yeah

weak plinth
#

Where people use json mostly

jade glacier
#

But I am very sure Overwatch is not sending human readable anything

amber trench
#

hmm

weak plinth
#

Still no protobufs or alike

jade glacier
#

thats going to all be bitpacked to the bone

weak plinth
#

Which btw, isn't readable

amber trench
#

but do you think protobuf isn't bitpacked? or cap'n'proto?

jade glacier
#

proto is bytepacked from what I know of it

weak plinth
#

It has a pretty decent amount of overhead due to their "encoding"

#

As per their own documentation

amber trench
#

yeah

jade glacier
#

I don't use any of them, but the point is that you can do what they are doing much tighter if you just get in and implement your own Write()

amber trench
#

i mean ultimately, how many Unity real time multiplayer games are comparable to an SC2 custom map, or overwatch

#

they have a standardized replication system, it has overhead, i think my point is that it ends up looking like cap'n'proto

jade glacier
#

I make assets, so I don't deal with any one off stuff - so I can't comment

amber trench
#

they don't write Write(...) and Read(...)

weak plinth
#

You don't have to

jade glacier
#

but making networking assets, I have to bias toward worst case - so I pack everything as tight as I can

amber trench
#

they don't annotate or weave

weak plinth
#

And it still won't look like protobuf

#

Because you don't need the overhead

jade glacier
#

Anyway, I think we have beat this horse. ๐Ÿ™‚

amber trench
#

yeah

jade glacier
#

If it works, it works

amber trench
#

it would be nice to hear from the Unity folks, every now and then, like what the angle is

jade glacier
#

If it doesn't, replace it with something better

weak plinth
#

The Unity folks as in, the people that work at Unity?

amber trench
#

yes

jade glacier
#

Unity on the networking front is going get you a lot of silence

weak plinth
#

I mean, are you familiar with UNet

#

What are you expecting from them for advice...

jade glacier
#

The Photon/Exit guys are generally the leaders on these topics

weak plinth
#

Besides, these networking principles are universal

#

It's not exclusive to Unity

jade glacier
#

as far as actually implementing usable networking that is in usage

#

We are all doing similar work, and these topics come up often

#

This isn't a new conversation ๐Ÿ™‚

weak plinth
#

I can guarantee you that people who make high-end network layers aren't going to use some pre-made serializer with overhead

#

Why would I buy your product if I can slap this on myself for the same result

amber trench
#

i suppose the hearthstone people don't count then

#

it's an interesting conclusion for sure

weak plinth
#

So, the people that made heathstone are selling their networking api?

#

Can you show me where please?

jade glacier
#

its hard to say anything generally, since games can vary from 2 people playing cards to 100 people in a BR

amber trench
#

it's probably the biggest unity client multiplayer game

jade glacier
#

2 people playing cards you could use json

amber trench
#

for mobile?

#

it's bigger than rust

jade glacier
#

Hearthstone?

amber trench
#

yeah i think so

jade glacier
#

its still 2 people playing turn based cards

amber trench
#

yeah...

jade glacier
#

Not the pinnacle of networking

amber trench
#

but the sheer scale of the game...

weak plinth
#

And besides, saying "game x did it so it must be good" is a pretty damn poor argument

jade glacier
#

the scale though is all in the backend

weak plinth
#

Minecraft uses Java and TCP

#

Not exactly the pinnacle of performance, that

amber trench
#

yeah, you're right about how important the backend is. like they're not using C# runtime unity servers

jade glacier
#

yeah, going to agree with @weak plinth - the point of talking in these channels is to come up with best practices.. not all agree on the shitty ones that are popular being good enough

amber trench
#

it's like, in order to achieve their scaling needs, they needed a cross-runtime, cross-boundary representation of data that was efficient and flexible

jade glacier
#

Yes, you can literally make networking with JSON or email...

amber trench
#

i'm definitely advocating for a best practice

#

i suppose though, why didn't they? i mean i think they have the same concerns, conserving bandwidth and all

#

for a mobile game that works well on LTE

#

anyway

jade glacier
#

Hearthstone?

weak plinth
#

Then you shouldn't advocate for slapping protobufs on a network and calling it a day

amber trench
#

it's just stuff to think about

jade glacier
#

The demands of hearthstone are nill

weak plinth
#

That's obviously not best practice

jade glacier
#

its likely a TCP packet like once a second

amber trench
#

hmm

#

what if i told you it isn't?

jade glacier
#

wouldn't care LOL

#

the point is the demands aren't there

amber trench
#

right

#

hmm

jade glacier
#

there is nothing inherently demanding about HS's networking

#

its all backend

amber trench
#

but surely, the per-server user count

jade glacier
#

and user facing animations and such

amber trench
#

concurrents for hearthstone

#

surely, they want to optimize their resource usage

weak plinth
#

Have you ever worked in business?

amber trench
#

yeah i like this backend idea

jade glacier
#

but the actual conversation is "User did nothing... user did nothing....... user played this card..... user tapped on this house"

weak plinth
#

With webservers or apps?

#

The network traffic is also quite low

#

And has more concurrent users than most games

#

Uses almost always some bloated format like json

amber trench
#

but the backend, you see, is it practical to trade around a specification for what a message looks like as a series of Writes and Reads

weak plinth
#

If they need more perf, they rather slap some more hardware in the server or put up another server

#

Than mess about with high-end coding

amber trench
#

yeah...

jade glacier
#

If I were doing hearthston, I would probably start with JSON actually

#

just so I could debug my traffic easily

weak plinth
#

is it practical to trade around a specification for what a message looks like as a series of Writes and Reads
Yes, because literally every serializer does this

#

How do you think JSON works? With magic?

amber trench
#

i don't think a protobufs schema looks like a bunch of writes and reads

weak plinth
#

I'm afraid you are wrong then

jade glacier
#

It has to be

weak plinth
#

Memory doesn't magically float to a buffer

amber trench
#

maybe we're not sure what a schema means

jade glacier
#

all networking is a bunch of reads and writes

amber trench
#

like a file, that says, this is an int here, etc.

#

as opposed to a file that says Write and Read

jade glacier
#

yeah, its going to do all of that internally

weak plinth
#

Who cares? It's still using a bunch of reads and writes

jade glacier
#

but its still the same concept

amber trench
#

like the difference between a protoc file and a cs file

#

yeah, i guess who cares

#

it's all very interesting

jade glacier
#

yeah, we are arguing nothing here for no reason

#

serialize however it works for you

weak plinth
#

I think you need to look up how a system handles memory. That probably clears a lot up

jade glacier
#

and if it stops working, move to something better. done.

weak plinth
#

You can't magically get one piece of memory to a buffer without write operations

#

Even if your library doesn't expicitely say "write"

#

It's still copying

#

And I also think we shouldn't forget about work vs profit

#

Even if hearthstone uses a horribly inefficient network layer, it uses very little for a lot of users

#

They can easily make enough money to slap some new servers down

jade glacier
#

@amber trench what are you making?

weak plinth
#

Definitely not worth the effort in a game like that to make the most efficient networking, for a game that essentially can run on a REST API

#

Also the case for business applications this

#

The extra effort to make a fast network layer isn't paid back when the thing is in operation

#

They rather slap some ready to go networking framework on there and not even bother with it

#

Performance isn't needed, and if it is, more servers are cheaper than hundreds of hours for developers to develop some propietary solution

#

Which then no-one knows how to upkeep

#

Which is also a problem in live-service games

#

Many propietary solutions that have to live for years on end

#

Maybe I'll finish a first version of my serializer tomorrow. It's a crude solution, with not top-of-the-line performance. But it's the best tradeoff between performance and ease of use without using codegen or ILWeaving

#

Haven't run any benchmarks yet, though. So maybe the performance loss will be alright over writing direct writes/reads

#

@jade glacier When will your project be done?

#

And are you selling it for ๐Ÿ’ต ?

jade glacier
#

Which one LOL

weak plinth
#

Codegen serializer

jade glacier
#

that's just likely going to end up in with the stuff I am doing for Exit

weak plinth
#

So, nothing opensource?

jade glacier
#

Will be hard to stop anyone from just stealing it - but technically won't be open

#

I don't care if it gets into peoples games, I just don't want to ever be competing with my own code is all

weak plinth
#

What do you mean competing with your own code?

jade glacier
#

Like I don't want to see it in Mirror next week LOL

weak plinth
#

LMAO

#

Put it in the MIT

#

"Excluded from use by Mirror"

jade glacier
#

Right now I am just coding in Limbo, since all of the drag and drop networking stuff I have made is slated to become part of PUN2

#

So its really going to be up to them

#

But what I am doing is along the same lines as what you are doing

weak plinth
#

Ahh, I see. That explains

#

Eh, not really

#

I bet yours will be faster

jade glacier
#

the only hangup is that Unity offers crap for callbacks

weak plinth
#

And it can handle objects

jade glacier
#

Finding the right moment to generate code is tricky

weak plinth
#

I won't get equal to your perf unless I use Cecil

#

Using Cecil might even be faster. But like I said yesterday, I probably won't be using that

#

So it's wasted effort on my side

jade glacier
#

It sounded like you were producing fairly parallel work, outside of the codegen part

weak plinth
#

The only reason I'd make it is to make it, and have it on git to show off I guess

#

I was, with ILWeaving. But that's a no-go in IL2CPP

jade glacier
#

All of the codegen is just to wire up the packing delegates

weak plinth
#

Need Cecil for that

#

I'm building something similar to what Wobes' is using

#

It's a more manual, static approach

#

But it works too

jade glacier
#

I never know what madness that guy is up to LOL

weak plinth
#

Only blittable types though

#

Apparently he got the idea from Freddie?

jade glacier
#

but I think we are all doing similar stuff, just slight differences for our usages

#

he is going way more ECS with his stuff

#

like doing shadow copies and all of that

weak plinth
#

I think Wobes is just finding out how he can break his CPU with DOTS

jade glacier
#

My stuff all originates from the problem of "how do I make stuff that looks like Unet's weaver attributes, but actually can do bitpacking, and is still fast without weaving"

#

so very different requirements

weak plinth
#

Why without weaving?

jade glacier
#

I don't want to maintain that for one

#

I want all of my codegen to be visible

weak plinth
#

I guess that's a fair point

jade glacier
#

And there are the dangling questions about IL2CPP I just don't know

#

The main restriction is I am a mediocre programmer

weak plinth
#

It's fine if you use Cecil

#

And weave before it gets compiled to C++

jade glacier
#

yeah, that probably is the ideal answer - and someday may revist that part of the codegen

weak plinth
#

This is with Reflection.Emit for a writer function

#

It's not too bad if you ask me

#

It makes exactly one delegate to serialize your entire type

jade glacier
#

I'll look into it

#

I am not opposed to it, just not something I know very well.

weak plinth
#

I was able to use generics too

#

The writer function is just a Write<T>

#

So technically, you can plug in your own writer implementation in there

#

As long as it inherits that interface

jade glacier
#

what's the resulting code you are getting from this?

weak plinth
#

The IL code?

jade glacier
#

I suppose you don't just have an example of it hanging around for cut and paste LOL

#

I need to set aside a weekend to just play with weaving

#

My main reason for not using it is that I just don't have any experience with it.

weak plinth
#
        static void Main(string[] args)
        {
            TestWriter writer = new TestWriter();
            var wFunc = WriterFuncs.GenerateWriterFunction<TestOBject, TestWriter>();

            TestOBject to = new TestOBject();

            wFunc(ref to, ref writer);

            Console.ReadLine();
        }

        private class TestWriter : IWriter
        {
            public void WriteValue<T>(T value)
            {
                Console.Write(typeof(T));
                Console.Write(" -> ");
                Console.WriteLine(value);
            }
        }
#

This is the bit I used to run it

#

The IL calls the Writer<T> method, for every field

#

But uses the actual type instead of the generic

jade glacier
#

The other thing I don't have my head around is when does this happen in the build process?

weak plinth
#

This?

#

It doesn't

#

That's why it doesn't work in IL2CPP

#

This is Reflection.Emit and it happens on runtime

#

That's also why it works a whole lot easier than Cecil.

#

Reflection knows the current assembly and all of its types

jade glacier
#

oooh, thought you were saying that this does work

weak plinth
#

With Cecil you have to "manually" load all the assemblies and containing types

#

Even the system types

#

But the IL weaving is the same

#

The setup just really sucks (and that's why I didn't bother with it)

jade glacier
#

yeah, that was what I was doing the other day - and tore my hair out with it.

weak plinth
#

Me too lmao

#

I thought I could be smart and use .Emit

#

But turns out it doesn't work

jade glacier
#

I had it working, but I can't be letting it constantly parse the entire assembly every time someone compiles

weak plinth
jade glacier
#

I have just punted that for now. I have a manual "Generate"

#

That's helpful

weak plinth
#

Cecil modifies the managed assemblies

jade glacier
weak plinth
#

You literally cannot IL weave any later

#

It works, and I used something similar

#

But I personally don't like codegen

#

Maybe if it's really hidden away well, and it gens on build time

jade glacier
#

Yeah, I am not in love with it, but the alternatives were all running into walls

#

Gen at buildtime is the problem

weak plinth
#

Because ORMs use codegen as well

#

And you don't really notice that, because it's gen on build time

jade glacier
#

If you gen in OnPreProcessBuild... it doesn't get into the buld

weak plinth
#

And the genned code is hidden away in your project really well

#

You could always look at the mirror weaver btw

#

Since they do cecil weaving

jade glacier
#

Mine is all hidden away, because its abstracted into that database

#

but the issue is the timing of it

weak plinth
#

It's a big damned mess though Cx

jade glacier
#

That weaver is constantly rerunning, not a fan of that.

weak plinth
#

They've thrown stuff all over the place and are weaving massive IL functions that they aren't even using

#

Wait what

jade glacier
#

the price of invisibility is that its always having to recheck things every compile

weak plinth
#

Oh shit

#

That's true

#

It needs to weave everytime you build

#

Well, for codegen it's the same

#

But at least there you can check if it's up to date

#

And just skip it

jade glacier
#

check what though?

#

That was the problem I had

#

you think "I'll just check if its current"

weak plinth
#

Idk. But ORMs like Entity framework do it

#

It's possible

jade glacier
#

then you realize that files aren't associated with types

#

Is there a way to quickly test for changes to types?

weak plinth
#

No

jade glacier
#

like a type having been created, or destroyed? or its interfaces and attributes changing?

weak plinth
#

But maybe hash the type file?

#

As soon as you make edits you can see the hashes are different

jade glacier
#

But if they just created a new one?

#

I mean you end up with a monolith thing trying to monitor stuff

#

just to avoid a rescan of the asm

weak plinth
#

Yeah. Well perhaps Entityframework has this

jade glacier
#

Not familiar, if so yay - I want that

weak plinth
#

But you know, years and years of development by large teams

jade glacier
#

I am not aware of any callbacks available in Unity to tell you what changed after a recompile

weak plinth
#

The first one

#

It's common in business applications

#

Java uses Hibernate

#

Does exactly the same

jade glacier
#

if its not available to me for this, then its dead to me

weak plinth
#

These are extremely big frameworks used to communicate with databases

jade glacier
#

My choices currently are rescan after every compile... or have the users trigger a build

weak plinth
#

Nothing you can use ๐Ÿ™‚

jade glacier
#

The big Unity letdown is that OnPreProcessBuild is too late for codegen

#

That is where I need to do it

weak plinth
#

Haven't read this yet

#

But maybe it's in here

#

If it works for cecil, it should work for you as well

jade glacier
#

I'll poke around - need to know what they trigger off of for a callback or something

weak plinth
#

Damn though

jade glacier
#

All I am aware of is OnPreProcessBuild

weak plinth
#

Having to rerun the weaver at every build

jade glacier
#

which fails

weak plinth
#

That's rough

#

That's really rough

jade glacier
#

I think that is why it does that

weak plinth
#

You are making me reconsider making this

jade glacier
#

there may be literally no other way

#

If you find a way to code gen or inject at build time... PLEASE let me know

weak plinth
#

Maybe not. But literally every compile action will get slowed down even more due to reweaving of assemblies

jade glacier
#

I am just skipping that part for now

weak plinth
#

I had a tough time dealing with this as well with T4's

#

Ended up moving them to a specific folder and copying them by hand ๐Ÿ˜ฆ

jade glacier
#

Even with that though... how do you know which types are in that file? and what their attributes/interfaces are?

#

I would need to know that a file changed that contained a type with my attribute

weak plinth
#

The latter doesn't matter

jade glacier
#

and I don't want to regex files for that shit

weak plinth
#

You're going to have to scan the assembly anyway for types with that attribute

#

But if you can link the type to a file ๐Ÿค”

jade glacier
#

The goal is to avoid the scan unless you have reason to believe there has been a change that mattered

#

I did come up with that as a possible

weak plinth
#

The scan isn't the problem though

#

The genning is what's going to take the longest time

jade glacier
#

limit rebuilding to if altered files have an attribute of mine

weak plinth
#

I'm sure the scan won't take long at all

jade glacier
#

If the file doesn't have my attribute... I just ignore it

weak plinth
#

But what I sent is useless

#

Since that only works on runtime

jade glacier
#

Though scanning a file for a text string... probably not much worse than just rescanning

weak plinth
#

Didn't think about that ๐Ÿ˜ฆ

#

You NEED to rescan anyway

#

I don't see any other way to avoid that

jade glacier
#

Where I will likely land is a full rescan, but maintain a catalogue of types

weak plinth
#

Time it. I'm sure it won't even take 100ms

jade glacier
#

and just check for changes relative to my catalogue vs the ASMs

weak plinth
#

That works

jade glacier
#

The rescan I think will be unavoidable

weak plinth
#

You need a rescan for new attributes anyway

jade glacier
#

You still have to loop the whole thing

#

all ASMs and ALL types to know what has been added/deleted

#

I might be able to reduce the number of asms checked, that is stuff I don't know enough about though

#

I had an editor only SO that was doing that

#

and I deleted it, so will have to find that in my git and bring it back

weak plinth
#

Maybe far fetched

#

But Git knows when files have been updated

#

But then again

#

A file =/= a type

#

You can define multiple types in one file

#

I think you're going to have to rescan, and compare for changes

#

Store the current version somewhere as soon as the gen is finished?

#

Some easy to process information that tells you which types/fields/members you've generated for

#

Scan again and compare the 2

jade glacier
#

No good for me, I have no certainty of that. This will by used by god knows who god knows how

weak plinth
#

Doesn't matter

#

If they delete the file, regen everything

#

If they mess up the file, discard and regen everything

jade glacier
#

you can capture that with Unity calls, they are limited but they exist

#

you can even stop people from deleting and such with them

weak plinth
#

You can't expect to make some library that's 100% fool proof

jade glacier
#

BUT, its all through the editor

weak plinth
#

Especially with code gen

#

Since they can just alter or remove the code gen files

jade glacier
#

so stuff outside of the editor... its dumb

weak plinth
#

I mean, you can store this version file as an asset, no?

jade glacier
#

The answer I need is the answer I can't have. I want to generate at build time.

weak plinth
#

Same as you are storing your genned classes now

jade glacier
#

I could database the text files yeah

weak plinth
#

You only need 1 for the current version

jade glacier
#

The thing for me though is that filewatch has to be faster than Unity on the draw

#

because if unity gets to the recompile first... it can throw errors since my codegen may now be invalid

#

Currently I have my codegen capture error messages and it triggers a file delete if they originate in one of my generated files

weak plinth
#

The process that generates the code should not be the same process that runs the code

jade glacier
#

But its after the fact, Unity already has thrown a red error to the log, and it stays there for a second

#

It doesn't run it, it just generates it

weak plinth
#

Can't you make some editor script shenanigans for this?

jade glacier
#

But that code contains hard references to fields and such in other classes

#

So if those classes change, its going to throw errors

#

I have not found ANY way to beat the Unity processing

#

and it offers no callbacks I have found that lets you intercede

#

you can only react to the things after the fact

weak plinth
#

Well what I mean is

#

If the process that runs the codegen is separated from the genned code

#

Compile time errors don't matter

#

You can just still run the code gen

jade glacier
#

Unity cares though, unless I misunderstand you

#

if at any point there are files with invalid references, Unity is going to raise a stink

#

Uness you mean build time?

weak plinth
#

This stuff is bending my brain so much lmao

#

No

jade glacier
#

Its been my whole week

weak plinth
#

The problem what you have, and I had

jade glacier
#

every path I have tried, ended in Unity not giving me a callback I needed

weak plinth
#

If you change something that makes your genned code not compile

#

It's game over

jade glacier
#

yeah

weak plinth
#

I had this same problem

jade glacier
#

I can recover from that

#

but it takes a second

weak plinth
#

I manually deleted files

jade glacier
#

I capture the errors in the callback

weak plinth
#

But I wasn't making some public api

jade glacier
#

and auto delete on that

#

It works, but it does show that error in the log for about 1 second

weak plinth
#

Maybe find out how these ORM are doing it

#

They don't gen code from already existing code, but they gen code from a database schema

jade glacier
#

The issue I have is that if there is a compile error, Unity is the first to know about it - and I don't get informed until AFTER the log has the error already

weak plinth
#

Hmm nevermind. ORM's work the other way around

jade glacier
#

the database won't change much, it just lets you check for changes before making a new file

weak plinth
#

Code IN the ORM can't ever be faulty

jade glacier
#

the database has value for that... you can just check to see if the type existed before, and if it matches up on fields, attributes etc.

#

Saves the codegen step

weak plinth
#

If only Reflection.Emit worked in IL2CPP

#

There would be no problems...

jade glacier
#

Or if OnPreProcessBuild let you codegen and compile in time

#

they need another sooner callback for when builds are started

weak plinth
#

@gleaming prawn Was talking about something they wrote

#

Codegen also, but something completely different

#

Maybe he can help you

jade glacier
#

they have some luxuries

weak plinth
#

Why can't you have those?

jade glacier
#

since they are TOTALLY outside of Mono and such

weak plinth
#

IL2CPP though?

jade glacier
#

Not sure, I only was half following that convo

#

I believe they rely heavily on codegen

#

that is the fholm way

weak plinth
#

I mean, if you are only targetting mono (which I guess you aren't) dynamic methods solve your issue in a heartbeat

jade glacier
#

I have a "passable" option right now, that is that if give them the option to not auto generate, and require a manual hitting of the Generate somewhere... I can easily throw log warnings of "Hey, you are trying to Pack stuff that hasn't been CodeGen'd yet... Be sure to hit the Generate Button"

#

The other option I can give them is to just let it autogen every time, they just risk a little slower compile times and an occasional log error that clears itself.

#

It will WORK, its just lame.

weak plinth
#

I can imagine with lots of types

jade glacier
#

I prefer a bit more polish than that.

weak plinth
#

That can have a noticable impact

jade glacier
#

Its not the end of the world having a Generate button somewhere

#

Bolt DEMANDS you compile like that every time

#

Bolt actually has its own Build button I think

weak plinth
#

Hmm, might be a viable option for Cecil as well

jade glacier
#

just so I can do what it needs to do before building

weak plinth
#

Handy thing about Cecil

#

No compile time errors ๐Ÿ˜‚

#

It's just not going to work at all

jade glacier
#

Which can be maddening

#

half of Gadget's job is telling people why they broke the weaver

#

since its not always obvious

weak plinth
#

They should fix that weaver in the first place

#

It's a mess

#

They have separated IL weaving for classes and structs for some odd reason

jade glacier
#

I am at the moment going to just leave the codegen part as is, and finish out the actual serializaiton attributes

weak plinth
#

And have a function where it passes a byte array down to it

#

And running some for loops in IL

#

I mean, comon

jade glacier
#

It works, so going to just revisit it later

weak plinth
#

array segment*

jade glacier
#

a lot of that code came from before array segment existed

weak plinth
#

Array segment is bad if you ask me

#

Lots of shifting required

jade glacier
#

Its a step up from nothing

weak plinth
#

And going to be very hacky if you want to bitpack

jade glacier
#

But it was a patch

weak plinth
#

They should just use unmanaged memory already...

jade glacier
#

Mirror is part of Vis2K's other libs, so has a LONG caboose attached to it

weak plinth
#

And you know, maybe weaving some generic bitstream interface

#

So there's actually some possibility to change things

jade glacier
#

I don't think anything with that is going to be a simple fix

weak plinth
#

Rather than having to rewrite some entire IL weave method

#

I think a big problem with Mirror is that it's hobbyists working on it

jade glacier
#

I personally think that if they were going to tear Mirror apart and do it better, they should do what MLAPI Forge and PUN2 need to do - which is give the whole systems proper tick based timing mechanisms that are core to it all

weak plinth
#

Rather than professional network engineers

jade glacier
#

The biggest achilles heal of all of the HLAPI is that they are fully adhoc timing

#

I can live with questionable data packing, but making it so hard for users to properly respect a sim rate is a real problem

weak plinth
#

If that were its only problem

jade glacier
#

Syncvars mixed with RPCs... holy shit.

#

Its all relative

weak plinth
#

How about, 2 threads per connection

jade glacier
#

I just know what people complain about

weak plinth
#

Or using managed memory for buffers

jade glacier
#

the tech guys like NX have bones to pick, but they are not what the average users sees or feels

weak plinth
#

Or writing per byte to a buffer without even packing

jade glacier
#

The average user is all "Why is my stuff all jittery"

weak plinth
#

The average user doesn't even know what they are getting in to

jade glacier
#

Because your networking has no concept of your sim... you are boned.

weak plinth
#

Mirror is advertised as some magic solution that makes networking magically happen

#

And people that don't know any better take this at face value

jade glacier
#

They all are, but only Bolt and Quantum actually respect simulation

#

The rest are generally just really messaging platforms

weak plinth
#

People underestimate how difficult it is to make a game

#

And infinitely more underestimate networking

jade glacier
#

Yeah, that is really my only personal beef with Mirror - that it works to keep people at that level

weak plinth
#

I wanted to make a multiplayer game as well 4 years ago

#

And here I am, still not having made a single thing

jade glacier
#

The things Mirror does magically, are things no one should be doing if they want to progress in networking

weak plinth
#

I've spend 4 years actually (trying) to learn how this all works

#

And I still don't know anything if I compare myself to the people at NCoders

jade glacier
#

I started my first game 3 years ago, and a year later I had instead made an Asset Store asset for networking

weak plinth
#

๐Ÿ˜‚

#

That's how I'm ending up too

jade glacier
#

After that first year I was like "holy shit, no one should have to go through this - I'm making an asset for others"

weak plinth
#

That's why I'm throwing that blittable serializer on git

#

I literally can't find an implementation of something like that on the web

#

And it's something to vital

jade glacier
#

I share some of my lower level stuff, and I did share NST - because its old and full of bad choices LOL

weak plinth
#

I'm sure a lot of people can benefit

jade glacier
#

NST for as bloated as it is - STILL is smoother than anything any of the HLAPIs can do on their own

weak plinth
#

I find it weird to put something that small on the asset store

#

(Talking about my stuff)

#

I think it has a better place on git

jade glacier
#

yeah, really small stuff is a tough sell

#

and big stuff is hard to support

weak plinth
#

Not looking to make any money either

jade glacier
#

there are sweet spots

#

SimpleNetworkSync for me is hitting that

weak plinth
#

What would I ask, 3 bucks for like a collection of 5 classes

#

And besides, I don't want that shit that if someone finds an issue I "have" to fix it

jade glacier
#

its supportable, and obvious in what it does - and needed enough that people who look for it know what it is

weak plinth
#

I know myself. I will move on eventually and don't want to bother anymore with the past

jade glacier
#

Yeah, the Asset Store is not a fun place

weak plinth
#

If people have issues on git, fork it and make it better yourself ๐Ÿ‘

jade glacier
#

There are also different kinds of libs

#

ultily libs I totally make public gits

weak plinth
#

You know what I need? For someone to extend Net Sockets to allow send/receive with IntPtr

#

It's such an immense disapointment to see that it's literally 1 layer abstracted away

jade glacier
#

No one in the NCoders circle has done that?

weak plinth
#

It's just literally there in the source code, abstracted under one layer of byte[]

#

Not that I know of

#

They use enet or just udp sockets (from C?)

#

But you currently can't use the net sockets without using byte[]

#

Could probably make a dll and import the winsock (and the other platform specific ones)

#

Ugh, I have to go to bed

#

1.45am and I need to work tomorrow

#

I'm going to come in so late tomorrow ๐Ÿ˜ฆ

jade glacier
#

I need to get after some house stuff here and get back to coding, im off as well

gleaming prawn
#

@jade glacier > since they are TOTALLY outside of Mono and such

#

The thing is: what we use is 100% compliant, safe and robust to work under Unity IL2CPP (Unity is the target platform of choice, of course).

#

I don't think we have "luxuries", it's quite the opposite: we need to design stuff with the IL2CPP restrictions, and that is cross platform deterministic also when running from non-unity Microsoft .net (including .net core).

#

So the question is valid, I thinK: why can't you use similar approaches? I think you can and should...:)

jade glacier
#

When do you codegen then? @gleaming prawn

gleaming prawn
#

We codegen on a visual studio solution, even before the code is inside unity (but also works adding the solution to the unity one)

#

So we do all this before the unity build with IL2CPP

#

We codegen as pre-steps (we have our own compiler to do that)

jade glacier
#

Do you though create serialization out of users mono fields?

gleaming prawn
#

This is done automatically as part of the VS toolchain on our customers projects, etc

#

Do you though create serialization out of users mono fields?
I like to talk C# (or IL), we're agnostic to whereas this is Mono or MS compiler.

jade glacier
#

That is just one example, trying to get a sense of where your codegen is thing itself to.

gleaming prawn
#

What we have is:

  • lots of serialization utils (ByteStream, BitStream, similar to what Complex showed here);
  • we CodeGen the user fileds (from our DSL), so we also codeGen the serialization for those (super convenient for them);
  • we add user callbacks if they need to serialize custom data that they could not express with the DSL (this is very very rare)
#

We codegen as a pre-step, that's it

#

The code that's compiled by VS/Mono/Rider/Unity (whatever) is just normal valid C#...

#

We don't do anything crazy at runtime (runtime is sacred for performance)

jade glacier
#

Interesting, so you codegen though as people are typing?

#

The headaches we are having is depending on Unity to trigger the codegen based on the results of its recompiles

#

The two choices are to constantly re-check the ASMs with reflection whenever something triggers a compile in Unity, or to try to codegen right before building. It sounds like you have avoided that?

#

@gleaming prawn

gleaming prawn
#

Interesting, so you codegen though as people are typing?
No, pre-build event

#

Standard VS stuff

jade glacier
#

Where are you capturing that event though?

gleaming prawn
#

We're not... By default our users write the simulation code outside the Unity project, on a separate VS solution

jade glacier
#

In Unity land I haven't been able to isolate how to get that... if the player in Unity hits build or play

gleaming prawn
#

No fancy automation on change...

#

AND, we only need to CodeGen when you change the DSL

#

So this is not frequnt

jade glacier
#

I am not familiar with Domain SL in this particular case, I have only ever heard the term loosely a few times before. My lack of programming depth here.

#

I am assuming you are creating your own workflow in there for creating what becomes Unity code, you aren't "scraping" code for what they have done in their classes, structs and monoB types?

gleaming prawn
#

I don't modify user code at all

#

Our CodeGen is the first, independent step

jade glacier
#

When I was referring to luxuries, didn't mean to make it sound like you have it easy at all - I was more referring to that you have your own workflow, which sounds like what applies in this case. Unless I misunderstand?

#

In our cases, the worst case example is trying to generate code based on user fields on the fly, or at build time. Like for my stuff I specifically have to be able to generate serialization code based on users fields in MonoBs

gleaming prawn
#

Understood

flint swan
#

Has anyone used SpacialIOS / have much luck using it?

latent scaffold
#

Hey fellas. figured i'd pop in to ask if any of you know what networking solution i should use for an "mmo" type game (hate using that comparison), but essentially I'm looking to have a persistent world.

To put it simply, I'd like to implement a persistent world. I want to be able to start a server, then all the game data (player positions, inventories, stats, etc) gets saved before the server closes, then when you start a new server you can load the previous save to pick up where you left off.

I'm still new to networking so I'm not too sure where to start aside from trying to work it out with uNet

jade glacier
#

I wouldn't even really try anything like that right out of the gate. I would give yourself a few weeks to do tutorial on some of the libraries just to get a sense of where you are even starting, and what the language of networking is.

#

PUN2, Mirror, Forge, Bolt all are places to poke around for getting your toes wet.

#

The new netcode stuff if you want to get more llapi with things and are planning to do your entire project with DOTS, but its not really ready for new users by any measure.

latent scaffold
#

Gotcha thanks. I've heard good things about PUN2 and it seems like the best free option (just looking to use this game to learn and play with friends so i'd rather keep it simple/free for now). Do you reckon I could convert my simple project from uNet to PUN without much hassle or would it be best to start fresh with PUN?

jade glacier
#

PUN is an all relay environment, so it has some real perks and real downsides, which would take me 30,000 to explain al the ins and outs of... which is why its best to do tutorials on some of the engines, so that you can even make sense of the nonsense I would type now to explain it all to you.

#

I would do tutorials for a few of them

#

PUN2, Mirror and Bolt would give a pretty good indication of the three very different kinds of setups

#

PUN is relay, no server auth at all
Mirror is Unet, same as MLAPI and to a degree Forge is similar
Bolt is a full stack. It is fantastic IF it matches your game type needs, restrictive if not.

dapper spindle
#

Anyone managed to get Lidgren working in any version of unity 2019?

sick sigil
dapper spindle
#

Yeah latest version of the UnityEngine no longer has certain features that lidgren requires

sick sigil
#

Ah okay

dapper spindle
#

It has literally just killed our project as I cant find another networking solution that I actually like

jade glacier
#

Sounds like your stuff is pretty close to transport level if its using lingren currently, shouldn't be hard to swap in transport replacements

silk nimbus
#

hello any one with used photon here need a bit of help

weak plinth
#

Does anyone know if webgl and Android has crossplatform support with Photon?

undone sigil
#

@dapper spindle take a look at LiteNetLib, the author actually made it cause he had issues with Lidgren

upbeat basalt
#

Making an mmo in unity where the main source of communication will be a mix between tcp/udp and was wondering if there are any tools that are good for this in unity already or if I should just build it from scratch? Mainly from a security or ease of use standpoint.

gleaming prawn
#

@weak plinth AFAIK it does support that (if you are talking about PUN or Photon Realtime), as both platforms are support to connect to the servers, and if that works, the communication between them is intermediated fine.

As for Quantum, it doesn't support WebGL at all, as that platform lacks standardized support for native memcpy (which is a requirement for Quantum).

weak plinth
#

Lidgren has pretty bad perf. There are better options out there, like ENet

junior moat
#

@dapper spindle i got lidgren working

#

its still very usable

#

is photon not build on it ?

dapper spindle
#

I haven't looked into photon as I believe they use a CCU model, the problem is while in editor I could not get the client to connect and when built as soon as the server starts everything stops working.

junior moat
#

i got that running smooth

#

sending packets and all

#

i had to use an older version of lidgren before they added threading

#

well a type of thread lock

#

hold on its 4:09am and im pretty wasted

dapper spindle
#

See I could send and receive packets in editor as long as I was connected on my own local machine and not over LAN or WAN

#

Also our networking is threaded so that could be the issue.

junior moat
#

i got wwan working

#

however

#

what stopped me was i need a global server array or something to host all my netcode

#

i was thinking do i get mofos to install a client or something and run "hubs"

#

or find some billionares daugther and make her buy me computers everywhere

#

many chanllenges

dapper spindle
#

That shouldn't be the issue though I believe the reason for needing central servers was due to NAT Traversal which shouldnt be a problem as a simple port forward should fix the issue

#

I am currently trying to implement LiteNetLib instead which still isn't going well, its probably something to do with our threading but who knows

#

ยฏ_(ใƒ„)_/ยฏ

junior moat
#

lidgren says that port forwarding standards suck and his code may work and if it doesnt someone should just open a port as it up to the router owner dude... i dont know if thats a cop out

#

i look at other peoples systems etc like but lidgrens should be fine

#

im just too tight to go renting servers even if its just for lookups

dapper spindle
#

TBH I want to avoid renting a server just for lookups as if the project flops then its wasted money.

junior moat
#

exactly

#

im going to make more projects and if any stick and support that cause ill push out more lidgren

#

so many people use lidgren its a solid network layer

#

for many things

#

if unity fail us with thier netcode ill be using lidgren... even if i make like a "family lan game" without servers to introduce folks

#

but im sure unity will deliver eventually, networking is difficult

#

state sharing through packets distributed accross the world its crazy and we use it for games lol

#

crazy new concept man. ok its 4:20 am

#

im out bro

#

see you tmr

dapper spindle
#

cya

weak plinth
#

@gleaming prawn Thanks for the answer. @silk nimbus cross platform for webgl and android is supported

weak plinth
#

Hey, having an unity server build which only loads c# modules that contains logic at runtime and not having to deal with unity editor to re-build every change sounds like a good idea?

latent scaffold
#

Anyone here ever work with Unisave?

weak plinth
#

im finding very little tutorials about making your first online multiplayer game, i don't even really know what it entails compared to making an offline game. anyone have a good video overviewing how this works in the scope of unity?

weak plinth
#

In short, you need a way to synchronize everything you need to other players (via a server)

#

You need something (the server or client depending on the model) to actually make the decisions

#

And of course you'd need interpolation and such to smooth out the game instances of remote players

#

@weak plinth I'd suggest you start trying out some multiplayer related stuff with a really basic concept like pong

mellow beacon
#

and that's the absolute minimum considerations to put into a multiplayer game

gleaming prawn
#

@junior moat Photon uses a highly customized version of ENET

weak plinth
#

@mellow beacon Yeah

#

There's a reason why so many games either don't bother with multiplayer at all, or have a horrible implementation

weak plinth
#

hm. it's so weird to me that there's like absolutely zero up to date tutorials or explanations about unity multiplayer

#

if I understand correctly, unity multiplayer is sorta in limbo bc they said "unet is deprecated now, please wait for new network stuff" and,,, have yet to release that?

#

like, surely bare bones multiplayer example, let's say Pong, couldn't be all that complicated. I watched an presumably outdated UNET tutorial and it seems to be complicated stuff, wrapped up into an easier to work with API

junior moat
#

@gleaming prawn is photon not based on lidgren ?

stiff ridge
#

No, it's Enet based.

gleaming prawn
#

@junior moat no, as Tobias said here. Not based on lidgren at all. It's enet

weak plinth
#

@weak plinth many high level API's have severe drawbacks

#

Such as lack of configurability or performance

#

right ok but my point is, even the nicely wrapped up APIs don't have any up to date tutorials? what gives?

#

UNET is dead, and as for the rest

#

Multiplayer isn't straight forward to make, not even with hlapi's

#

@gleaming prawn Maybe a silly question, but does your bitstream have functions for signed and unsigned both?

gray pond
#

@weak plinth Mirror is the closest replacement for UNet right now. If you have any questions, please join our Discord and we'll be glad to help. UNet tutorials, while a bit dated, mostly line up with Mirror's public-facing API and components...just keep our docs handy to resolve any differences.
https://assetstore.unity.com/packages/tools/network/mirror-129321

weak plinth
#

Mirror is built and tested for MMO Scale Networking
Do you still have this on there?

#

I wouldn't exactly call 207 CCU on a Xeon W-2145 8 Cores x 3.7 GHz at 95% cpu "MMO Scale"

#

But whatever

gray pond
#

Depends which transport one uses. Telepathy hits a Unity-imposed limit at 600CCU. Apathy can go much higher because it lives outside the Unity context, but now we're in the realm of where the game's own resource demands are the limiting factor vs. the networking.

weak plinth
#

What do you mean now we're in the realm

#

That should always be the case

#

If your game's networking is using more resources than the actual simulation, you've done something horribly wrong

gray pond
#

ok you're nitpicking my choice of phrase now. o/

weak plinth
#

Maybe use better wording then, so it's understandable

gleaming prawn
#

@weak plinth yes, both unsigned and signed, separate functions.

weak plinth
#

Thanks. I'm browing around a bit which one I should use

#

You are using a is_writing type right? (reading/writing with the same function)

gleaming prawn
#

yes, makes our serializers code smaller, and we're used to this semantics

weak plinth
#

I've seen it in other projects as well

#

All the if statements have minimal perf impact then?

#

(Does make me understand why you use ref value ๐Ÿ™‚ )

gleaming prawn
#

It hasn't been a bottleneck for us.

weak plinth
#

And a last question, do you support all primitives?

gleaming prawn
#

Let me confirm

#

A few more...:)

#

We have our FixedPoint types as well (these are wrapped Int64s, etc)

#

But for streams we can also serialize strings, of course

#

We normally don't use strings in runtime high-frequency messages, but the streams are reused for everything, and handshake messages might include GUIDs, etc... Also some infrequent commands may use strings (although we don't recommend customers using them in this case)

weak plinth
#

I'm still figuring out how to do strings ๐Ÿค”

#

Without allocating that is

gleaming prawn
#

Because we only use this very infrequently, we do allocate... Strings should NOT be part of regular runtime messages...:)

weak plinth
#

No, I figured ๐Ÿ™‚

#

Why do you use #bits instead of a maxvalue?

gleaming prawn
#

These are the RAW methods...

#

maxValue can be used as syntax sugar

#

Remember we're not using this to transfer STATE

weak plinth
#

No, this is just serialization

gleaming prawn
#

At least not regularly as a state transfer/snapshot interpolation library

weak plinth
#

Or do you mean that this entire thing is not used with states at all?

gleaming prawn
#

We have several different overloads and variations on top of this.

#

"Or do you mean that this entire thing is not used with states at all?"
In quantum we do not transfer states regularly...

weak plinth
#

Oh yeah, inputs

#

Right

gleaming prawn
#

And when we do, it's for a late-joiner or reconnect (full state), so we do bit compression on top of the whole stream

#

We don't bother with delta compression in THAT case.

#

For input we have different strategies for compression.

weak plinth
#

The biggest portion of data send are the inputs, no?

#

You don't use bitstreams for those?

gleaming prawn
#

we do, but we compress differently (most cases compression is not needed actually)

#

The meta-data has a bigger impact than the actual input data (which is minimal)

#

So it has been much more important to be smart with the meta in all the different use cases, etc...

#

We have some mobile 32-player games released (which is not something most people think is even possible with determinism - people tend to think of old lockstep issues - something we don't suffer from due to the server which has authority over the input stream).

weak plinth
#

Trying to wrap my head around all of this is pretty difficult

gleaming prawn
#

๐Ÿ™‚

#

Games are live, running with full deterministic predict-rollback and 32 players (on mobile!).

jade glacier
#

I couldn't get my head around quantum for a while either @weak plinth because I was assuming that the final word on user inputs was part of some kind of agreement between all clients, which made no sense. Once fholm pointed out there is an authority server for the final word on inputs, it all cleared up.

graceful zephyr
#

came out on friday

jade glacier
#

morning/evening @graceful zephyr

graceful zephyr
#

o/ yo

weak plinth
#

Nice! Bookmarking this

jade glacier
#

@weak plinth https://hatebin.com/

Codegen is working nicely (other than still struggling to find the ideal timings from unity to generate/destroy it)... but the gen'd code is getting less and less human readable. It does all resolve out though to just delegates at runtime, so should be fast.

weak plinth
#

Why would you use a min-max range? Rather than just a max?

jade glacier
#

for an int?

weak plinth
#

For any numeric value

#

I saw this in FSE's bitbuffer as well

jade glacier
#

because zero isn't always the min

#

ints go negative

#

most common case will be 0-X, but no need to bake that in

weak plinth
#

Ah yes I forgot about that ๐Ÿ˜…

jade glacier
#

its an addition and subtraction away from allowing any min/max

weak plinth
#

I've been tinkering about a good API that isn't too verbose

#

But I think it's going to be pretty verbose

jade glacier
#

I just rely on default arguments heavily for that

#

behind the scenes there is a LOT of variables

#

but you can in this case just stick [Pack] on a field... and it will run the defaults

weak plinth
#

I'm going to serialize all by default

jade glacier
#

So basic use case, just [PackObject] on the class or struct, and [Pack] on any fields you want included

#

I debated that, but decided having to switch off fields is more annoying than switch on

weak plinth
#

It's a lot of extra work setting up your objects now

#

Rather than just nonserialized above the exclusions

jade glacier
#

Though you could make that a switch in the object attribute

#

[PackObject(Serialize.All)]

#

[PackObject(Serialize.Marked)]

#

something like that

#

@graceful zephyr I assume on the topic of Quantum, that you have variables for things like induced delay, and I assume knowing you you also have some kind of automatic delay feature that factors in the round trip times of players, to create a balance between delay and extrapolation?

foggy vale
#

hello guys

jade glacier
#

morning

foggy vale
#

is evening here ๐Ÿ˜‰

#

berlin clock

jade glacier
#

America is the center of the known universe though... get on board.

foggy vale
#

๐Ÿ˜ฉ thats a funny statement

jade glacier
#

Not in America it isn't LOL

foggy vale
#

lived in the US for 2 years... in boston, it feels like a very provincial place

#

also lived in new york

#

and visited the rest

jade glacier
#

I'm from the east coast, so I know the "vibe" well

#

very different from west coast usa

foggy vale
#

yeah it isn't the center of the world... more like a suburban perifery

#

west coast I don't know well

#

I was happy to leave... lot of ignorance and a very low quality of life

jade glacier
#

east coast = "Fuck you"
west coast = "Let's try to all get along"
south = "Passive aggressive niceness"
north = "Howdy"

foggy vale
#

๐Ÿ˜„

#

ok let's get back on topic... could ytou advice me about this two libray:

jade glacier
#

yeah, we spend as little time in the US as possible these days

foggy vale
jade glacier
#

I have to be back there for 4 months a year to play in my bands, and that funds my being abroad the rest of the year.

#

We dread going back

foggy vale
#

sne dme a link to your bands

#

I can listen to that meantime

jade glacier
#

Not originals, they are working cover/tribute bands

#

Basically just cash cows

foggy vale
#

--- about the libs... I was doing serialization by hand but decided to try a lib supporting polymorphism and classes serialization before my project get's bigger

#

using new unity llapi preview

jade glacier
#

is your net serializer byte or bit based?

foggy vale
#

the datastream writer supports only standard types... no structs or classes

#

byte

#

if i use datastream writer

jade glacier
#

FSE's variation of NX's packer is a good balance of speed/features and mixing byte/bit packing

#

Any byte reader/writer is probably going to look about the same these days

#

unless its just badly written

foggy vale
#

the two libs I posted seems to be the most performing ones supporting custom classes

#

but ceras uses extended generated code

jade glacier
#

There is an upper limit to "performance" on them, so if its good... its good

#

unless you start making choices about things like pinning your byte[] at the start of serialization and passing around a pointer

foggy vale
#

could you tell me if the second supports polymorphism?

jade glacier
#

polymorphism in what context here?

weak plinth
#

Advice? What kind of advice?

jade glacier
#

You mean that you can just throw whatever object at it and it will come up with a default serialization?

foggy vale
#

y

#

right

jade glacier
#

yeah, don't do that

foggy vale
#

@weak plinth choosing betweent he 2 libs I posted

jade glacier
#

First thing with that is you will want to differentiate between ref types and structs

foggy vale
#

?

#

why?\

jade glacier
#

I see reflection going on in there

foggy vale
#

I mean if we re just talking about serialization... having a library that can serialize classes helps...

jade glacier
#

hopefully that is one time

foggy vale
#

in which one?

jade glacier
#

I see emit, so I assume its one shot

foggy vale
#

it is generating code at runtime.... so not much refl I guess

jade glacier
#

Seems similar to the stuff Complex was trying to make happen

foggy vale
#

maybe he could find it useful then

#

seeems to be a very smart implementation

#

we are talking about the ceras lib right ?

#

the first linki

jade glacier
#

I'm not looking that closely, was just poking at netserializer

foggy vale
#

I'm getting tired... there is 1000 libs doing a similar thing and is very hard to choose

#

but this 2 seems very interesting

jade glacier
#

Just abstract your code from any of it, pick one and refactor later if needed

foggy vale
#

that's not possible atthis level

jade glacier
#

But generally for regular tick traffic, any autoserialzation is going to be bloated

foggy vale
#

or very hard at leastr

#

the way I structure my data depends on it

#

ok thats interesting

jade glacier
#

your serialization just sit inside of the Serialize/Deserialize methods, and you should be able to revisit what goes on i n those methods later

foggy vale
#

you mean slow as hell?

jade glacier
#

nah, just uncompressed

foggy vale
#

yeah but I represent my data based on serialization

jade glacier
#

or limited in how you can compress it

foggy vale
#

if I can't make an extensive use of polymorphism then things change

jade glacier
#

why based on serializaton? serialization for networking involves a LOT of culling, packing, RLE compression and whatever else you can throw at it

foggy vale
#

I'm talking about the way I represent the data

jade glacier
#

the idea is that you take a struct/object and pack that into a byte[] as tight as you can... and on the other end reproduce that byte[] back into your object

#

Maybe I am just misunderstanding you

#

your serialization is packing stuff into a byte[]

#

it doesn't have to directly coincide with that stuff in your object

#

heading off to breakfast

foggy vale
#

if I have alibrary that automaticly sends any class I have over the net

#

I may just organize my data ina more confortable way

#

but I have to choose now

#

if I want to serialize by hand I would use a different data structure

#

good breakfast

jade glacier
#

the serialize and deserialize methods just need to match up

foggy vale
#

y

#

not the methods

#

you mean the output

#

I mean that I'm concerned about what to pass to them as input

#

because that changes the way I organize my data

#

and this tdepends on the library I use

#

that's why I needed an advice ๐Ÿ˜‰

#

(I messed up the writing,, just tired... )

weak plinth
#

I'm busy writing something what you probably want, though it's not done yet

#

Also, I'd recommend using structs to represent data over the network

foggy vale
#

@weak plinth what would be the easier to serialize a struct? I ended up using this lib that allows me to easily send serialized classes or structs, but I'm not sure about the overhead

#

unity serializer in the new llapi doesn't serialize structs

#

talking about the datastreamwriter

weak plinth
#

If the struct is blittable, you can take the offset of the fields and use pointers

foggy vale
#

implementing it my way in an unsafe method? heard is not advisable to deply on multiple platforms

weak plinth
#

What's unadvisable for multiplatform?

foggy vale
#

that while compiling for multiple platform going usafe can create problems downstream... didn't further investigate

weak plinth
#

Depends what exactly it is you do

#

But pretty much, no

#

Pointers can differ in size x32 vs x64

#

As well as booleans

foggy vale
#

could you advise about a wide spread library that does just that?

weak plinth
#

I don't know of any

#

That's why I'm writing my own

foggy vale
#

I'm trying not to ulosse control by using something overcomplex... but I also don't want to reimplement something done 1000 times by others

#

netstream for example

#

seems to be widly used

#

hem.... i think was called netserializer... posted a link just up

#

are you trying to implement something that does exactly that?

weak plinth
#

Eh

#

This uses IL

foggy vale
#

you think isnt a good implementation?

weak plinth
#

You can't use this with Unity IL2CPP

foggy vale
#

great... I must have missed that

weak plinth
#

There's a table somewhere that tells you which platforms support mono

#

It's not a lot

#

Reflection.Emit is not usable in IL2CPP builds

#

The closest thing you can get to this is using mono.cecil

#

But that requires you to alter an existing dll and save the changes

#

IE, you have to run that code everytime you build (before the build)

foggy vale
#

ok, so no way, thanks you saved me sometime

#

this could be interesting for you

#

it is IL2CPP compatible

weak plinth
#

I've seen this

foggy vale
#

but it as a lot more functions, like polymorphism

weak plinth
#

But it has a lot of overhead

foggy vale
#

really?!

#

could you tell me more?

weak plinth
#

Well, for one it converts to byte[]

#

And apparently, it uses setvalue/getvalue

#

which is insanely slow

foggy vale
#

isn't converting to byte[] what most serializers do?

weak plinth
#

Perhaps, but you'd want to be able to get unmanaged memory preferably

#

So you can avoid GC allocations

#

Worst-case scenario, you can use a fixed byte[] buffer that floats around somewhere and lives for the lifetime of the game

#

Also, his serializer is a class

#

So everytime you create one, you have gc

foggy vale
#

what if I use it only with structs?

weak plinth
#

The serializer you have to create with his thing is a class

foggy vale
#

do I care?

#

I may have 2 serializer classes

#

in the whole project

#

the developer really stresses that the implementation is GC "optimized"

#

about the getvalue/ setvalue, I had no idea they were this heavy

weak plinth
#

And I'm not too sure about his actual write/read implementations

#

Not sure about the perf of this

#

You can always give it a try and profile it

#

See how much it allocates

foggy vale
#

mmmm

weak plinth
#

Or be patient and wait until I'm finished with mine ๐Ÿ™‚

foggy vale
#

you really think that allocation is so bad ๐Ÿ˜„

weak plinth
#

Yes. Especially for networking, it's easy to rack up a lot of GC

foggy vale
#

you mean here?

#

var value = Unsafe.As<byte, int>(ref buffer[offset]);

#

I'm struggling to understand here

jade glacier
#

Trying to avoid reflection at runtime is the hard part with this stuff

#

I'm working the same problem right now as well

#

And I have opted for straight up code gen, which has the headache of "when" to do it

#

Trying to codegen using unity callbacks pre-DOTS is painful

#

like you can't codgen in OnPreProcessBuild

#

your code will generate, but not make it into the asm

#

Which leaves either having users manually generate as needed, or to check the asms after each compile to see if anything that matters to your has changed.

foggy vale
#

hey guys, in the new unity llapi this is how you send over an udp driver:

#

int Send(NetworkPipeline pipe, NetworkConnection id, DataStreamWriter strm)

#

int Send(NetworkPipeline pipe, NetworkConnection id, IntPtr data, int len)

#

the documentation suggests to use a disposable datastreamwriter object to prevent keeping allocating memory

#

using (var writer = new DataStreamWriter(200, Allocator.Temp))

#

__

#

isn't this less efficient than having a persistent allocated buffer?

#

this is a link to the lib

#

More in detail... I'm using a lib that sereializes over a byte{]

weak plinth
#

I'd say yes. But I don't know the lib in detail

foggy vale
#

now it seems stupid to having to write in a datastream buffer (thus serializing) and already serialized byte{]

#

but since I can only pass to a send a datastream object, how am I supposed to deal with it?

#

@weak plinth that's a suggestion form the guide... I can allocate the buffer in the datastream as persistent avoid the using {} part

#

at the end is my choice... I'm wondering what could be the problem with that

weak plinth
#

Why don't you use an IntPtr instead?

#

I don't know what the datastreamwriter exactly entails

foggy vale
#

could you explain me how to pass an intptr to the function?

#

a datastream writer is just a unity serializer, very basic, that has a pointer to a buffer

weak plinth
#

IntPtr is a type, if that's what you mean?

foggy vale
#

A platform-specific type that is used to represent a pointer or a handle.

#

do I get in trouble using it? what's the usage if I want it to point to my byte[] buffer?

#

got it

#

I just have to allocate heap memory to an intptr

#

and it becomes my buffer... thus have to use MArshal..

weak plinth
#

You shouldn't need a byte[] at all if you use IntPtr

#

The difference is, one is managed and the other one isn't

foggy vale
#

int Serialize<T>(T obj, ref byte[] buffer, int offset = 0)

#

tha't what my ceras serializer takes

#

can I give it the intptr somehow?

weak plinth
#

Probably not if the guy isn't using that

foggy vale
#

is there a way to go around it?

weak plinth
#

Nope. That's the way his API is

#

I mean, I have a serializer that you can use to serialize stuff by hand currently

#

That does use IntPtr

foggy vale
#

does it serialize custom struct/class?

weak plinth
#

Not automatically

foggy vale
#

what do yo mean?

#

could you post the usage of some methods?

weak plinth
foggy vale
#

@weak plinth seems this does more or lesst what the datawriter from unity new llapi does

#

I didn't check for performance

#

but very nice code, had already bounced in your lib before

#

I'm at the point where I'm considering using structs thus a need a lib able to deal with custom structs

weak plinth
#

I'm making that atm

foggy vale
#

I'm writing with the author of the Ceras lib I showed you

#

he is willing to help me bypass the byte[] thing... using directly a IntPtr

foggy vale
#

@weak plinth I'm getting a bit scheptic ... but you gave a fast look at this Ceras and there was nothing worring with using it right?

weak plinth
#

I think it uses getvalue and setvalue from Reflection

foggy vale
#

maybe not 100% the fastest.... but more than fastenough

weak plinth
#

Its quite considerably slower than a direct method call

foggy vale
#

but that's maybe forced to be able to generate code to handle custom class/structs?

#

I'm asking because this is beyong my understanding... I guess more at your level

#

or this is just a very bad implementation and I should drop the lib?

weak plinth
#

Profile it and see if it fits your use case

foggy vale
#

I'm not good enough to profile 10 libs and choose the best case for my appllication

weak plinth
#

The best case is any one that you choose and causes no bottlenecks for your application

jade glacier
#

I still think you are WAY overthinking your serialization

foggy vale
#

you know... overthinking people are rare this days... everyone is writing shitty code... I'm a bit old school ๐Ÿ˜„

jade glacier
#

that thinking goes two ways though. These networking channels are full of guys all making the same low level stuff with nothing actually finished or even to show. Its one thing to leave bad code forever un-fixed or refactored... but that is just good planning and time management.

#

Serialization is super compartmentalized if you code that right, and you can change your mind many times later on it.

#

I've refactored my serialization a bunch of times, and likely will have to do it again to change everything to IntPtrs and go pure unsafe

#

But not doing that up front didn't stop me from producing an entire component library

#

I mean, you do you - it just seems like you are buried in the same muck so many others in these networking chans get buried in

#

Granted, I have no clue what you are actually ultimately making.

foggy vale
#

It is a midLib for a game

#

basedon the new llapi

#

You see I already went to the IntPtr stuff... avoiding refactoring ๐Ÿ˜‰

jade glacier
#

95% of game networking coding work is in the simulation creation

#

This serialization stuff should take like a day to pick something

foggy vale
#

Just trying to keeep the vibe positive and get out of the muck what ever it is ๐Ÿ˜„

#

yeah.... let's see , I'm very old school slow ๐Ÿ˜‰

jade glacier
#

If this is pretty much hobby work, whatever pace suits you and is fun for sure