#multiplayer

1 messages · Page 169 of 1

thin stratus
#

Yeah, can't really run the sim on 30hz and have the Elite Gamer rock their 165hz monitor

#

Or whatever is the norm..

tardy fossil
#

i wish there was fixed tick 😦

lament flax
#

isnt 100 big when set to actors that are not used a lot ?

#

does lowering the value make it skip replication ? or does it just delay it ?

#

for eg, for a door i could lower it a bit since not 100 players will try opening it at the same time

lament flax
half umbra
#

hi, someone can look in #blueprint I need an expert

chilly haven
#

Hi,
I 'd like to cleanly separate my client and server code, since I am not supporting listen servers.
In other words, I want my client binary to exclude server code at compile time, and vice versa.
I have therefore split my code into server, client and shared modules.
However, now hitting the UHT issue that you can't use UPROPERTY() etc inside a conditional block.
So for example my player controller class creates various client-only objects on the client, and those are UPROPERTY member variables.
How can I exclude those for the dedi?
Thanks!

#

(I have a #define hack that may work... but I don't like such hacks)

hollow gate
# tardy fossil i wish there was fixed tick 😦

you can , i just posted a "little" video about this . doesn't go much in depth. but you can use fixed. https://www.youtube.com/watch?v=ltNaPfHwxhE

Quick Overview Of Mover, Explaining Biggest Complaint about the 5.4 mover, The "Jitter". Talking about what you can do to fix it and what possibilities the network prediction plugin allows.

▶ Play video
woven basin
#

sorry for the necro of a few weeks - have you seen any tutorials/guides/blogs that describe a better way that you've hinted at? I understand what you are saying, just looking if anyone has more on this before I delve into this exact topic

hoary spear
#

Matts approach (sounds pretty much like Lyra) is possibly a better alternative

#

The superstructs tend to carry to much unnessesary crap for every item 😅

#

Like why do my Rock item entry have Socket data, Enchantment data and other bonuses? They cant ever exist on the rock

quasi tide
#

Until you want to create a situation where the Rock is enchanted

hoary spear
#

One could ofc separate them and replicate them side by side

#

Extra work, and some linking but avoids the unessesery data when it doesnt exist (beyond some link of type integer or smth)

#
FItemBaseData
{
...
Int32 EnchantmentIndex = -1;
Int32 SocketIndex = -1;
}
TArray<FItemEnchantData> ..
TArray<FItemSocketData> ..
#

Not sure if this would be any less tho

#

If this is all the fragmentation there is, then possibly. But easily becomes massive aswell

#

And can be painfull to maintain

lyric heart
#

what are some things that would cause creating a session through steam to fail ? it's connected to steam, but it won't create session

hoary spear
#

Editor?

#

No app id ?

lyric heart
#

maybe the app id is bad

#

that could be one thing i'll have to look at that

hoary spear
#

480 is the testing one iirc

lyric heart
#

i have it set to 480 in DefaultEngine.ini

graceful flame
#

I have a strange spawning issue where the location im trying to spawn an AI character is ~50,000 units away from my possessed character and it won't spawn. If I move my character closer to the spawn location and trigger the blueprint again to make it spawn the actor then it works. I think it has something to do with net cull distance because the bug goes away with standalone mode. But I checked the values and the AI character is using the default net cull distance of 225000000.0 which is far larger so I don't see how it could be the cause of the issue.

lament flax
#

maybe the cull distance has to be applied on player

#

and not the AI

#

(or both)

graceful flame
#

but its all using the massive 225000000 default

#

so im well within that range at all times

hoary spear
#

Sure thats not squared?

graceful flame
#

yea so what's that mean in distance units then?

#

im not sure about the math

hoary spear
#

Root if im not mistaken

lament flax
#

if its squarred then its v225000000

hoary spear
#

15k

lament flax
hoary spear
#

Could that be correct ?

graceful flame
#

ughhh that's much smaller than what I need

lament flax
#

its kinda logic that its in square distance

#

maybe easier to do math with sqare than circle

graceful flame
#

no wonder LOL

hoary spear
#

Squared distance is cheaper mathematically

#

50k^2

#

2 500 000 000

#

Not sure ifnit accepts that input nor how much imoact that'll make 😆

#

How come you need to spawn itnso far away?

graceful flame
#

Well the AI is spawning on the other side of the level

lament flax
#

well

graceful flame
#

that works, thanks for being so smart you smart people you!

lament flax
#

the ator is still spawned right ?
its just that your player isnt replicating him yet

#

when you will get closer you will load him

graceful flame
#

I just used some massive net cull distance number for these AI characters who should always be relevant anyways

#

no I looked on the level outliner and it doesnt get spawned in at all which is a problem

lament flax
#

is your player the listen server ?

graceful flame
#

no its dedicated

lament flax
#

weird

lament flax
graceful flame
#

I use a widget for testing to click a button to spawn the AI characters in the "respawn room" then they run towards a "role selector" which then spawns them elsewhere on the level as a different character and destroys the old one. Problem was that distance was greater than the net cull squared distance (which I didn't know was squared lol) and so they failed to spawn in.

hoary spear
#

Center that room 😁

#

So its never culled

#

Just place it below the map

graceful flame
#

oh yes I see now they do spawn in once I move closer to them I was confused because on the scoreboard they appear as "dead" even though on the server they're alive but by the time I got to their location they died to other actors anyways. Silly ai bots.

#

I tested again and moved my character within the default net cull distance and saw they were alive on the scoreboard and hadn't died to other actors .... yet.

#

So that means all I have to do is fix a bug on the scoreboard so they appear to be alive even though my character isn't within the net cull distance which was giving a false report of "dead".

hoary spear
#

This means they wont start before within range of player tho, right?

graceful flame
#

and they appear as "dead" on the scoreboard because that's the default behavior

#

Well they are starting and interacting with the level just only on the server because of the net cull distance is hiding them on the client.

frosty crag
#

guys how can I not replicate something done on the server, if you wonder why it's done server side it's because it's a listen server so the server is also an instance of the game

mystic estuary
frosty crag
#

@mystic estuary yes but lets say for example you want to hide your pawn for the other but for you in local just change the material like a invisibility spell how do you do xD the pawn has to be replicated

mystic estuary
#

Just make the pawn invisible on remote clients, you don't have to stop replicating the pawn

frosty crag
#

@mystic estuary yes but if for example a client is using his spell, for the client in local you change the material, but on the server session you hide it right ? but if you hide it, it will hide the pawn for everyone because the action is done server side am I wrong ?

mystic estuary
#

SetActorHiddenInGame is replicated, yes. However, you could ignore that on owning-client: anytime the property is changed, change it back to false on the player that is using invisibility potion locally. Sadly, the bHidden property doesn't have an OnRep function, so there would be a harder way of ignoring the true state, nevertheless, it's not impossible.

frosty crag
#

yeah but this is fighting with server, and I don't like that ... What about hiding the component and not using actor hide in game

#

maybe it's not replicated I will test !

#

Yes !! that's working !

mystic estuary
#

🥳

frosty crag
#

is there a way to put a delay in a function in blueprint ?

eternal canyon
#

functions are not meant to be latent in blueprints

frosty crag
#

ok

eternal canyon
#

as they are meant to return asap, in bp

maiden flame
#

What multiplayer functionality makes GAS worth using, besides client prediction, responsive root motion replication, and easy replication of montages?

I don't have a game where I need to manage a lot of different states with tags, damage types, resistances, etc.

So in terms of pure multiplayer functionality, does GAS do other important things under the hood? I mean stuff like more optimized montage replication (as opposed to RepNotify and Multicasts), or if it handles packet loss for montages/abilities more "gracefully".

Secondly;
Is GAS beneficial, or even viable to use, for its multiplayer capabilities alone? I mean without utilizing every aspect of the plugin, such as Gameplay Effects, or at least to a minimal degree. Can GAS shine without organizing all your gameplay within its structure, and feeding everything through it? Or does it require you to handle all gameplay elements, such as health and damage, within the GAS system?

I am not opposed to this, but I would like to know if it's viable to integrate GAS alongside your own systems, and only use it for certain functionalities. I already have a vertical slice of my game, and I don't see the need to refactor everything into GAS if it is not necessary. Hence I am curious if it's reasonable to only use a few functionalities that I want from it.

Thanks in advance for any advice!

#

Let me know if I should move the message to #gameplay-ability-system. It's sort of a two-sided question, so I was unsure where to ask. I'm mostly interested in learning about the first part, concerning multiplayer.

hollow eagle
#

Prediction is the primary benefit.

#

That is not a small benefit, it's pretty important.

maiden flame
#

True, but I was able to create predictive montages with Blueprints.

hollow eagle
#

Yes, but do you have a system to rollback mispredictions? Do you have a way to confirm whether a client successfully predicted something? Do you have a way to predict a fast-changing value without the server's confirmations stomping on your newly-predicting changes?

#

It's not as simple as predicting montage playback.

#

I'm not telling you to use GAS just for prediction, just that prediction is way more than just playing an animation.

maiden flame
#

You're right. Does GAS offer functionality to help with those things as well?

hollow eagle
#

Yes.

maiden flame
#

C++ mainly, or Blueprints as well?

hollow eagle
#

The complex parts of prediction must be handled in C++. Some of it is handled for you automatically, which mostly makes blueprint unaware of it.

#

Anyway, if you're going to use GAS then you generally should be integrating just about everything you can with it. As a framework it likes to take over a project.

maiden flame
#

Understandable. Really appreciate the insight, thanks.

maiden flame
#

Had a quick skim of that, but I'll go over it more carefully.

#

How does GAS handle rollback of abilities? I mean, without the plugin if you predict an event wrongly, the server will correct you anyway.

#

What's the difference?

#

I see the part about prediction keys, but doesn't the CMC and RepNotify functions do something similar when locally predicted?

hollow eagle
#

GAS does not handle character movement prediction

somber glade
#

If I have a boolean set to repnotify and when an actor is spawned by the server on begin play it sets that variable to true (it's not default true) and a function is set up to do something (change a material, etc) when a client joins after, that should run correct?

maiden flame
# hollow eagle GAS does not handle character movement prediction

Sorry, I should rephrase. Does GAS handle rollback/server corrections smoother than a corrected, locally predicted RepNotify event?
I can't tell the difference, besides the potential for value stomping as you mentioned.

They still rely on similar fundamental parts of replication within the engine, right?

hollow eagle
#

There's no smoothing, GAS prediction is designed for instantaneous actions, it is not suited for something that needs a buffer for rollback/resim like movement.

maiden flame
#

Gotcha, that makes things clearer. I did see someone link a video about using NPP for smoothing corrections, so I guess that is partly where it comes in.

hollow eagle
#

Yes, NPP is much more suited for that type of prediction as it sets up a more generic framework for rollback/resim.

#

GAS prediction keys are usable outside of GAS itself, though you then have to implement sending/confirming/rolling back in your own systems.

maiden flame
#

Thanks!

maiden flame
somber glade
maiden flame
somber glade
# maiden flame BeginPlay of a player character?

Begin play for a spawned actor. Actor spawned by the host/server. pulled off switch has authority. Actor is present, actor is replicated, but the repnotify just didn't fire. Even stuck a print string on it to be sure.

maiden flame
#

If I remember correctly, event OnPossessed in the character BP only runs on the server, which is who should set the notify in order to replicate it.
Otherwise, just call a server RPC on BeginPlay.
Use a print string for OnPossessed, before setting the notify, to make sure the server is called.

somber glade
#

not a character, this is a random actor in the scene.

maiden flame
#

Hmm, and you know that the server is calling BeginPlay of the actor?

somber glade
#

Yes, because when I had it previously as a multicast the multicast was called off the begin play. I've temporarily fixed it with another function for now, but I'll have to do some more testing later

marsh seal
#

Hello everyone!
Is there anyone who would be up to guide me for like 5 minutes via a call? You don't need to have a mic hehe

maiden flame
somber glade
hollow bridge
#

Anyone knows?

olive crow
#

is TSubclassOf replicatable?

fossil spoke
olive crow
#

So if I had it as a member on some component/actor of type TSubClassOf<UUObjectDerivedClass> with defined GetLifetimeReplicatedProps it will be replicated right? I'm asking cause I know UObjects aren't replicatable.

steel vault
#

Hello multiplayer experts. I'm using a custom CMC with safe moves to launch my character at another, but when they collide, the client is showing a ton of net corrections I suppose due to the fact that the other character is stationary and the client hits them before the server does. Is there a decent way to fix this? I'm looking to launch at the other character and continue my motion or at least if I get stopped not rubber band everywhere... Also, when the character gets close to the other, it launches them as well so that seems to be adding to the confusion as the client version seems to be off from what the server launched target seems to be.

fossil spoke
#

UObject Instances are not replicated out of the box.

#

TSubclassOf is a pointer to a UClass

#

The Engine can resolve that across the network because every machine will always have the UClass being pointed to.

olive crow
#

I see, so it will work then, thank you!

steel vault
dusky cradle
#

Hi i started learning about Character movement component, and it mostly says it's useful for multiplayer games since it transfers the data towards the server side, the thing is if it's without a physical server , like a multiplayer with a pc-hosting & clients configuration is that still useful or i should keep the usual movement system witch is client sided ?

fossil spoke
woven basin
#

why do you think GMC is not a path forward for the movement stuff?

fossil spoke
#

There are very few usecases where Client Authoritative movement is necessary.

dusky cradle
dusky cradle
fossil spoke
#

As a new user you should never need Client Auth movement.

steel vault
#

Hmm I'm curious if my launch abilities would be considered high speed movement. I'm launching forward 1000 to 2000 u/s sometimes and knocking back about the same. Wonder if that's also contributing.

devout sonnet
#

I bought a rock paper scissors multiplayer game on the UE launcher to help me understand how to make multiplayer games.
I can't say it has helped much.

echo pasture
#

is there a limit to how many replicated variables one can put

#

just the number alone, not related to how often they are being changed

fossil spoke
#

@echo pasture Not that I am aware of?

#

Whats prompted you to ask such a question?

obtuse field
#

I mean, to not choke the buffer

fossil spoke
#

The NetDriver does impose bandwidth limits

obtuse field
fossil spoke
#

His question was specifically is there a limit to how many replicated variables you can have. He also specifically stated that he was ignoring any limitations on their replication.

#

I answered his question as he asked it.

obtuse field
#

Ik, I must've misunderstood

zinc acorn
#

for some reason i cannot travel a specific level but all other levels seem to travel just fine? whenever i try to travel to this level it just puts me back in the main menu

#

on build it just gave a black screen

grim rain
#

hello what would be the best method for creating a money system for a multiplayer game? would it be in the game instance since they will have different player controllers?

steel vault
#

Hmm I seem to be confused about Safe movement variables in the CMC. Right now I'm using them to perform movement abilities which properly predicts on the owning client and sets it properly on both the owning client and then the server. However, the simulated proxies do not see things properly because the Safe variables are not replicated. For instance, I enter into fly mode by setting a safe variable bWantsToFly to true which is then checked in the update movement function to properly call the launch and switch to fly movement mode. When I want to toggle the safe variable to false to exit, it works fine on the owning client because it's changing it and pushing up to the server to match. When I do this same thing on the ListenServer, it immediately exits because bWantsToFly is always false on the simulated proxy due to it not replicating. Just now I added property replication to this variable and marked the CMC as this component replicates and it seems to now only call on the server without exiting like it has been, but this feels wrong. What am I missing?

echo pasture
#

if variables are being internally copied and moved around or something idk

fossil spoke
obtuse field
obtuse field
zinc acorn
obtuse field
zinc acorn
#

no other levels besides this specific level do this which is the odd part

#

like i can travel to other levels fine which is odd because i can also load into it from the main menu fine too

obtuse field
#

Can you send the logs?

fossil spoke
#

Did you forget to enable Seamless Travel?

zinc acorn
zinc acorn
obtuse field
# zinc acorn

Have you tried to remove broken asset from the level?

zinc acorn
obtuse field
#

Or, is it level name?

#

Ye, it is, mb

zinc acorn
#

the level assets store level info so i can put it on the loading screen and such if that makes sense

#

like it stores name, path image, description

#

and then i get the path and pass it to the level loading function

#

but yeah it may be the levle asset for some reason which would be weird

#

will investigate some things

slow wing
#

How do people handle respawns that have an animation and move players? I seem to occasionally have the issue where the packet with position does not arrive the same time as the packet that restores a players health / plays the respawn animation. These things are all set on the same frame for the server, but their replication is not atomic, and this results in clients occasionally seeing simulated proxies rez in place before suddenly teleporting. This can be rather misleading during gameplay, does anyone have any elegant designs to tackle this?

obtuse field
zinc acorn
#

ok weird update i added it to my level pool asset thingy and it just started working for some reason???

#

strange

slow wing
#

I guess pawn destruction is a way to force it, but I kind of dont want to go that route, theres a lot of players and they die often, dont want to reinit the pawn that frequently ideally

obtuse field
slow wing
obtuse field
slow wing
#

I could, but there is also the matter of the health value being restored. I could similarly make an exception for that, but there might be something else in the future etc, so I am a bit hesitant to take that route

#

I dont know if alternatively, forcing the actor channel to close and reopen for all connections (Except the owner) could work

obtuse field
slow wing
#

I effectively need the transform to replicate either in sync or before anything else, if I reduce the problem it's core issue

slow wing
obtuse field
slow wing
#

I will probably consider that as a fallback approach. The issue is also that some effects (like invulnerability and some immunities) are also applied on respawn, so those must also be handled... and it's just become a bit of a long list of edge cases 😄

obtuse field
#

Then, maybe encase it all inside of the struct, and just replicate the struct, and it should all repliace at once

slow wing
#

Yea I could make it replicate atomically, but then that means everytime 1 thing changes, I pay the bandwidth price for many things. Some of these things change very frequently, replicating effects or animation state because a health value changed feels a bit overkill and will hurt bandwidth

obtuse field
#

I ran out of ideas, unfortunately. The last thing that is coming into my mind, is to send a reliable RPC to set everything at once only at spawn, then set variables on the server

vagrant grail
#

@fossil spoke I rewrote my code again to handle inputs only in the player controller, I hope I made progress 😄 The only issue I have now is still the Client not being able to press any input for some reason and can't find how to fix that 😬

hoary spear
amber vale
#

Hey, if I’ve got some simple information, like the class of the character each player selects in a “character selection” screen, how should I communicate that information to the game mode when opening a new level? I know I could make a map with the players and their character class in the game instance, but I’m wondering if there are better methods?

lament flax
#

I have a similar question

#

"How to pass data to the GM from other level data"

fossil spoke
#

There is nothing really wrong with using the GameInstance of the Server for these things

#

Really depends on the type of data I suppose

thin stratus
#

You can also use OnSwapPlayerControllers in the GameMode to move it between controllers.

fossil spoke
thin stratus
#

Both needs the selection screen to be while already connected to the server

#

If the screen is in the MainMenu then this won't work

fossil spoke
#

If there is a preselection period before connecting to the server you would need to pass the selection in with the connection options.

thin stratus
#

In C++ there is a nice way to communicate such a selected class on connect

#

Yeah

fossil spoke
#

Did Epic expose that better in 5 to BP?

thin stratus
#

Doubt. The function is part of the ULocalPlayer

#

It's easy enough to expose it I guess

fossil spoke
#

Shame. I guess omitting it helps force people into C++ lol

lament flax
fossil spoke
#

Where they should be for those things

thin stratus
#

Yus

dawn cypress
#

I have a problem with replication. Looks like replicated actor receives different name when replicated to client. I assume that because of that replicated array of references is empty. Is it normal? Object are spawned on begin on game.

solar stirrup
#

are they all actors?

dawn cypress
#

yes, all of them are actors, and they are replicated - I can interact with them on client side

solar stirrup
#

Show your code for the replicated array

dawn cypress
solar stirrup
#

that select is likely at fault

#

It probably makes a copy of the array

#

instead of a select, use a branch

#

Also: make sure to only set the data in that array server-side

#

don't wanna overwrite anything on the client - the server is the authority

dawn cypress
#

will give it a try, but you can see array is filled on server

solar stirrup
#

yep

#

ah

#

hmm

#

are you certain the actor is replicated

dawn cypress
#

yes, but i will double check the relevance

#

yeap, it is a problem with relevance, they are not passed to client if I make them hidden before client joins

#

thanks for help!

woven basin
#

Do you mind expanding on why you think GMC is not a path forward for the movement stuff?

thin stratus
#

Their repro steps are a bit strange, cause we can get this with just 1 client and outside PIE, but well. Error is the same.

viscid escarp
#

Hey guys! Does a RPC (Server, reliable) called by SERVER does some network traffic, or is it ignored, as if it were just an ordinary method call?

lost inlet
#

not sure how using network traffic would make sense

viscid escarp
lost inlet
#

I would also love the fixed tick policy to not suck

thin stratus
#

It's only like what, 3 people working on Mover? and possibly "none" on NPP?

#

And I'm not sure they work fulltime on it, given that Epic said NPP (and Mover?) is in maintanance mode.

#

So I wouldn't expect much at the given point in time. They will also not address any of the Bandwidth issues any time soon.

lost inlet
#

Mover has a dependency on NPP, I would hope that NPP would actually get more attention as a result

thin stratus
#

Yeah but both aren't being used by Epic as of now

#

And NPP is def in maintenance mode

lost inlet
#

From what I remember, not even the samples in the extras plugin even worked properly with the default settings

thin stratus
#

They fixed some BasedMovement stuff on Mover fwiw

#

I'm relatively sure the Examples are from Dave Ratti still and haven't been touched beyond that

#

Wouldn't even surprise me if he had local settings that he never submitted

#

I'll have to look into either patching IndependentTick to have combined reconciling of multiple SImulation Instances, or patch in a Service to get the Smoothing done for FixedTick I guess

woven basin
#

What about Iris, how does that fit into any of this? Or we still don’t know?

thin stratus
#

Iris is mostly working in the background. I assume if Iris is enabled it will only really have an effect on the NetSerialize functions of a Sim's Sync, Aux and Input Structs.

#

haven't gotten that far yet though

lost inlet
thin stratus
#

@hollow gate Posted a video outlining this a bit. Doesn't seem too tricky, but if I see it correctly he mostly implemented this into Mover itself. I would much rather have it a Service.
I know how to add those, but I haven't thought about what I would need to do yet.
I assume it has to tick every frame and simply pass the data that SirKai passes along in his functions to the Driver/Simulation.

#

Would be nice if he could simply share the code that lives inside the Smoothing and maybe even Lag Compensation components.

#

But that's up to him, I would understand if he doesn't want to share it just yet.

hollow gate
# thin stratus <@396299599654027265> Posted a video outlining this a bit. Doesn't seem too tric...

i did mention in video if anyone is interested can DM me, but i guess it's best i put it in a public repo. still i can't put there the getter function i added to network prediction manager. i will clean the code and add some comments then post it.
as for services.. i did it but.. it was so much work since every single model defined needs to implement the templated functions for smoothing. every single one in extras plugins 😅 . the longer epic takes to do this the bigger the task. that being said there's a cleaner way. you can specialize the Tick and the finalize services to do it. take a look at MockNetworkSimulation.cpp which has custom tick service that does a parallel for. but you'll need to copy paste this custom tick service in every model definition you want it to have it.

thin stratus
#

as for services.. i did it but.. it was so much work since every single model defined needs to implement the templated functions for smoothing. every single one in extras plugins 😅
if we ignore the extras plugins, cause they aren't relevant for actual projects, would it still be a lot of work?

#

I feel like only Mover and any project specific sim would need it

hollow gate
#

if you delete the extras plugin, you'll have few model definition you'll need to add the templated function for. so it's not that much work. but personally prefer making custom tick and finalize services that i would just reuse. because not all simulations would require smoothing in reality

#

for an ability system type simulation , i don't think you would need it. but it's good to have the choice.

thin stratus
#

But Models can just not register for the given smoothing service

#

Or am I misunderstanding something

#

Maybe we are talking about two different things but my idea would be a Smoothing service that models can just not register for if not needed

hollow gate
hollow gate
#

and a custom finailize service that calls finalize smoothing after the actual simulation "finalize"

thin stratus
#

I mean, that can all be just one Service

#

Guess there are different implementations possible

hollow gate
# thin stratus I mean, that can all be just one Service

yes it can, but you'll need a double loop. to loop through the registered smoothing services after sim tick and after finalize. i thought making custom existing services is a more elegant solution that doesn't require deleting extras plugin or even editing engine plugin. the templated functions will still need to be defined in the driver of the simulation.

thin stratus
#

Right, so you would simply inject single calls into the existing loop, at the end

#

But doesn't the FixedTick loop only tick.. fixed?

hollow gate
#

yes, the services have been designed in a nice extendable way.

hollow gate
#

the thing it does is same. they just go into differents arrays when registered based on if they are fixed or not.

thin stratus
#

I guess I need to look once more into how FixedTick is implemented. I was very focused on the Independent one for now

hollow gate
#

it's same thing , calls same functions, just that fixed tick use time roll over to accumulate time and tick on a fixed delta time, calls the simulation tick in that loop. everything else is the same.

thin stratus
#

Right but, if it only ticks if the Accumulated Time hits the FixedStepMS, you'd need to use the Components or Actors tick to do the actual interpolation/smoothing

hollow gate
#

MockNetworkSimulation.cpp has the custom tick service example.

thin stratus
#

Lemme check

hollow gate
#

in the video i said you need the add getter functions to NP manager so you can access the "UnspentTime" so you can do the smoothing.

thin stratus
#

Yeah I get that, but my comment is about actually having something that calls each frame to update the mesh

hollow gate
#

called each frame, not fixed

thin stratus
#
for (TUniquePtr<IFinalizeService>& Ptr : Services.FixedFinalize.Array)
{
    Ptr->FinalizeFrame(DeltaTimeSeconds, FixedServerFrame, FixedTotalSimTimeMS, FixedTickState.FixedStepMS);
}
#

So that one

#

Hm hm hm, makes sense

hollow gate
#

or none i guess

thin stratus
#

Yeah so in other words:

BeginNewSimulationFrame_Internal will cause 1 IndependentTick call + 1 Independen Finalize call. And it will cause 0 to X FixedTick calls (based on accumulated time) + 1 Fixed Finalize call

#

And the Fixed Finalize one is what we can use to Smooth

#

+- the extra getters

hollow gate
#

yes . that is how it works. , TFinalizeService is same for fixed or not. you run it for both but for independent you need to set smoothing alpha to 1 directly. so you can smooth correction. for fixed smoothing alpha is UnspentTimeMS/FixedTickMS

thin stratus
#

Makes sense, UnspentTime is just Accumulated DeltaSeconds

#

Since last "actual" Tick

#

Is the custom TickService relevant then?

hollow gate
#

yes whatever fixed tick left over, so we can use it to know where we are supposed to be between the fixed tick updates. linear lerp

thin stratus
#

Do you use the Interpolate functions on the States to lerp/etc. between 2 states?

#

Can't recall if you showed that in your video

#

Also, does that automatically fix correction interpolation?

#

Is does that need an extra step

hollow gate
# thin stratus Is the custom TickService relevant then?

custom tick updates the smoothing data. and since it only update when not re-simulating. and it saved "last update smoothing data" when you are about to tick you can check the cached "last update smoothing data" against the input of the simulation. if you did not correct it will be same and there's no delta, if you did correct there will be a final correction offset between these 2. i just blend it out by adding back it by scaled by 0.2.

hollow gate
thin stratus
#

Maybe it's easier to follow if you would actually be able to release some sort of repo.

hollow gate
#

the component i made has the actual code doing things, where you write it down and call it from can be changed as long as its after sim tick and after finalize frame

hollow gate
thin stratus
#

Ah

hollow gate
thin stratus
#

So is that CustomTick another Service?

#

Also thanks for the link. Wasn't aware of that article yet.

hollow gate
#

all functions call parent except the Tick.

thin stratus
#

Right, but that's the ParallelFor one, right?

#

Yeah

hollow gate
#

if you want to have a VC call with screen share i don't mind

thin stratus
#

Another time maybe. I'm ill atm and my throat would probably die.

hollow gate
#

sure, get well.

thin stratus
#

Does that Mock LocalTickService get picked up automatically?

hollow gate
#

yes.

thin stratus
#

Ahhh. Ok

hollow gate
#

this is the util function that calls the TickSimulation on the sim class.

#

used like this inside the Tick function of Tick service

thin stratus
#

Yeah I've seen that before

#

So, something I wasn't aware of before, but that seems to be the conclusion: A Model can define a custom Service (of existing type) and that will be solely used for that Model when it is being registered?

hollow gate
#

i used this to test out input decay too. spoiler forward predicted simulated proxies can't look good if predicting with old input kinematic movement. interpolation is the way to go

thin stratus
#

That's pretty cool

#

I wonder where exactly that magic happens. I think somewhere in ConditionalCallFuncOnService

#

Right yeah, it passes in ServiceType<ModelDef>

thin stratus
hollow gate
#

yeah, all services can be inherited. ngl dave ratti did an amazing job.

thin stratus
#

In terms of pure C++, this is as complex and confusing as it is awesome

hollow gate
hollow gate
thin stratus
#

Well the template stuff is to make it cache friendly I guess?

hollow gate
#

yes. i assume that is the main reason.

thin stratus
#

I'm honstly still not sure about the CustomTick and post Sim/FinializeFrame stuff you mentioned.

#

Is that mainly for corrections?

#

That's at least how it sounds like in your text.

hollow gate
#

there are few things that he does in extras as well , that makes you think. like how he did root motion sources with a store and Object ID and the params. immediately makes me thing of a gameplay ability that can have its own serialized params state data.

thin stratus
hollow gate
#

tomorrow , at least smoothing comp will be in a public repo. i will also make a video on what you need to do to hook it for anyone interested.

thin stratus
hollow gate
#

the comp will show you why you need to use both tick and finalize

hollow gate
#

since you can tick at multiple times a frame this saves last sim tick state , used for both correction smoothing and used during interpolation in finalize. for corrections you just get the delta between what you cached as last sim state and the input state of sim tick. if you did rewind and get corrected these states will have an offset between them.

thin stratus
#

Hm

hollow gate
# thin stratus Hm

simulation tick gives you input state which is the last simulation state output.

#

if it's different from what you cached when not rolling back. then you did rollback and get corrected.

analog yarrow
#

Hi im new, how does multiplayer in Unreal Enginge 5 work, in unity you have to write it all, is that also how it works here?

coral badger
#

fivus Problem: Severe lag in an empty UE5 project in local standalone any net-mode.
Steps:

  • create a new project from FPS template.
  • print ping from player state in character BP.
  • launch as Standalone with 2 players in Client net mode (with a dedicated server) this happens with a listen server too.
  • ping will be 120-200ms with noticable lag.
    Other notes:
  • turning on network lag emulation in editor settings does work and if turned on, it makes it all worse. I tried setting the emulated 'lag' to minimum 0 and maximum 50 to emulate normal conditions, but this did not work either as lag was around 300-400ms.
  • my network-related .ini settings are optimal with 60 tick rates and cranked up bandwidth, it does not influence anything, since I only run two clients with two default players.
  • this lag happens in literally every UE5 project that I tried, including Lyra example.
  • I have some older UE4 projects that I checked for sanity's sake and in those the locally run net modes report ping of 5-8ms which should be normal, but not in a UE5 project.
  • I turned Iris on/off, which did nothing, which makes sense I suppose, since it is only a method of getting/sending the data down the pipes.
  • I have googled and clicked on pretty much anything related and all have been vague dead-ends, but seems like many have had this problem in UE.
  • I am not running any kind of VPN, WiFi, Firewalls, it's literally just a local home PC with a wire.
    What gives? Is this normal for everyone?
analog yarrow
coral badger
#

lol no, ofcourse you write networked code for your game, but it's much more streamlined and you don't have to write low level replication logic, like in unity.

thin stratus
# hollow gate simulation tick gives you input state which is the last simulation state output.

I get the idea behind saving the state etc. Just not when you do that.
You said it's a custom tick, but that's very vague for me.
Did you mean "Custom Tick Service"? And how would you make sure it's called AFTER FinalizeFrame?

I know that SimulationTick gives me the In and Out (Out I generate myself) State.
And that I can possibly Cache that State in my Component.

But isn't that the same state I would get in the next few FinalizeFrame calls until the SimTick happens again?

#

@analog yarrow Please read the pinned Multiplayer Network Compendium

thin stratus
#

@hollow gate I think I'm either really bad a following today, or I'm missing something obvious :P sorry

thin stratus
#

I assume we are talking Network Lag and not Frames.

coral badger
#

Yehh, I would think so too. And yes, it's all about Ping values.

hollow gate
# analog yarrow Hi im new, how does multiplayer in Unreal Enginge 5 work, in unity you have to w...

you want to look at RPCs, Replicated Properties and Rep notifies in unreal engine. only Actor class and its children can do replication stuff.
https://www.youtube.com/watch?v=4Tnbf44NjXo this series of videos should help. reids is a great teacher

Support the channel through donations. Crypto accepted!
PayPal: https://paypal.me/reidschannel?locale.x=en_US
Patreon: https://www.patreon.com/reidschannel
Bitcoin: 1JFwWHr4X6uAeoZadukzqKjzFBj3Qjy7Sk
Ethereum: 0x2B2Bc108F1Cc0fF899959dEF3226637787d8C3dE
Dogecoin: DNQ33YnhpWoTBokBNVkZP5ub8KTLkpyjpv

Join our community discord!
Discord: https://dis...

▶ Play video
analog yarrow
coral badger
#

Lots of great other examples too.

analog yarrow
thin stratus
thin stratus
#

But I wouldn't worry about performance of C++ vs BP at this point.

coral badger
analog yarrow
hollow gate
# thin stratus <@396299599654027265> I think I'm either really bad a following today, or I'm mi...

nah all good i don't mind the slightest it's a confusing subject in general.
ok let's forget about the custom tick service for a second. let's talk about smoothing in general what you need.
you need 2 states to interpolate between during finalize frame, these 2 states are the simulation state the last simulation ended at (the state that you get in finalize function as input) and the one before it. this one before is not necessarily a state that finalize frame was called for it. remember sim tick can tick multiple times per render frame.
so you need to update the smoothing states in sim tick ( this is where you also catch corrections).
and in finalize which is every render frame you use the states you updated in sim tick to interpolate between them.

hollow gate
thin stratus
#

Just pseudo code

hollow gate
#

so FinalizeFrameSyncState - 1

#

in mover LastCachedSimTickSyncState, will be what you get in finalize.

thin stratus
#

I mean sure, if they are the same, lerp would be redundant

hollow gate
#

yes, that is the idea. the article i shared earlier, has the equations in it as well with clearer naming that what i am saying

thin stratus
#

You mean Sn+1 = f( Sn, Cn+1 )?

hollow gate
#

LERP( Position_Simn-1 , Position_Simn , Accumulator / Tick_Length )

#

to smooth out correction you need to add bit more. this howver will smooth the fixed tick

thin stratus
#

There is also something else I'm wondering with FixedTick.
If we say we have a FixedTimeMS at 20hz. And the game runs at 60hz.
How does that work with ProduceInput?

#

First thought would be, only every 3rd frame of Input is actually considered.

hollow gate
#

but yes input is sampled at the simulation rate.

thin stratus
#

Right, so if I press Jump in any of the 3 frames, it will be cached and used?

#

Alright

hollow gate
#

if you press it mid render frame, it can be used in next sim tick before that render frame ends also

coral badger
thin stratus
thin stratus
#

You shouldn't really get high pings when playing locally without Network Emulation.

#

There is some ping of course, but very very low

coral badger
#

Yeah, that's how it should be, but isn't. I'm getting high ping in local net mode in any UE5 project I've tested so far.

#

People at my work have just been working with a project as is and never paid attention to it, but the lag is the same, just that in Lyra animations mask it and it does not look as bad.

#

Am I going crazy?

ember jasper
#

Hi,
I have a supposedly basic issue here.
Everything **close **is NetworkRelevant if I use a character.
Nothing is NetworkRelevant if I use a pawn
Do you have any hint for me ? (I already read exi's guide)
PS : the pawn is composed of a blockAllDynamic cube and a camera and its network settings are the default ones

queen escarp
#

hm this is in the player HUD

#

is this wrong to set it up like this ?

#

in my "player hud Widget" im getting the same player character..

coral badger
# queen escarp

Don't see anything wrong with that. In general, you might want to avoid having hard refs of the Player character in widgets, but that's just my oppinion. If you need it, you need it.

queen escarp
#

hmm then why is it bugging :/

coral badger
#

Needs more context. Player HUD only exists for the local player, so you should get the correct pawn.

#

Where is the HUD set up?

queen escarp
#

in game mode

coral badger
#

And you get this bug when launching in what mode?

queen escarp
#

its assigned in the game mode

#

listen server + 1client

coral badger
#

try with dedicated + 2 clients.

queen escarp
hoary spear
#

Pawn may yet not exist

coral badger
#

Are you saying that a print message is coming from a HUD on server?

hoary spear
#

Add print to cast failed

queen escarp
#

ah true

#

hm dose not fail

#

@coral badger might be abit confusing i have the "player_Hud" and also "PlayerHud_wB"

#

this was from the player_HUd

#

also getting same resault from playerHud-Wb

coral badger
#

So, it works?

queen escarp
#

no

#

theyre all same char

coral badger
#

I'm lost with the namings and all, but this still looks like a Listen server launch, not a dedicated + client.

queen escarp
#

yeah

coral badger
#

Try that. HUD does not exist on server. So each client should only get his own.

queen escarp
#

be different then right

coral badger
#

I'm not actually sure if Owner gets set correctly for the HUD in Game Mode if it is not set explicitly in BP code.

ember jasper
#

If I spawn an empty character and possess it : close stuff is NetworkRelevant
If I spawn a basic pawn and possess it : nothing but bIsAlwaysRelevant gets NetworkRelevant

#

Any idea why ?

queen escarp
#

hm

coral badger
#

I don't have experience with the why, but it makes sense how character network relevancy settings would be different than just a pawn, since a pawn can be an AI and character will always be a player. What are you trying to achieve/what breaks?

#

Change the relevancy setting/net culling on the Cube Pawn and see if it changes anything.

queen escarp
#

well this is real simple its just hooking up the player to the widget and im using progressbar to detect health thats it

#

i could do it in the widget itself but i like having a parent holding the core reffs

coral badger
#

As to the bug itself, seems like the HUD just has a wrong owner. Not sure why.

#

You could try just getting player pawn and playing with the indexes, which would at least tell you what exists on BeginPlay for the HUD.

queen escarp
#

hm

#

im trying to set the Character from within the controller instead

#

how is this wrong O.o´+

coral badger
#

Controller exists on the server too.

#

Try getting player character by index.

queen escarp
#

but that will always get the 0

#

first player

coral badger
#

So, put different indexes into it, to see if that works correctly

queen escarp
#

it dose

coral badger
#

from the HUD

#

Ah ok

#

I assume the player characters just spawn from being set in game mode, not explicit Possess or anything like that?

queen escarp
#

yeah

coral badger
#

And your characters are set to replicate?

queen escarp
#

no

#

xD

coral badger
#

Try that

queen escarp
#

oh wait they are

#

this is just bnlehhh

coral badger
# queen escarp

So, if you print the owner here, do all controllers return the same?

queen escarp
#

yeah

#

hmm even the controllerss are the same

#

something is messed up

coral badger
#

yeh

queen escarp
#

oh ok so no

#

this is from the controller it displays correct controlklers

#

but same character

coral badger
#

Try printing NetPlayerIndex on controllers

queen escarp
#

since index

#

like so ?

#

all 0

coral badger
#

And with dedicated?

queen escarp
#

how do i simulate dedicated only clinets ?

coral badger
#

As in just launch in CLient net mode

#

not Listen

queen escarp
#

aye

#

yeah

#

all 0

#

this is just garbage

#

ok tell me how i would do it from scratch

#

this is just mind numing

#

how would u set up the player character reff for each player

#

just gimme the most common easiest way

coral badger
#

As I said, I wouldn't. I'd just bind the value in the widget.

sinful tree
#

You can't use the "Get Player .... #" nodes reliably in multiplayer, especially so on begin play of certain actors as the player may not have the appropriate reference assigned to them yet.
Same with using "Get Controller" on a pawn on Begin Play - it may not be posssessed on Begin Play.
Same with using "Get Controlled Pawn" on a Controller.

coral badger
#

In an empty project I`m getting the same result from the HUD, so, I'm not sure if that is right at all.

queen escarp
#

hm ok

#

so u mean

#

in the player hud Widget

#

u would cast for

#

u would do it like this ?

#

forget the is valid

hoary spear
#

Not really

queen escarp
#

then what do you mean+

hoary spear
#

Get owning player pawn

sinful tree
#

This is within the Pawn class.

queen escarp
#

ok

sinful tree
#

That's the first event that is both server and client where the controller and pawn can know about each other (in blueprints anyway...)

queen escarp
#

hm mkey

#

this however give only player charcter 0...

#

for everyone

#

this is how im creating the widget

#

in the HUD

sinful tree
#

If your cast is succeeding, then it should be correct.

queen escarp
#

oh its failing

#

hm

#

is it happening to soon or ?

sinful tree
#

Well I'm guessing that's a bind right?

queen escarp
#

yeah

sinful tree
#

Then it shouldn't matter, it may fail the first few ticks until such time as your controller possesses a PlayerCharacter_BP

queen escarp
#

yeah true

#

but yeah thewy all gives player character 0

#

so not working

#

this is so weirddd ???

sinful tree
#

Are you actually playing as client/listen server and not playing as standalone?

queen escarp
#

jupp... 😮

#

any more ideas anyone :/?

sinful tree
#

Can you show the actual printout that you're getting? You should be seeing something like:
Client1: PlayerCharacter_BP0
Client2: PlayerCharacter_BP1

queen escarp
#

yes exactly thats the issue

coral badger
#

just tried that too lol. All of my experience, but have no idea whats up with that. Guess I never needed to do it that way.

maiden flame
#

If you are in the GameMode, owning player on listen server will only return itself I think.

sinful tree
maiden flame
#

Getting controller for each player state could work, but I wouldn't spawn HUD in the GameMode, if it still is.

queen escarp
#

ok so i just moved the creation of the hd widget to the player controller

#

wtf ???

maiden flame
#

Uh

hoary spear
#

You're running the code on the server aswell

#

On the servers copy of a clients controller

queen escarp
#

aye ofc -.-

#

im dumb

#

yeah im so lost i dont get it

sinful tree
#

Well, technically you shouldn't necessarily rely on the display name of an object to know whether it's the right object or not.

#

The reference is more important than the display name that a client may have as the display name is handled locally.

#

This is within a pawn class.

daring cosmos
#

Hello, i have an issue syncing a PlayerState variable, what i want is that, when the player open the game, it does a http request to my backend, and then gets an accountId, this accountId is then set in the PlayerState , this happens from the client, then later on, it joins a dedicated server, but in the dedicated server, when i check this PlayerState, the AccountId is empty, so i dont know what to do to make sure this value gets sincronized

i have something like:

// MyPlayerState.h
UPROPERTY(Replicated)
FString AccountId;

UFUNCTION(BlueprintCallable)
void SetAccountId(const FString& NewAccountId);

// MyPlayerState.cpp
void MyPlayerState:SetAccountId(const FString& NewAccountId){ 
   AccountId = NewAccountId; 
}
void MyPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
  Super::GetLifetimeReplicatedProps(OutLifetimeProps);
  DOREPLIFETIME(MyPlayerState, AccountId);
}
sinful tree
sinful tree
# daring cosmos Hello, i have an issue syncing a PlayerState variable, what i want is that, when...

If you're joining a server later on, the PlayerState wouldn't carry over as it would be destroyed when the client is moving to the server. The only thing that would normally persist is the GameInstance.

I'd also be cautious of having the client telling the server an account ID after what I'm guessing is authenticating with your backend. This could potentially be an easy way for someone to spoof someone else's account.

coral badger
daring cosmos
coral badger
#

@daring cosmos
This is a very big architecture question with a LOT of variables, but:
you should have a separate module/subsystem that handles that stuff, independent from the gameplay. Have that module have authentication/sending info to the backend.

Have your stats/whatever you need tracked in the game state (which is server authoritative) and then pass them to that module which will send them to your backend.

Have your game session on the server handle authentication-related data, like ID's. Depending on how your backend is set up, if your server will be hosted on that same infrastructure, you could directly call those methods from the server and let it post stats to the backend.

However, the game server and your authentication/player account infrastructure should be separate modules and ideally should not even know about each other.

daring cosmos
# coral badger <@933047162919604274> This is a very big architecture question with a LOT of va...

got it thanks, i have some of those things already made like i have a subsystem just to interact with the backend, and in the game session dont know anything about backend until the match finishes that then needs to report who won to the backend, then the backend handles the progression to each player, and thats the part i dont know how to handle since i need the ids of each one player to be able to update the stats of each participant, like exp, etc in the backend

queen escarp
#

sry was afk for abitÄ

coral badger
# daring cosmos got it thanks, i have some of those things already made like i have a subsystem ...

Ok, then you should be able to give those id's to the session, since session joining should happen from each client after they auth. And then get them all on the server from the session when your match is done and send stat update to the backend. I don't exactly recall whats available in the session interface, but the idea is that you should definitely not keep ids as replicating variables or do any of that stuff with in-game events, if that makes sense.

visual mountain
#

Anyone know how I would get some printed string to appear for clients? I tried running the string through a game mode event with different event server settings but have come up dry.

hoary spear
#

GameMode only exist on server

#

if its a global message, passing it through Gamestate would suffice

if its a player specific one you'd want to pass it through an actor that player owns specifically. PlayerController sounds like an ok fit

visual mountain
#

thank you very much.

gloomy tiger
#

How do you make your AIs/Bots looking at a given player's pawn?

The simple answer would be something like SetActorRotation on the server and take it for granted; I feel, however, that's quite costly, since server is dispatching updates every time the pawn of the player moves.

Another option - although unrealistic I bet, - would be replicating AI's target and rotate it locally; can't even imagine the consequences of that - stuttering et al.

Which virtually leaves me without ideas... so, what are your takes on this? Am I missing something? Is SetActorRotation on the server the way to go? 🤔

dark edge
#

keep that same energy

daring cosmos
gloomy tiger
dark wing
#

In the context of a multiplayer first-person shooter game, which approach would you guys take for handling automatic weapon fire , sending RPC to the server to initiate firing when the fire key is pressed, followed by another RPC to cease firing upon the release of the fire key? / Or send Fire RPC everytime when the fire rate has passed

The first approach cons is there might be a latency delay to stop shooting, which can confuse the player if a ping is a little bit high like 0.2ms but reducing the overhead
The second approach cons is there might be a latency delay to shoot, which can be a disadvantage for the player, and also there is a network overhead
Also not to mention if player times out, or really high ping like 1000 ms for a few seconds

hoary spear
#

Atleast for the last scenario, no players can expect anything from their experience in the game. Timeout is timeout, not much to do with that

#

I would think sending start/stop with local prediction would be the way to go

queen pecan
#

I want to use Manager singletons
Commonly people put Manager-type classes in GameInstance or maybe GameState
I heard a better way is to put them in Subsystems
However, Subsystems don't replicate
So for networking, I should not use Subsystems, is that correct?

cursive steeple
# queen pecan I want to use `Manager` singletons Commonly people put Manager-type classes in `...

This come up in one of Epic's livestreams about subsystem (which was a while ago, but don't think much have changed/progressed since), and I think the workaround was to reroute that particular system logic that needs replication through a helper actor. Sounds abit dirty but I guess that's the only way if you don't wanna pollute your core classes. Would be happy to be wrong about this tho!

hoary spear
#

Ugh that sounds... dirty

queen pecan
hoary spear
#

Yepp

cursive steeple
#

check with the timestamp

hoary spear
#

Ty for that^

cursive steeple
hoary spear
#

Still can't understand why they wouldnt even have it on the roadmap

cursive steeple
hoary spear
#

Yepp.. as many other things

cursive steeple
# queen pecan I see, so for multiplayer we'd best just use `GameInstance` or `GameState`? Alth...

Kinda wanna point out that you can still somewhat avoid bloating your core classes by using actor components, they can be replicated the same way actors can and you're still separating your code and avoiding polluting your core classes.

(And later if you decide you wanna move that logic to another class (from gamestate to playercontroller or whatever), you can just move the actor comp to the other class and only fix a few minor errors. Easier than transferring whole systems via refactoring major classes.)

queen pecan
cursive steeple
cursive steeple
slim jay
#

Replication graph isnt being initialized , i have reviewed the target files, the build file, and the default engine multiple times, but I still can't figure out the reason why

quasi tide
hoary spear
#

Exactly

quasi tide
#

"So we know we have a multiplayer focused engine, but we decided not to do this but here is a workaround in case you want to do it"

hoary spear
#

Just the way he said it wasn't even on the roadmap.. like.. what?

quasi tide
#

Then the argument is, "but it's an actor!". Cool - make it work

#

It's your dang engine

hoary spear
#

Almost like they forgot 😛

cursive steeple
# quasi tide It's your dang engine

Doesnt contribute enough to their income/vision progression so they'll just put up with a few people malding on discord/reddit every now and then.

I agree tho, in certain cases it would be a no-brainer to use a replicated subsystem. 🫠

lusty kelp
#

if the other user is static usally mean you are online on a game

#

right?

outer sphinx
#

hello guys, a question, is it advisable to use php to make the backend of an mmorpg?

dark wing
hoary spear
#

You can do keepalives

#

which can be at a less frequent interval than "every single shot", but more often than just on and off

#

like every third shot or smth

sinful tree
dark wing
hoary spear
#

Forsure

dark wing
#

And the problem happens more when the fire rate is higher
for example 700 RPM
60 / 700 = 0.085 S
So player should have less than 0.085S latency to send the stop response, any time more than that will cause problems

hoary spear
#

Yepp

#

which ofc is not very viable

dark wing
#

I don't think there is competitive games using this approach

#

I'm reverting back to sending RPC for each fire command

hoary spear
#

I think you'll be surprised by the smoke and mirror they put up

#

If you have a gun with 700RPM,

#

and > 85 ms ping

#

your gun will fire at sub 700 speed

#

is that a good solution?

dark wing
#

smoke and mirror?

#

didnt understand you

hoary spear
#

trickery

dark wing
#

if you don't have a gun that fires more than 700 RPM, and you are restricting your players to 85 ms latency

#

or your game doesn't depend that much on ammo and you just want to optimize the network traffic

hoary spear
#

local prediction is what you wanna do I believe

#

So the player experience is as nice as possible, while the server is gonna have to play some 'catch up', depending on the ping

dark wing
#

Its not about predicting results, I am already implementing prediction and handling the mis prediction cases

#

Here:

you are a player shooting with a weapon that shoots 700 RPM, and your ping is 100, if you release the fire button after 0.15ms, then your "ReleaseFire" RPC will arrive to the server late, at that time server consumed two bullets, and on your screen you consumed one, because you shot once, server thought something else because of the delay

#

So server will send you the correct values "Ammo", but eventually you lost a bullet

#

You wanted to shot one bullet not two

#

This may work fine with certain games genre, but not with survival games

hoary spear
#

It's not optimal either way

#

while you may have the correct bullet count by sending the RPC's, your gun can fire considerably slower than it's supposed to with high ping

#

meaning damage output is reduced

frosty crag
#

I always have trouble knowing what put inside player controller, for example the team the player belongs to, I set it in the controller but also in the player char bp (the pawn the player is controlling) does it make sense to set it two times once in the player controller and one in the player char ?

hoary spear
#

team belongs to Playerstate typically (as all players can see other players team?)

frosty crag
#

@hoary spear Yes and so what store the player controller ?

#

and does that make sens to also store the team in the character bp ?

hoary spear
#

atleast from local testing

#

gonna try emulating some lag

#

Seems I'm getting kicked x)

#

LogNetSerialization: Error: FBitWriter overflowed! (WriteLen: -1, Remaining: 7620, Max: 7620)

dark wing
dark wing
#

because server will always be 100 ms late

hoary spear
#

Seems the rpc's might get batched aswell ..

#

Idunno, feels weird. Glad im not doing any MP shooter tbh 😆wether its survival or god forbid competitive

dark wing
#

One way

#

Could be

#

sending many RPCs to the server

#

but it feels dumb

#

Especially I'm using GAS, that means i would need to get rid of it

dark wing
frosty crag
#

I repost I don't know if you saw it :
@hoary spear Yes and so what store the player controller ?
and does that make sens to also store the team in the character bp ?

dark wing
#

Player controler is replicated only on owning client and server

dark wing
hoary spear
#

Storing team in the Pawn seem a bit unessesary as you can GetController->GetPlayerState->GetTeam()

frosty crag
#

@dark wing I am doing a little 3v3 game, for example you can inflict damage only to the other team not your team mate

#

@hoary spear so I was thinking maybe it's easier to also have it in the player bp, b ut like you said i can get it from controller -> gamestate

dark wing
steel vault
dark wing
#

When damage occures, server checks if the player TeamID are equal, or you can do a for loop on the Team Array and check

#

In that case you don't need a variable on the player

frosty crag
#

ok !

#

I do the damaga calcul server side

dark wing
# frosty crag ok !

Psuedo:

int ReturnTeamID(AActor* ActorPointer)


Loop through Teams
  for loop in Teams.Players, PlayerIndex
  if ActorPointer = PlayerIndex.ActorPointer
    Then Return Team.ID;
frosty crag
#

but it's in is own bp, and this bp doesn't have the team array

dark wing
#

Are you using unreal engine methods? "ApplyDamage" if yes then there is a reference to instigator, and you are already in the "PlayerToDamage" BP
from there you have reference to both

frosty crag
#

yes i use those

#

okok nice one !

#

but the player does store the team id no ?

dark wing
#

You don't need the player to store TeamID

frosty crag
#

let say I have a bp called damageffect

#

he took two actor the instigator and the player to apply the effect

#

here it's damage

#

so how my bp check the team id if the players doesn't store it

dark wing
#

As i said
Create a struct called Team, add an integer variable and name it TeamID, add a variable called Players, set it to array of actors

#

Then in game state, you can add a variable called Teams, set it to the Team struct and set it as array

#

Mark it as replicated, so all players receives the data

#

You can also set it as RepNotify, if you want to run some kind of logic every time the Teams are replicated

dark wing
frosty crag
#

Oh ok !

#

yeah yeah make sens alright !

#

ty !

dark wing
#

np

#

ping me if you need help

frosty crag
#

@dark wing Ty !!

outer sphinx
dark wing
#

How many players?

#

And what exactly do you want to implement in the back end

#

Will it be the main master server?

#

There is a lot more than just that

#

Node.js would be a good start

outer sphinx
# dark wing It depends

The idea is to make a dedicated server that is authoritative, that can support 1800/2000 players

dark wing
#

So master server

#

check this

outer sphinx
#

I did see it, I'm in your discord haha

dark wing
#

It would be a good start

#

Facebook and twiter and AAA games

#

uses Phoenix Framework

outer sphinx
dark wing
#

my pleasure

frosty crag
#

On a performing aspect is it really bad to make cast to ?

dark wing
frosty crag
#

I don't know it's more a general question

#

lets say a skill touch an actor I try to cast to the player bp class

dark wing
#

It depends

#

Its fine

#

Its better to not use casting on tick, you can cache the result once and use it

#

But all other cases are just fine

frosty crag
#

ok ok ty !

quasi tide
dusk fable
#

requesting some guidance , i want to add voice chat in my game , anyone know a way to add that ?

thin stratus
#

UE has voice support but it might need a Subsystem like steam to use it over the net

#

Been a while since I used it

dusk fable
#

can i use the EOS voice chat system while using steam sessions ?

thin stratus
#

That I can't answer. I simply don't know.

dusk fable
#

ah absolutely yeah , thank you !

vagrant grail
#

Why my characters are floating from the point of view of the other player ?

dark edge
#

if the capsule looks right then its on your component or animation setup

vagrant grail
# dark edge make the capsule visible

The capsule is in the right place. Which component ? I didn't touch any animation blueprint yet since the beginning of this project and I didn't have this issue before today 🤔

dark edge
#

show your character in the bp editor

vagrant grail
dark edge
#

Something is moving it somewhere

vagrant grail
brazen anvil
#

I want to add different walking speeds to my character. Whats the best way to handle this so that it is replicated correctly without corrections?

fossil spoke
brazen anvil
fossil spoke
#

Its that easy.

#

You can also override the acceleration etc

#

There are functions for those types of properties as well

brazen anvil
#

Oh well then. That makes it a lot easier than I thought.

#

Thank you for your help!

shy gust
#

Does anyone have any good ideas on why Lan multiplayer wouldnt work , or would stop working ?
its not specific to my game, ive tested another blank template project i got from the asset store that 100% used to work , but I havent tested Lan play in some months till now, ive tested Steam networked builds and those work fine.

but regardless of game , Lan session are not working. im not sure if i need to contact my provider or manually figure out how to open a port or something

eternal dune
#

Moving here from #cpp since this is a replication question. Can a replicated UObject also have it's own replicated subobjects? I don't see any ReplciateSubobjects() method defined on UObect, so there's nothing for me to override.

steel vault
#

It appears most of my issues with rubber banding come from player to player collisions when impulsing at them. Is there a better way to handle that? Take off blocking collision and impulse on overlap?

fossil spoke
#

The same way that it was replicated

eternal dune
#

OK. Then what about my specific situation

Class A includes a TArray of pointers to class B. Both are intended to be replicated UObjects. Would that array get replicated anyway without a ReplicatedSubobjects call?

#

Err, no sorry. NOT an array. Just a TOBjectPtr<B>
I was thinking of a different class for a moment

Specifically, class A has

    UPROPERTY(Replicated)
    TObjectPtr<UDcsInventoryItem> InvItem;
#

If I have to I can make class A be an AActor, though that seems a little silly since it will never exist in a level.

storm grove
#

Whats a consistent way to map some data to a client? I just need some kind of ID that consistent

#

It would be in UNetConnection right?

#

I see this but it mentions local and server only

    UPROPERTY()
    FUniqueNetIdRepl PlayerId;
#

PlayerState seems to have what I am after I think. If whenever someone experienced reads this could just let me know if I am on the right path or not I would appreciate it

fossil spoke
#

FUniqueNetIdRepl is a wrapper around a FUniqueNetId that allows it to be passed across the network.

#

A FUniqueNetId is a platform Id, like your Steam Id for example.

storm grove
#

Alright that sounds perfect, Ill look around for it but do you know where its stored? Or is it something I create passing something through in the ctor

fossil spoke
#

For the local player you want to use ULocalPlayer::GetPreferredUniqueNetId()

#

When on a server you want to use their NetConnection

#

UNetConnection::PlayerId

storm grove
#

Yeah thats awesome, what if I wanted client A to store some data about client B in a subsystem, I was planning to map their ID to the data but what you described sounds like it works locally or server only

fossil spoke
#

You can also use APlayerState::GetUniqueId()

storm grove
#

That sounds like it

glad robin
#

So I'm working on my lobbies and just I'm curiuious. If I understand the Online Subsystem is used to communicate with the various services like Steam and Epic. So now, why would someone want to avoid the Online Subsystem and just work with say Steamworks SDK directly? Would it just be about optimizing and not having all these unused parts of the Online Subsystem?

solar stirrup
#

It'd be dumb

#

The online subsystem is there just use it

#

Use what you need and don't worry about the rest, won't matter

glad robin
fossil spoke
#

@glad robin The only reason you wouldnt use an OSS is if it doesnt expose something you need from the platform specific API.

#

There arent many reasons not to use the integrated OSS's

lusty kelp
#

anyone wanna quickly test my project?

dark edge
lusty kelp
#

???

#

very funny but its a game

dark edge
#

Yeah lemme just run an executable from somebody who joined the server today

lusty kelp
#

lol

fossil spoke
#

@lusty kelp This server is full of your peers, not your personal testers. If you need assistance with development of your game, make a Job Listing.

lusty kelp
#

ok

vagrant grail
#

Are "Structs" replicatable through blueprint ?

fossil spoke
vagrant grail
fossil spoke
#

Keep in mind that the properties within the struct must also support replication.

fossil spoke
vagrant grail
vagrant grail
vagrant grail
#

Why is "Client 0" printing twice ? 🤔

hoary spear
#

are you playing with 2 players?

#

Seems like you are

#

because the client got 2 pawns

vagrant grail
hoary spear
#

so thats why

vagrant grail
#

huh ?

#

Both print "Client 0"

hoary spear
#

yes

#

client0: Char 0
client0: Char 1

icy jetty
#

Basically 2 chars on one client

lusty kelp
#

cool somebody who do the same thing as me, good luck getting somebody to test with you

thin stratus
vagrant grail
# hoary spear

Alright then I have no clue on why it still doesn't work even if now the client and the server value of the "CurrentCamera" are in sync...

hoary spear
#

A guess would be camera loc is not updated on server

vagrant grail
hoary spear
#

Y

vagrant grail
# hoary spear Y

how is that not updated on the server when the Character himself is replicated ? so shouldn't children components of it being replicated too ? I also tried to enable replication on both camera and the issue still persists

#

Also the raycast logic is done on the server 🤔

thin stratus
#

I can't find where the original post about the issue is

thin stratus
#

Is that a Camera on a Character?

#

@vagrant grail

vagrant grail
thin stratus
vagrant grail
thin stratus
#

And which of the two gives you problems? Both? Or just one of them?

thin stratus
#

You can try simply using GetBaseAimRotation

#

Instead of the Camera Rotation

#

But you are also having issues with the location?

vagrant grail
thin stratus
#

Hm hm, try GetBaseAimRotation for the Rotation

vagrant grail
vagrant grail
thin stratus
#

Eh, something something Pitch

sick sphinx
#

any good resources on how to properly end sessions, so that they don't hang around and cause weird issues when trying to create a session with the same name?

hoary spear
#

Isnt that simply DestroySession ?

#

Client call -> Leaves session
Server call -> Makes all clients leave session

sick sphinx
#

yeah i think i should be calling it right now, if the server destroys the session, everyone is kicked out, but there's some stuff hanging around it seems 😄

#

also the session interface only takes the name of the session as a parameter, is there some way of ending a session for a specific player id?

#

and is leave session the same as destroy session? 😄

hoary spear
#

Last I used it there was no leave session 😮

#

but perhaps its just to avoid confusion ?

#

Using a plugin ?

sick sphinx
#

nope, just built the subsystem based on a tutorial for steam.

woven basin
#

so should the link to Jambax's website be removed from the pins, and replaced with the other link you gave?

#

cause I was about to follow Jambax's post not realising there is the newer way (which I will now follow instead)

fathom aspen
#

How dare you ditch our legacy

#

I think it's good to keep it for the meantime for people on older versions

#

If I'm not wrong he also said the other day that he's going to do something about it

woven basin
#

arh ok. Yeah maybe just a red box at the top of the web page itself saying "if you are using 5.1 check this out" or something

fathom aspen
#

@chrome bay sorry, but an ez mode suggestion/fix you might like to hear ^

stuck rock
#

Hi everyone! I'm making a two player local game but for some reason the second player can move the first player's camera as well and make him jump. Has anyone had this issue before?

lost inlet
#

The rare splitscreen/local MP question

unique forge
#

Hi there
I’m having trouble about steam friend list. I wanted like there’s a button called invite and after you clicked on it the Steam Overlay FriendList pops up

mystic estuary
#

Hello, does anyone know whether Epic changed how they handle widgets on seamless travel?

I always knew that they are persistent (https://wizardcell.com/unreal/persistent-data/#should-userwidgets-persist-seamless-travel), however, it doesn't look to be the case anymore. I have made a bare example with seamless travel (screenshot), but upon it the widget gets removed mid-travelling (on transition map). I have checked the SeamlessTravel in GM.

Upon executing the console command, this is triggered

void UEngine::TickWorldTravel(FWorldContext& Context, float DeltaSeconds)
{
    if (Context.SeamlessTravelHandler.IsInTransition())
        Context.SeamlessTravelHandler.Tick(); // <<< Following the chain, it calls UGameViewportSubsystem::HandleRemoveWorld
        // ...
}

and then

void UGameViewportSubsystem::HandleRemoveWorld(UWorld* InWorld)
{
    // Gather all widgets...
    for (UWidget* Widget : WidgetsToRemove)
    {
        Widget->RemoveFromParent();
    }
}
stuck rock
lost inlet
#

why would each player have a completely different BP

#

GetPlayerController(0) is dangerous for MP

#

and in local MP, that will always be the first player

stuck rock
#

This is the custon event Adjust player logic in the game mode.

#

I just started using Unreal recently, so I'm trying to figure things out.

woven basin
#

Sorry to necro this comment - I'm currently researching (searching) for the right way to do some inventory stuff. What you wrote around this comment is how I'm approaching it at a high level - so I'm feeling good I'm on the right track.

Just wondering if you ended up releasing any of this code so I could browse it? All good if not, just thought I'd ask. Thanks.

chrome bay
#

I haven't as of yet I'm afraid

woven basin
#

its ok - i'm afraid knot

#

(sounded funnier in my head)

obtuse field
#

Is there a way to no notify a server that variable has been successfully replicated in C++? I've heard that Blueprint's RepNotify can also fire on the server, is there an equivalent in the C++(ReplicatedUsing is firing only on the client, as far as I know)?

hoary spear
#

Just calling it manually is how one trigger it on the server

#

OnRep_MyRepFun(const var oldVar)

#

What you put in 'successfully replicated' might ofc be something else

#

The BP version is not that, fyi

obtuse field
#

I need to be sure, that varibale on the client received a replication. I wonder if there is a way without sending an RCP, if maybe unreal is doing it by itself

hoary spear
#

There is something there i guess, as it picks up if package is lost etc

#

There was some PostReplicate talk a while back, but got no clue when thats called

#

Guess one would need to dive into the replication system

#

Seems there is no PostReplicate

#

UNetdriver.h and Netdriver.h got quite a few comments about it

elfin lintel
#

Would there be a functional difference between creating a dedicated server build and a regular multiplayer build with an observer mode? I already need to add an observer mode to my game (I'm making a text-based college basketball sim and if a user coach is fired they need to be set to observer mode so as not to be able to control any teams). I think the observer mode route would mean the person hosting would have to render the graphics as opposed to a dedicated server build, but since its just text-based I don't think that would mean much, could be wrong though.

quasi tide
#

My question is more - why are you using UE for a text-based game?

#

Seems like massive overkill

random verge
#

best fonts ever

maiden flame
# elfin lintel Would there be a functional difference between creating a dedicated server build...

Well, a dedicated server would not be able to render any graphics to begin with. The server can't directly interact with gameplay either.

If you need to use a dedicated server, you could check if the hosting client has the same UniqueNetID as the server, and then put the client in observer mode.

If you use a listen server where the host and the client are running the same instance of the game, it would be easy to create an observer mode for the host.

cursive steeple
maiden flame
#

Yeah. I guess I misunderstood a bit also, because if the user coach can be any player regardless, going in or out of observer mode as a dedicated server wouldn't change anything. You'll just deal with every player interacting with the game as a regular client, if there's a dedicated server.

I do agree a listen server would benefit, as it's more convenient to host for community members, and that there probably isn't any real-time gameplay (correct me if I'm wrong) that would require the sort of performance that dedicated servers are useful for.

#

Unless you want to be really strict about the security and validity of user data, and only allow trusted parties to host servers (dedicated).

hoary spear
#

Plus money

#

Dedicated easily costs.

elfin lintel
# quasi tide Seems like massive overkill

It definitely is overkill, but its just the engine and the programming language I was familiar with, and seemed to be the best as far as easy to set up, built-in multiplayer.

#

I do have a listen-server setup working right now. I was just planning on adding a dedicated server setup in the future, but had a thought last night that I might not need one if I can easily adapt my listen-server setup to have a pseudo-dedicated build as well.

cursive steeple
lament flax
#

the component spawns well on server and clients, but when later setting the Material var, the SMC var is null on client
Note : both var are set repnotify, the code is called some time after both player are created

any ideas why?

sinful tree
lament flax
#

right after

sinful tree
#

So then there's no guarantee that the static mesh component has been created by the time the OnRep triggers for the material.

lament flax
#

you are right

sinful tree
#

When the OnRep for the static mesh fires, check if it and the Material is valid and if so, set the material on the static mesh component.
When the OnRep for the material fires, check if it and the static mesh is valid, and if so, set the material on the static mesh component 🙂

lament flax
#

i'll do that

#

now i got another issue, destroying the comp on server doesnt destroy it anywhere
(i checked if i had multiple stacked comp, i only have one)

lament flax
frosty crag
#

@dark wing Sorry to bother I ask you a question about handling team yesterday, I have another question on it, may I ask you ?

dark wing
#

yes

frosty crag
#

@dark wing I have done like you say, my game mode choose which player goes in which team, he set the player state and told the game state a player join a team, in the game state I store a map, actor -> team

#

I made a function in the game state, to find if two players belong to the same team

dark wing
#

So your game mode grabs the team array, and assign the player to one of the teams?

#

why are you setting the player state

#

show me the bp

#

or the code

frosty crag
#

ok if you want I can go on a vocal channel to share my screen as you want

dark wing
#

ok

#

come at #pivot.point

visual sail
#

Does someone know why screen turns black in splitscreen when debug appears?

maiden flame
#

No, but nice anims 🙂

visual sail
#

created a brand new project and the same thing happened

#

debug on splitscreen makes additional local players black

oak flower
#

While testing my game, I noticed that a variable (ECombatState) was not being replicated back to the state I programmed. All configuration parts (ComponentReplication, GetLifetimeReplicatedProps, etc.) are working correctly.

#

The behavior is simple, I press a button to change weapons, perform the swap and change my character’s state to ECS_SwappingWeapons (on the server). At the end of Swap animation an AnimNotify is called, changing back to ECS_Unoccupied.

It works correctly when my main computer is the HOST and I’m testing it on my notebook as a CLIENT, but in the opposite situation it doesn’t work, the SwapFinished function isn’t even called (this function is called through an AnimNotify) at the end of the swap animation.

Could this be an Anim Notify problem, or a replication problem? and if it is replication, would it have to do with the fact that the HOST is a weak computer and is not capable of replicating the variable back?

final wigeon
#

I'm struggling to get a CheatManager set up for multiplayer. I have the client running EnableCheats and am able to define Exec function in a custom CheatManager BP class that I can call from console, but I'm not sure how to get my calls up to the server to do the actual work since nobody "owns" the CheatManager object. I'm sure there's a simple way to set this up but I'm having trouble finding it.

#

Actually, I would think the PlayerController owns it since I have the CheatClass pointing at the custom CheatManager. But any attempt to call a "RunOnServer" event is still called on the client.

silent valley
final wigeon
gloomy tiger
lost inlet
silent valley
#

Yep. Acror component helps keep it separate. May or may not be of interest to you.

lost inlet
#

Which just uses ServerExec from the player controller

#

At work, I did make BP run on server events get the same treatment

gloomy tiger
#

So can you have static functions BlueprintAuthorityOnly that will be bridged automatically to APlayerController?

lost inlet
#

Look at UCheatManager's ProcessConsoleCommand or Exec function (I forget which)

gloomy tiger
#

Ahhh you're specifically talking about UCheatManager

lost inlet
#

And not static

gloomy tiger
#

Sorry, I got hyped for a moment here

gloomy tiger
final wigeon
#

Whew awesome. Got a proof of concept up and running now.
Setup is a CustomCheatManager with Exec function that grabs local PlayerController, gets a DebugCommandsComponent on it that can then do RunOnServer events. Does that seem reasonable or am I adding unncessary steps? I do want to keep any debug/cheat logic local to a single component.

visual sail
#

Funny how splitscreen in ue5 is tossed aside. I don't even have all the extra options to fix my hud stuff.

thin stratus
#

UMG should support split screen just fine

visual sail
#

now the problem with umg: if I get the same widget from the player 1 to get into the other local player 2, the resolution get all messed up. Also the anchor scale with the render and I can't setup stuff on screen for any resolution

#

If I scale down that, this happens

thin stratus
#

Adding the UI to the PlayerScreen instead of the Viewport for any per-Player UI should be enough. This doesn't remove the requirement for you to design the UI to match the screen.

I developed UMG UI 4 years ago already and had no issues with this. You will have to design the UI different if you have 4 players vs 2 players vs 1 player.

thin stratus
#

But I vaguely remember stuff like that

visual sail
thin stratus
#

It's a bit similar to how WebDevs have to solve Desktop vs Mobile

#

The layout will have to change a bit depending on your UI

#

fwiw you can make different versions and make the inner widgets as dynamic as possible

#

e.g. your Characters selection can have an exposed NumColumns variable

#

Or EntryWidth and what not

#

And then you can try to make 3 different versions (think 3 is enough, you need one for the big screen, one for the horizontal screen that appears for 2 and 3 players, and one for the tiny screen that appears for the other two players of the 3 players and for 4 players).

#

You can also try to put everything into one widget, and maybe work with a grid

visual sail
#

I already found a solution for my case since I dont want to create multiple widgets for all the cases for the splitscreen manipulating the render scale and setting all my UMG anchors to 0,0.

thin stratus
#

The thing is

#

We tried all of that

#

It looks like ass in the end

visual sail
#

that's so true

thin stratus
#

The information that you can easily display in the normal 1 Player Screen gets too tiny in the small version.

#

And doesn't look good in the flattened version of 2 players

#

We ended up designing 3 layouts iirc

#

You can try that with a WidgetSwitcher

#

Or by altering the Row, RowSpawn etc. of a Grid

#

E.g. put your elements into a grid and alter the values based on the total number of players and the index of the player itself

#

But that all depends on your UI

#

if that supporst that idea

visual sail
#

In the end I think I'll do what you're saying, but this is ok for now just for testing

thin stratus
#

Actually, now that I'm saying that, I think for at least the in-game UI, we made sure the HUD works in all 3 ways

#

in-game being the HUD with like numbers

#

It was an arena shooter

#

With weapon, health etc.

#

The UI for selecting stuff was more custom, but I can't find images/videos of that anymore

#

The project never shipped. Don't know what my client back then ended up doing with it

visual sail
#

that's alright

#

thanks for your input btw, I'll plan a rework on my hud when I got the time. I'm currently converting all my project to UE5 by hand since I got a nasty problem with corrupted files

thin stratus
#

Like that somewhat worked.

#

But already got a bit cramped on the side for the weapon select

visual sail
#

true

thin stratus
#

Steam isn't offering a lot of pixels

#

Idk what state that game is in on Steam :D it's long lost