#multiplayer

1 messages · Page 61 of 1

grand kestrel
#

This is the third person template with this

void UMyCharacterMovementComponent::CalcVelocity(float DeltaTime, float Friction, bool bFluid,
    float BrakingDeceleration)
{
    Super::CalcVelocity(DeltaTime, Friction, bFluid, BrakingDeceleration);

    if (IsMovingOnGround()) { DebugFloat += 0.2f * DeltaTime; }
    else { DebugFloat = 0.f; }
    
    if (CharacterOwner->HasAuthority())    { GEngine->AddOnScreenDebugMessage(38265, 1.f, FColor::Orange, FString::Printf(TEXT("[Server] %f"), DebugFloat)); }
    else { GEngine->AddOnScreenDebugMessage(38266, 1.f, FColor::Orange, FString::Printf(TEXT("[Local] %f"), DebugFloat)); }
}
#

( CalcVelocity() is a common method called from the physics loops, same result with PerformMovement() )

#

@gleaming vector ^

#

It was breaking my stamina code and I couldn't figure out why until I tested that

#

Probably fine to just do that in regular tick tho, just not entirely ideal and may get a desync from time to time

wheat niche
#

Hey, i have a problem im trying to run a custom event from a client it tries to call SetMaterialServer it replicated (run server only) und and multicast if i press k on the server it works but for the client it wont do anythink can someone help me

grand kestrel
#

Where are you calling these from?

wheat niche
#

is it correct?

grand kestrel
#

Is your cube set to replicate?

wheat niche
#

yes

grand kestrel
#

If so, show your bp graph

wheat niche
#

okay give me a momemnt

#

Replicates:

wheat niche
#

first character second cube @grand kestrel

grand kestrel
wheat niche
#

@grand kestrel i have another question

#

@grand kestrel
i have a question. I implemented a interaction system the problem is that the actor cannot send something to the server after interact it needs authority. im wondering how i can fix it so that the client can send a event too

grand kestrel
#

Only an actor ultimately owned by a playercontroller - anywhere up the owner chain - can call RPC

wooden abyss
#

Hello, I have a problem creating a Widget on clients. In my PlayerController I have a replicated Event that is set to run on owning clients which creates the basic HUD Widget and sets a Ref to the Widget in the Controller

#

My Gamemode calls an Event in the Controller to update the PlayerScoreList in the HUD. The Update Event in my Controller is replicated to run on owning clients as well and reliable.

#

The UpdatePlayerList Event gets called from my Gamemode in the Even OnPostLogin. This works fine for the server but i get a null pointer on the OverlayRef when UpdatePlayerList is called on the client

#

I did the same thing to add "PlayerCards" in my Lobby Gamemode/Level

#

Exact same setup

#

But I have no idea why the OverlayRef cant seem to be set for the client in the CreateOverlay Event

#

Anyone has an idea why this could happen?

grand kestrel
#

There is no guarantee that those clients even have a valid playercontroller replicated to them at that point in time, in fact, its unlikely because the playercontroller has only just begun play

#

Your game mode can't possibly have a reference to a widget either because gamemode only exists on server

#

It also wouldn't be appropriate to pass widgets around if you even can, they are client only and a visualization of what is happening

wooden abyss
#

My gamemode doesnt have a reference to a widget

grand kestrel
#

Is that the controller?

wooden abyss
#

This is in my Gamemode. The UpdatePlayerList Event exists in the controller

grand kestrel
#

I might have misread that part

wooden abyss
#

And I loop over all the controllers to call that function

#

The ref is saved in the controller

grand kestrel
wooden abyss
#

I might have just found the culprit

#

Like I said I have the exact same setup for my Lobby. There it works fine. The difference is that my clients connect directly by using the Join Session blueprint. When the host starts the game inside the lobby I call this to load the new level

#

In that case the UpdatePlayerList gets called before the Event BeginPlay

#

But only for the clients

#

The Clients cant have a ref to their widget at that point cause its created in the Event BeginPlay

#

The servertravel also takes like 3-5 seconds

#

I had added a delay in my Gamemode so that the Controllers have enough time to run the BeginPlay Event

grand kestrel
#

Is there a reason to store this on gamemode instead of gamestate with a repnotify (and therefore no need for pricier netmulticast)

#

netmulticast is generally for time sensitive stuff you need right away

#

Replication is comparatively cheap

wooden abyss
#

Its a PlayerList with scores that is always visible so I wanted to have it updated as soon as a player joins. Thats why I called it in event OnPostLogin

#

Each player entry in the list is a seperated "PlayerCard" Widget that then update the score on their own

#

But in case someone connects or disconnects I want to have the correct "amount" of player cards shown

buoyant kelp
#

Why did I click the mouseleftbutton once while 2 bullets were created?

wooden abyss
#

Well it does work with a delay of 3 seconds but it just seems that the servertravel is rather slow. Is there another method to move all the clients to a new level that doesnt take that long?

#

Do you spawn the bullets on the server? Might be a replication problem that the client also spawns a bullet?

grand kestrel
gleaming vector
#

You can like, combine moves too

#

To get different dt values

wooden abyss
grand kestrel
#

Not sure how accurate that will be though

gleaming vector
#

There is a thing you can inherit override, but i forget it's name

#

But, did you try scaling by deltatime?

grand kestrel
gleaming vector
#

Ag, yeah

#

Sorry on my phone about to go to bed

grand kestrel
wooden abyss
#

But I dont really understand why there is such a huge delay between the Event OnPostLogin and the Event BeginPlay for my client player controllers

gleaming vector
#

Not without looking myself and my cat has already claimed my legs so no going to my pc tonight lol

grand kestrel
#

You know, it occurs to me, I probably don't need to add stamina to net prediction at all - only when we're in a drain state, because I'll let the player do something that costs 50 stamina even if they only have 1 left, it just penalizes them for running out fully

wooden abyss
#

Is it feasible to add a dispatcher to my Player Controller that fires whenever the BeginPlay has run successfully and have my Gamemode bind to that dispatcher so it knows when that controller was setup correctly?

grand kestrel
magic furnace
#

On Server when a new instance of a pawn is made my BeginPlay does not fire. My gamemode upon restart destroys all pawns and for each controller spawns a new one. This works but for the host BeginPlay does not fire after the first time, any ideas?

thin stratus
#

The PredictionData of the CMC, ServerSide, is that reset somewhere when unpossessing or so?

#
    if (CharacterMovement)
    {
        CharacterMovement->ResetPredictionData_Client();
        CharacterMovement->ResetPredictionData_Server();
    }
#

Okay they do

#

But why is that not happening if I manually set the Controller to a valid one after Unpossessing hmmmm

latent heart
#

You're trying to use a valid player controller without possessing?

thin stratus
#

Yop

latent heart
#

That seems like folly! 🙂

thin stratus
#

Reason is: The Character is currently controlling another Pawn during an Ability.

#

And the original one still needs a valid pointer to Controller and PlayerState for scoring etc.

#

And all of that works fine, just the RootMotionSource is not playing

verbal tendon
#

Seems like a dependency on the character issue

latent heart
#

Why does your character need a controller and player state for scoring to work?!

thin stratus
#

Cause if that Character dies no one otherwise would know who he is

#

Unreal Tournament does it the exact same way with the Redeemer Projectile

#

The only issue I have is with RootMotionSources and the CMC

#

Everything else works just fine as expected

#

Currently I'm trying to puzzle together why a frame after unpossessingthe CMC suddenly has PredictionData again, including actual values for CurrentClientTimestamp

#

Even with Tick not doing anything

#

Where the hell is it getting that Data back from..

#

Ah, there are still ServerMove calls coming in after the Unpossess. Guess that makes somewhat sense

latent heart
torpid girder
#

Hello, is there any logic in AGameMode that needs to be called before a player can spawn into the world?

twilit radish
#

Generally I think the first approach is the best, I would not specifically specify "I interacted with the elevator" because of the obvious scenarios of "What if I add a door? A cup you can pick up? A different button you can press that's not in an elevator?" and with that also comes state management like "What if I don't want a player to press the button when they are holding something with both hands already like a chair they could have picked up?". Then you need to link those all manually up and that will get an absolute mess.

However I would take a slightly different approach to what you're currently doing. Instead of a generic "I interact with the elevator" implement the generic way per button. The button should already know what elevator it belongs to. So if the button is the interactable object you can easily implement it as "Button 1 is pressed, get the elevator object it belongs to, lock whatever state you need to lock and make the elevator do its thing".

#

Sorry first sentence should have been "with the elevator" not button.

#

My first thought was to have it as an interface, but I'm not sure if interface references can be networked honestly 🤔
You could definitely try it though, if it works it would look something more like:

UFUNCTION(Server, Reliable)
void Server_InteractWith(IInteractableObject* Object, ACharacter* Interacted, Payload?)
```Then you can decouple the logic from an actor in specific.
thin stratus
#

The default Getters aren't virtual.

twilit radish
#

For payloads in specific you could do it similar to the CMC where you just pass a struct/class or whatever along with it so that you can then cast towards an object that inherits from it and can push that same inherited class/struct over the RPC.

#

Which could also solve your button issue if you don't want to use (or can use?) an interface for the current actor you have.

#

Yeah, it's definitely not always practical, even possible or it making sense to have separate objects for everything and in those cases a payload definitely makes more sense. Ideally I still think the buttons can just be processed through an interface, but if a payload does the job too why not 😛

#

But that was in the specific case of the buttons 😄

#

As long as it's not a specific RPC for all your specific objects. That will absolutely get a nightmare to manage 😅

frank birch
#

so, since Warning: CanServerTravel: Seamless travel currently NOT supported in single process PIE
How do I enable multi process PIE?
The following checkbox is unchecked and I restarted the engine but it still tells me that I am single process

#
    if (World->WorldType == EWorldType::PIE && bUseSeamlessTravel && !FParse::Param(FCommandLine::Get(), TEXT("MultiprocessOSS")))
    {
        UE_LOG(LogGameMode, Warning, TEXT("CanServerTravel: Seamless travel currently NOT supported in single process PIE."));
        return false;
    }

ok, then I need to run UE with MultiprocessOSS 🤔

#

yep, that did it ❤️

woeful ferry
#

Are there any good classes for generating unique IDs for replication? FGuid seems like a whole lot to replicate

#

Need it to identify indices in an array.

frank birch
#

what is the problem with FGuid? 🤔 however, if you only need indices of an array... then do make that ID the index of the array 🤔

#

or make a global integer that increments each time you ask for it, so you always get the next one 🤔
an infinitely growing int will always be unique

woeful ferry
#

Some indices are supposed to be recongnized as one, that's why I need a identifier for those

#

But yea I can do the integer thing

frank birch
#

make a singleton static thingy (or a subsystem) that has an uint (uint8, uint16, uint32, whatever gives you enough indexes) and every time you ask for a new ID you return the current value of that int and then increase it. Only the server should call/have this thing. The server gets a number and gives it to the corresponding player.
Downside: Any player can guess the others number and maybe impersonate them (if they are evil)

#

no idea how sensitive this is 🤔

torpid girder
#

hello, i am trying to figure out why i can't simulate a dedicated server in UE, i am running as a listen server, but the problem is it seems like a client is never spawns, so i don't see two calls the player controller, one from a server, one from a client

frank birch
#

you will get a terminal (the dedicated server) and a game screen (the client)

torpid girder
#

i thought client was p2p

#

wow something is very broken LogLinker: Warning: [AssetLog] D:\src\frith_PHANTEKS5950X_ARoK\arok\Avalon\Content\Blueprints\MainMenu\BP_GM_MainMenu.uasset: VerifyImport: Failed to load package for import object 'Package /Game/Blueprints/MainMenu/BP_Avalon_MainMenuController' i can find it

torpid girder
thin stratus
#

In theory, if I have a Client owned Actor and I send an RPC in frame x and I then remove the ownership after sending it, what does the server do when receiving the package?

#

Does it check if the Actor is still allowed to process the ClientRPC?

robust oriole
#

how do i go about constructing an object at runtime that is stable for replication? PikaThink

#

or is that even possible

thin stratus
#

Depends on who is resposnible for the movement

#

But you need some interpolation either way, yes

#

Yeah then interpolation on the client side

#

Uff, not sure. CharacterMovementComp is very tricky to follow

#

ProjectileMovementComponent might have some interpolation code

frank birch
#

Why doesn't game mode notify games rate when a player arrives/leaves the game/server? Would a multicast in gamestate called when gamemode decided be enough?
(Just making sure I didn't miss anything)

twilit radish
#

notify games rate
Sorry, but what are you referring to with 'games rate'?

fierce grove
#

What is the best way to attach a pawn to a mesh in multiplayer? it seems to work randomly when trying to attach a pawn to something.

twilit radish
# thin stratus Does it check if the Actor is still allowed to process the ClientRPC?

Don't quote me on it, but it seems like it just validates the data first and then immediately after turns it into a bunch. Either queues it up or sends it immediately to whatever processes the connection. But I would expect at this point for it to not be checked any more. Would be a bit ridiculous if they start looking through bunches that are already being send out to see if it actually should have.

#

What may however be an issue that I'm not sure about is that if you remove the owner before it has had the chance to be send out whether it can still refer to that owner connection. (Which I kind of assume not).

real ridge
#

guys does anyone know why I have bugged timer when I respawn my player ? :/

thin stratus
#

So something somewhere must filter

#

The MoveCOmp for projectiles has replication :P

twilit radish
thin stratus
#

Client -> Server

twilit radish
#

Well that makes sense right? The server doesn't accept incoming packets from actors that aren't owned by that player. So if you remove the owner on the server then the server is going to reject that as otherwise cheaters could do a lot of stuff they shouldn't be able to do.

thin stratus
#

Yeah but I'm talking about ServerMove packages that were already send by the client

#

But haven't reached the server yet

#

Because if that would happen, then the server would set/increment the Timestamp of the Client in the Prediction Data. And since that is 0.0 on unposessed pawns (after unpossessing) I assume that this doesn't happen

#

I noticed that if I unpossess but set the Owner back to a PC (no possession), it process "old" ServerMoves from before unpossessing

#

Hence me wondering if there is some filtering happening when receiving packages

frank birch
solar stirrup
#

Got a quick question, what exactly makes subobject replication expensive? I know the packet header also needs to contain the outer actor's id, but anything else i'm missing?

#

Makes sense to avoid it for the CMC as it calls tons of RPCs every second, but what else?

thin stratus
#

Character actually calls those RPCs

#

Just to be clear :P

solar stirrup
#

Well, yeah because they wanted to optimise the cost of the RPCs

#

afaik

thin stratus
#

Yus

solar stirrup
#

But like, what else is there to know about subobject replication that makes it costly?

#

Because I'm not really seeing any other reason to really avoid them, unless you have a CMC scenario

twilit radish
# thin stratus Hence me wondering if there is some filtering happening when receiving packages

Yes it happens when receiving packages on the server. The channel calls GetNetConnection() on the actor belonging to that channel. Then it checks if that connection is the same as the current connection for the channel and if so sets:

RepFlags.bNetOwner = true;
```This is later on used in `DataReplication.cpp` to check through a method called `ShouldCallRemoteFunction` in the net driver if it actually allows it or not which it doesn't allow in this case any more because you have removed the owner at the time of processing it.
https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/Engine/Private/DataReplication.cpp#L1315
https://github.com/EpicGames/UnrealEngine/blob/release/Engine/Source/Runtime/Engine/Private/NetDriver.cpp#L6689-L6692
#

So the owner must be set at the time that packet arrives or it will ignore it as it can't guarantee any more that you are / were the owner of that connection. Even after already having send it from the client.

thin stratus
#

Alright. Thanks for confirming.

#

That explains the bug I have when setting the Owner/Controller again after unpossessing

#

sigh

frank birch
#

when is a rep notify fired? before or after the variable changes? 🤔

#

maybe before this... repnotify is meant to run on client machines, right? When the server changes something clients get a repnotify, right?

river hazel
#

After. You can get the old value in the parameter of the onrep

twilit radish
#
public:
  UFUNCTION()
  void OnRep_CustomVector(FCustomQuantizedVector PreviousValue); <---- PreviousValue
```Unless we're talking blueprints then I have absolutely no clue.
frank birch
#

How can I tell if a PlayerState is "local"? 🤔
When the localrole is remote and the owner (playercontroller) exists? 🤔

twilit radish
#

I would just grab the player controller from it and use IsLocalController() on that.

frank birch
#

prior safety check because controller might be null if a remote client asks for somebody else, right? 🤔

twilit radish
#

Player Controllers aren't replicated to others. So if you're doing this from client 2 (client 1 being the host for example) while being on client 3 then client 2's player controller doesn't exist.

frank birch
#

from my previous repnotify question:
RepNotifies only run on clients and never on server, right? 🤔

twilit radish
#

In C++ correct. In blueprints they do run on the server.

frank birch
solar stirrup
#

Yep

#

The Set node fires the rep notify

frank birch
#

Okay, just to make sure blueprint isn't doing a nasty on me, using the Set w/ Notify node from a client... only sets it locally, right? 😰
please tell me that it's not a disguised rpc 😰

frank birch
#

ok, at least I am safe on that one 😅

wheat niche
#

i started my multiplayer game in unreal engine as follows: Num of players2, net mode: play as listen server and new editor pe. On My GamMode class i tried to create a userwidget and add it to the viewport from the player controlelr that i got from the postonlogin event but i get this error: Only Local Player Controllers can be assigned to widgets. PlayerController_1 is not a Local Player Controller. what should i do now?

chrome bay
#

BP "Notifies" are more like "call this function whenever this variable changes".

#

Which sucks

#

tbh

frank birch
#

GamMode class i tried to create a userwidget
oof, please reconsider 👀
ListenServer should work, but dedicated servers will go up in flames because they don't have a screen and GameMode only lives in the server 👀

#

Consider creating your userwidgets either in the BeginPlay of HUD class if you are a peasant like me, or do what eXi does: #multiplayer message

potent coral
#

for some reason this code wont trigger a RepNotify when called on client, what am i doing wrong?

#

thats the rep settings i used on that variable

#

when i click the widget on server it works fine and triggers the OnRep, though not from the client

chrome bay
#

Widgets don't/can't replicate or have replicated properties

#

Widgets should talk to/read from some other object that contains the state and does the replication

potent coral
#

so i just pass on the owning player from the widget and do the replication in my pet code?

chrome bay
#

TL;DR, widgets shouldn't have netcode / game state info in them

#

The widgets' domain starts at showing stuff to the user about the game, and taking inputs from them, but that's it

#

Putting actual game logic in them is very not ideal

potent coral
#

the other stuff i made works though

chrome bay
#

I doubt it does

potent coral
#

but it does

chrome bay
#

That won't work in MP

potent coral
#

i tested it, it works

chrome bay
#

Unless you are actually on the Server when interacting with that widget

#

Won't work for a client

potent coral
#

it works on both server and client

#

both can rename him and both see the change

chrome bay
#

It can't work. You're calling an RPC in a widget which has zero network functionality

potent coral
#

do i have to stream it to you?

chrome bay
#

Only if you want me to repeat myself...

prisma snow
chrome bay
#

The only explanation is the test-case is broken

prisma snow
#

Maybe Sweeny wanted us to code our game logic using slate macros

potent coral
#

maybe the problem is where im constructing the widget?

chrome bay
#

If "Pet" is a replicated actor that was spawned by the Server, then only the Server will execute that "change name" function. A "Run On Server" function that is called on an object with no network functionality is just treated like a regular function

potent coral
potent coral
chrome bay
#

The only logical explanation here is that "Pet" is not a replicated actor, and instead something that exists locally on the client

potent coral
#

pet is a Character

chrome bay
#

But who spawns it?

potent coral
#

its placed on the map

chrome bay
#

What's 100% definitely happening is the "Name" property is only changing on the client interacting with the widget

#

for everybody else, it'll be whatever it was before

#

unless the server player changes it, in which case it'll replicate (assuming it's a replicated property)

potent coral
#

the renaming works for both

chrome bay
#

Although there's another wierd thing happening here which is that you're setting a property via multicast RPC

#

That looks like the Server changing it to me

potent coral
#

name isnt replicated, it comes from the text box

chrome bay
#

I mean the "Name" property on the Pet itself

#

Also FText shouldn't be replicated either, it's localised text

potent coral
#

there is no name property, i just set it in a text render with this event

chrome bay
#

The deeper we go the worse this gets 😄

potent coral
#

yes xD

chrome bay
#

State = Properties always

#

Otherwise, RIP

#

Relevancy + Late Join will break instantly

potent coral
#

wouldnt the text render component just get replicated to anyone who joins because the character is replicated?

chrome bay
#

negative

#

Text Render component doesn't have any replicated properties

#

So even if you mark the component as replicated, it has no actual data to replicate

#

But also, since it's being changed via a multicast RPC, any clients that drop that RPC or don't receive it won't change the text locally

#

And if the actor leaves/reenters relevancy range, it'll be back to default too

#

Any persistent change you make needs to be a property set by the server and replicated to clients

#

Then you use an OnRep to apply changes if needed

potent coral
#

ok thx i will make new code based on this

#

but then how would i communicate stuff from a widget to the server?

prisma snow
#

you don't

chrome bay
#

^

prisma snow
#

widgets only reflect/display the state of the game

chrome bay
#

The widget should basically read info from the game, and ask the game to do stuff

potent coral
#

so from my widget i trigger a function/event in my character that sends stuff to the server?

chrome bay
#

Yeah exactly

#

What's annoying is Epic could probably make this easier to understand by not allowing you to add replicated vars/events inside objects which don't support it... but I've been asking for that since 4.0 sooooooooo

prisma snow
#

Ye at least it shouldn't be there in the blueprint graph

chrome bay
#

Just keep in mind you can only call RPC's on stuff you "own" too

#

yeah

potent coral
#

well at least now i know xD

prisma snow
#

For simple setup I recommend PlayerController or Character

chrome bay
#

Lots of people understandably try this stuff then end up hitting walls

#

And it's not obvious if you're new to MP

prisma snow
#

Is Character owned by the client in the same way that the Player Controller

#

?

potent coral
#

not sure, there is also local player controllers

prisma snow
potent coral
#

they not needed at all?

prisma snow
#

not sure but it's related to multi-screen local games and messy from what I understand

#

so better use the proper ways for networking

potent coral
#

ohh ok

frank birch
#

riding on the question, if for any reason (most likely the reason is that I fucked up) a client that doesn't own an object attempts to call an RPC of that object...
Nothing happens? or the RPC is ran locally? 🤔

chrome bay
#

The engine will just log the error and do nothing

#

It checks on client before sending, and also on server when receiving

frank birch
#

it logs it? that's good! 😅
if I am not seeing any of those logs it means I didn't fuck up 😛

#

is UProjectileMovementComponent somewhat replicated? 🤔

chrome bay
#

not directly

#

It just moves the actor, but the actor itself would replicate it's transform/velocity

wheat niche
#

Hey, i have a problem. im using the event onpostlogin and im trying to add a numg to the player controller but i get this error Only Local Player Controllers can be assigned to widgets. PlayerController_1 is not a Local Player Controller. Can someone help

twilit radish
#

Unless this is a local multiplayer game don't add UI in the game mode to player controllers. It only exists on your server and not on your clients, they also do not have any networking capabilities. So you're trying to assign the widgets to a player controller that's indeed not local. Initialize them in something like the HUD instead 🙂

wheat niche
twilit radish
#

The player state gets replicated to other clients too, not the place you want to initialise UI exactly either I would say.

wheat niche
kindred shadow
#

is there a way to fallback if you have multiple platformservices?

#

I currently have and I'd like to be able to not have to manually edit this with GOG or any other service name, wondering if there is a way to handle this

[OnlineSubsystem]
DefaultPlatformService=STEAM
pallid mesa
#

You'd need to build multiple authentication graphs for that

#

or use EOSPlus w/ EAS and setup custom providers

vagrant grail
#

How to replicate the mesh of the BP_ThirdPersonCharacter being rotated 90° horizontally (like if he's sleeping). He's rotated locally but it's not replicated to others

pallid mesa
#

haha thats cool

#

well there are many ways to do this.. through animation

#

and having some sort of replicated proning variable that you set in the server

#

read that from the anim graph and play the looping state

#

or you can simply Have an OnRep variable in your character that simply sets the rotation of the character mesh

vagrant grail
pallid mesa
#

because you aren't setting it in the server

#

😅

twilit radish
#

Hey Vori, when are we getting an article on Iris? Asking for a friend.. 👀

fathom aspen
#

I'm the friend, I affirm the question

twilit radish
#

😂

#

I expect an article from you too.

fathom aspen
#

I will do it once vori gives up patrick_hehe

twilit radish
#

Poor Vori.. 😅

#

I'm honestly just curious about the performance. I've still not seen anyone post any comparisons between the two.

fathom aspen
#

Once someone gets it to work they will do

twilit radish
#

Does it not work?

fathom aspen
#

I had nightmares trying to make it work. But the other day I saw a post where you need to edit some ini files for it to work

#

There is also a CVar you need to turn on (but not sure if that alone is enough - don't think so)

twilit radish
#

You definitely need to set a pre-processor too somewhere, all that code is #if IRIS 😅

misty stirrup
#

anyone know of something that explains the client connect to server process?

#

from how i understood the documentation, you can seamless travel to a server you've connected before, so i was thinking maybe if on initilization it did a quick connect to each server??

twilit radish
#

You can't really seamless travel between actual instances. An instance/server it self can seamless travel to a different world though. But the connecting to a server is always a hard travel.

misty stirrup
#

so what do people have to rewrite to get soft travel in unreal games?

twilit radish
#

I don't exactly know, I never attempted it. Assuming we are still talking about what you want to do and not regular seamless travel. It's possible through modifying the engine I suppose, there was someone who did it not too long ago in here but I don't know what parts they modified. Although I wouldn't expect there to be any topics about this.

#

But IIRC the initial connection to the first server was still a hard travel.

real ridge
#

guys can I ask? I have timer in game state with replicated time and I am printing it on my screen but when I die and my player get respawned its counting little weird like 2 numbers were there it looks like this here is how I am checking if its valid to not create new one but it seems problem is not in it
also my name get deleted after respawn
thhis is how I am respawning

fathom aspen
vagrant grail
pallid mesa
#

you cannot send Rpcs from a non owned actor

pallid mesa
vagrant grail
pallid mesa
#

your interaction interface can do such thing

#

you can put your interaction component in the character or the controller and send rpc events from there

vagrant grail
pallid mesa
#

you'd do it a bit more generic Diver

#

you'd create an interaction component or interface

vagrant grail
pallid mesa
#

and rather than call it "Sleep" you call "Interact"

#

on the character

#

and the bed implements the interactable inteface

vagrant grail
#

Look the bed has already the "Interact" interface

#

And it's called by the BP_ThirdPersonCharacter

pallid mesa
#

yeah, so your interaction happens in the server which is good!

#

:D

#

now its a matter to implemenr the behaviour

vagrant grail
pallid mesa
#

u dont need the extra RPC's

#

if the interaction is happening already on the server

vagrant grail
#

which ones ?

real ridge
pallid mesa
#

the ones in sleep/wakeup

real ridge
#

just in widget it seems wierd

#

weird

vagrant grail
pallid mesa
#

no

vagrant grail
#

then I don't understand

pallid mesa
#

so

#

assuming your interaction system is already giving you server flow

#

you don't need more server RPCs

#

because you are already in the server

#

in fact those server Rpcs will never work cause the bed is a non owned actor

vagrant grail
#

So in simple words, what do I have to do ?

fathom aspen
#

Honestly those are simple words, you are just lacking the knowledge to understand

vagrant grail
#

I understood the part with the server, but what do I need to do with the Sleep and Wale Up Event besides changing those to not be server anymore as the workflow is already server

pallid mesa
#

so once you got the interact flow in the server

#

you can call a wakeup (boolean) function in the character

#

and have the onrep implemented in the character

#

if you did everything correctly, the mesh should rotate, also ensure u are using the proper axis

pallid mesa
#

mh i may have an idea...

#

are you adding this widget to the viewport when you respawn by any chance?

#

xD what can happen is that you dont erase the previous widget in every respawn

vagrant grail
#

This works locally but not in multiplayer ☝️

turbid island
#

How do I replicate this event? When it fires it just aims at 0,0,0 because the server/client doesn't know anything about other's mouse positions (I think). This event is on tick.

It is supposed to just smoothly rotate to face the direction the mouse is in. It is a somewhat fixed camera arpg type game, so I can't use control rotation without it messing things up.

vagrant grail
pallid mesa
#

this is local execution

#

that's no server flow

#

also get player character when you are in the character is no bueno

#

Casting is not getting

vagrant grail
# pallid mesa

This is not in the character, this is in the bed BP ☝️

pallid mesa
pallid mesa
pallid mesa
# pallid mesa

also, if you are calling the two events in your character, remove these other two variables

pallid mesa
teal jolt
#

where would one go to get a few volunteers to run some testing for a peer to peer networking test in unreal5?

real ridge
#

so it's should be cleared

#

i don't understand it

#

maybe I fucked somewhere maybe it's server timer and its showing for client too idk

#

honestly

pallid mesa
#

Woopsie doopsie, it looks like you haven't clear it out properly

pallid mesa
#

hahaha

#

but indeed take a look right when you spawn the new widget and right when you remove it

turbid island
pallid mesa
real ridge
#

because I need something similar for my plane and I don't have idea how to make jt

pallid mesa
#

so you can pass in the mouse input to the server @turbid island

turbid island
#

I understand that, but don't know how/where to start writing the code for that. Do you have a simple example you can link?

pallid mesa
#

@vagrant grail save up on rpcs! you are already in the server diver!

pallid mesa
vagrant grail
pallid mesa
#

yeah, look here Diver

turbid island
vagrant grail
pallid mesa
#

i recommend you to put some print strings to understand if you are in the server or not

#

its a bit hard to keep track of it at first, but you'll get used to it

vagrant grail
pallid mesa
#

you don't want rpcs there because you are already in the server

#

so you should make them... not rpcs

#

and if you want a RPC version of the node

#

just make a RPC version of the node

#

hehe

vagrant grail
#

better ?

pallid mesa
#

yes sir

#

now...

#

forget about the jump event

#

and test this first part

vagrant grail
#

works locally but not in multiplayer

pallid mesa
#

can i check the interact method

pallid mesa
#

can can you verify that you reach the interact event in the server?

pallid mesa
#

can you show me your onrep variable?

turbid island
pallid mesa
vagrant grail
pallid mesa
#

one sec brb bathroom

real ridge
pallid mesa
#

aight im back

#

im sorry that was a kinda long break

#

@vagrant grail So I think I figured while I was in the bathroom

#

you cannot really rotate the character mesh 😬

#

because the sim proxy is actually refreshing its transform every tick

turbid island
# real ridge and are u printing your mouse cursor on window? and moving with it or?

nah using mouse only for aiming/interactions, I made a project with with mouse movement before and it feels pretty bad without spending tons of time making sure the nav mesh is perfect. I also don't like how limiting it is. You can't really have any platforming elements with mouse movement.

not sure if i understood/answered your question

pallid mesa
#

so your logic is indeed good, but we cannot simply rotate the mesh like that

vagrant grail
pallid mesa
#

basically the logic that we built together and the logic that you have now

#

animations!

vagrant grail
#

I don't have laying down animations 😒 that's why I wanted to do this this way

pallid mesa
#

you can do it on tick i believe, just take this "prone" boolean

#

and apply this rotation every tick

#

i think this might work

dark edge
pallid mesa
#

just tested it

vagrant grail
grand kestrel
#

The proxy mesh smoothing conflicts

grand kestrel
#

I bet paragon and fortnite do it too

pallid mesa
#

In fact it should be fixed in 5.1.1

grand kestrel
#

Really? I already made my own solution that doesn't rotate mesh and just uses actor rotation 😄 Its flawless

pallid mesa
#

be careful with that 😬

grand kestrel
#

pandahmm what does that mean

#

It works well, its better than Lyra's solution

pallid mesa
#

you cannot turn the capsule just like that!!

#

the proper solution is un UT

grand kestrel
pallid mesa
#

have an animation that does the turning for ya :D

grand kestrel
#

I still rotate the capsule based on extracted root motion from TIP anims 😄

pallid mesa
#

as long as you are careful with the cmc interop it should be fine

#

I missed it was you Vaei!

#

I'm sooo sleppy you don't imagine 🤣

grand kestrel
#

It definitely is fine 🙂 It's very much battle tested

#

Zero desync zero jitter in any situation

#

As far as I'm concerned Epic have been teaching the wrong way to do TIP

#

If we're turning the character then just... turn the darn character

pallid mesa
#

yeah you've been here for ever, thought I was speaking with someone else 😄

grand kestrel
#

Ah yeah I jumped in 😄

pallid mesa
#

I'm kinda curious what Lyra does in 5.1.1

#

because if you look at the release notes, its claimed to be fixed

grand kestrel
#

Probably something hacky with the mesh interpolation

#

Did try that myself before thinking "why am I copying them when it clearly isn't adequate"

pallid mesa
#

but yeah if you look at UT, the turn in place is basically rotating the capsule

#

and having animations that counter rotate it

twilit radish
#

How old is UT now though?

grand kestrel
#

I didn't think to look at IT, but my system follows that principle

pallid mesa
#

the genious sync move

#

UT is from 15''

grand kestrel
#

UT still teaches a lot worth learning, the projectile prediction is worth its weight in gold

pallid mesa
#

yes, archaic, but just works™️

grand kestrel
#

I completed that prediction years back, even implemented rewind for projectiles characters vs projectiles

twilit radish
#

GAS would like to know your location.. 😛

pallid mesa
#

yeah unfortunately GAS doesn't handle predictive actor spawning

twilit radish
#

It does not?

pallid mesa
#

I wanted to make an article specifically about that

grand kestrel
#

Yeah that's when you use UT's solution

pallid mesa
#

but I needed to chillout from articles

lost inlet
#

if only more happened with the NPP too

pallid mesa
grand kestrel
#

The arrows I fire in my game will use UT style prediction. Its quite simple really, you tick the movement component based on the instigating player's ping 😄

#

I had UT projectiles pooled as well

pallid mesa
#

now, needs some love, its obvious

twilit radish
#

I've started learning GAS since 1-2 days ago and I already managed to corrupt my project with it somehow x)

lost inlet
#

iirc it's effectively abandoned though

grand kestrel
#

Yeah GAS isn't really that friendly to get into but once you've beaten your head into the wall long enough its truly fantastic

#

No its literally abandoned

lost inlet
#

so GAS is the only real out of the box prediction system that isn't the CMC

pallid mesa
#

read a bit around in udn

thin stratus
#

GAS prediction system is basically non-existing though

lost inlet
#

I haven't started my new job yet so I'm temporarily out of a UDN account lol

pallid mesa
#

I like when eXi roasts UE systems 🤣

grand kestrel
thin stratus
#

That's part of my job

pallid mesa
#

yes!

lost inlet
#

and I thought on UDN someone from Epic stated that the NPP wasn't receiving any future major development

twilit radish
#

But.. Isn't one of the main selling points of GAS its prediction/networking support?

thin stratus
#

The prediction is more or less limited to the few things GAS offers

grand kestrel
#

IMO its main selling point is the gameplaytag implementation 🤣

lost inlet
#

gameplaytags are independent though

pallid mesa
#

i gotta go now guys, have a good evening/night o/

thin stratus
#

Activating an Ability. Applying a GE through that Ability and fwiw GameplayCues

grand kestrel
#

Yes but they implemented gameplay tags into an ability system is what I meant

thin stratus
#

Anything beyond that is kinda useless

grand kestrel
#

I'm just too lazy to type properly

thin stratus
#

Specifically rolling back your own stuff when something gets rejected is kinda shite

#

And since you can't predict removal of GEs, you can also throw the whole "Use GE for Cooldowns" out of the window

grand kestrel
#

GAS seems like an afterthought "oh they found our paragon stuff and actually want to use it, might as well"

thin stratus
#

Which the majority of people do due to docs saying so

#

GAS is used on Fortnite too though

twilit radish
#

The cooldown thing and not being able to predict it supposedely is definitely a bit awkward from what I've seen so far yes.

thin stratus
#

Epic doesn't use GEs for cooldowns either

#

But you only learn that here randomly when Cedric or someone else rants, or on UDN

#

<3

twilit radish
#

😄

thin stratus
#

Or in some random forum post fwiw

twilit radish
#

Imagine having UDN access though.

thin stratus
#

ANYWAY, I'm still mad about CMC and RootMotionSource stuff atm

twilit radish
thin stratus
#

When we worked on The Ascent, I honestly wondered how anyone releases a game of that size or similar without UDN

#

The Engine was falling apart more and more the further we got

grand kestrel
thin stratus
#

And most of the things asked by us were things that could affect everyone, but the questions had to be private for reasons. So others will still have to figure stuff out on their own

grand kestrel
#

I "sync" my ragdoll using those, did they break something 😄

thin stratus
#

No, but I have issues with them atm

#

I followed UT's Redeemer logic of temporarily possessing another pawn and keeping Controller Owner and PlayerState alive on the "main" Character. And everything works just fine, only RootMotionSources are breaking apart if you have anything but a possessed Character or unpossessed Character.

#

Unpossessed Character with a Controller being valid? Straight to jail.

grand kestrel
#

Oh no 😄

thin stratus
#

TickComponent doesn't even handle that case, so I had to write that myself.

#

And even then, since the Character still has an Owner, it receives the ServerMove calls from before unpossessing, which recreates the Server Prediction Data

#

And sets the CurrentTimestamp on them ONCE

#

And to use RMS, you gotta either have 0.0 as CurrentTimestamp in that Prediction Data

#

Which is the case if you unpossess

twilit radish
#

In the defence of CMC, this is a very specific thing to do though.

thin stratus
#

Or have it increment properly, which happens through ServerMove

#

But since the RPC only comes in like a handful of times and the not until I re-possess the character, it's stuck

#

So my idea for Monday is: In Server_Move, return when it's not a fully possessed character

#

Probably gonna hit the next wall after that

#

But since a lot of internal stuff relies on Controller and PlayerState pointers and those Getters aren't virtual, I can't really inject my own pointers

grand kestrel
#

Btw cedric question since you're here, my project is still ~3 years from anything akin to completion, would it be worth switching to iris early on (i.e now) to try and future proof the netcode since I'm currently focusing on developing that

thin stratus
#

Also the project is so big that I don't want to go through every little possible reference and replace it

grand kestrel
#

You'd probably want to call FlushServerMoves too

thin stratus
thin stratus
grand kestrel
#

They did say its meant to be backwards compatible true

#

You're right

#

Saw that yesterday 😄

thin stratus
#

I mean, you can enable it and try it out

#

I personally wouldn't

grand kestrel
#

Yeah I'll wait until they develop it a bit further then

thin stratus
#

Which we found out the hard way

grand kestrel
thin stratus
#

We have a Cast time before and it took me ages to figure out why with the cast time it was causing corrections on the RMS

#

Also, about Iris, and also these new Materials. I just gave my employees the links to the "docs" and had them learn it upfront. Gotta enable it once it's taking over

#

But with Epic, no one knows if that actually will happen any time soon

real ridge
#

Question it's good to have same game mode in menu and my game map?? where I do have login and Lobby and options? it's all offline+websockets for lobby and chat and then I am joining session where is also game mode, should this 2 maps have different or same game mode?

thin stratus
#

I strictly cut my game in as many GameModes as possible

#

Usually:

  • GameMode_Base
    -- GameMode_MainMenu
    -- GameMode_Game
    ---- GameMode_Lobby
    ---- GameMode_Gameplay
#

And then Gameplay has children for custom stuff if needed

#

And that goes for all the other classes too if needed

#

So PlayerController_Base, _MainMenu, _Game, _Lobby, _Gameplay

#

GameState_Base ...
PlayerState_Base

#

Not all of them are needed

#

E.g. PlayerState_MainMenu or GameState_MainMenu might not be needed as I usually have no custom logic in the mfor MainMenus

#

AND NOW, I will head to bed

#

CYA

real ridge
#

i understand but I should not use game mode base and game state base when it's multiplayer,or?

real ridge
thin stratus
#

Same with GameState_Base

real ridge
#

okay so we still stick with mp

thin stratus
#

I actually never use the simpler AGameModeBase versions of epic

real ridge
#

right thanks

#

i did , do not do it pls

fathom aspen
#

Not if PlayerController persist the seamless travel

#

This is when that happens

hollow swallow
#

very new to multiplayer, but am i able to have my game (very early stages) on steam that i can share with friends so they have it in their library and it can be update etc... but its not published on the actual store? Mainly was want it for testing

prisma snow
graceful flame
hollow swallow
#

Yeah i did see that, im happy to pay that, but how playable does it need to be at that stage? could i just use the 3rd person character and then set that up? or do i need a fair amount done first?

graceful flame
#

Alternatively you could upload your game to any other file host and distribute copies privately.

dark edge
#

It can be literally anything if they're given a key through steamworks

hollow swallow
#

yeah steams just easier so my mates can just update on the go xD

#

rogey thanks guys appreciate it

#

my first project so ill start diving into it. want to get all the nitty gritty multiplayer stuff done first

dark edge
#

I'd get the ball rolling on Steamworks asap

#

takes a while

#

I've only ever done the developer one, the release state override might depend on the product passing some sort of QA

hollow swallow
#

Cheers mate, looking into it now. how longs a while? a few days?

dark edge
#

Took me a few weeks but that includes making my LLC and business bank account etc

hollow swallow
#

"Before your store page or game build can go live, there is a brief review process where we run your game,"

#

not sure if i can just have a very basic person running around a room then xD

#

i think its more refering to if its a full release though

graceful flame
#

It's more like they want to filter out all the illegal / bad stuff, the quality of your game is up to you. But I'm not a lawyer or Valve employee. Just taking a guess.

opal pulsar
#

thoughts on prefixing functions you only want to run on the Authoritative version of that actor with Auth_, similar to how its convention to use Server_ or Client_

prisma snow
hollow swallow
#

Yeah, i only enjoy multiplayer games, so i want my first project to be one and learn all that side of it first

#

easier than trying to convert a game after xD

low helm
#

I strongly suggest learning non-multiplayer fundamentals before trying multiplayer code

#

Anytime you write multiplayer code there are like 12 things that can go wrong

#

but if you're already new to code, that adds an additional 20 things that can wrong, so your chances of solving problems through guess-and-check become exponentially less likely

hollow swallow
#

yeah i understand that, i originally started with unity. no coding experience. had a basic multiplayer game, map, hp, xp, leveling, weapon switching, ai and a few more all working correctly over the network in about a month. it was a massive headache, but im glad i learnt it early as you have to write everything completely different to suit

#

it will probably never be a fully released polished game, more just a hobby to share amongst friends

#

and so far, networking seems 100x easier in unreal than unity

fathom aspen
#

Still could be same PC class though

fathom aspen
#

Well that was been said in the attached picture, and then I said it again :/

#

I don't think you'll get it tho

low helm
#

Exactly which code is breaking

#

post a pic

thin stratus
plush crow
#

Hi guys, is there a way for a joining player to load a Certain map first like customization map before joining the actual Game map?
something like: Main_Menu -> Customization -> Gameplay map

pallid mesa
#

yes... you could do that

real ridge
#

Guys do you have idea why I cant read value in my game mode from player state? I am printing empty team despite I am having it in player state because I am also printing it there any ideas?

#

maybe is cast failing?

#

no its not I just tried print there string

thin stratus
#

Is this on the first spawn?

real ridge
#

wdym first spawn

thin stratus
#

Well you posted ChoosePlayerStart

#

Which is used in the GameMode to find a Start Location for a player

real ridge
#

lol just tried add another player after first spawned and for him its working

#

so prolly yes first player is wrong

#

I have numbered spawns 1- 5 for red team and 6 -10 for blue if game mode check from player state player is blue he pick random number from 6 to 10

#

but when I package game every joined player is in red team however it doesnt get value from player state idk why

thin stratus
#

Well ChoosePlayerStart is called very early for initializing the players spawn. You'd need to ensure that your Team is already set at that point

#

Where do you set the team value?

real ridge
#

In lobby I login in game Kamil / Kamil then I am in menu I click find game it will throw me in lobby maked from websockets there randomly will pick me team it will store in game instance, from game instance it goes to player state after joining server because player state gets erased after joining server and then from player state I am getting it for choose player start

#

bit complicated?

#

its clear XD ?

grand kestrel
#

Looking for some insight on net prediction for Stamina. I've moved it to CMC now. My game doesn't care about what your stamina is, it will let you consume your 1 remaining stamina point for a 50 stamina ability, what it does care about is that when you use up all your stamina you enter a "drained" state, and then after the stamina fully regens you recover from the drained state.

So do I sync the stamina float, or do I sync the drained bool, or both?

real ridge
#

its spawning me near red base despite I am blue team

#

oh I need upload it on youtube

thin stratus
#

You still need the float in the saved moves for combining moves

#

For the boolean you can also sync that on corrections

real ridge
#

is video working guys ? 😄

#

i cant load it

grand kestrel
#

It works

thin stratus
#

The boolean probably needs to be in the saved moves and actually be restored on replaying, not sure

thin stratus
real ridge
real ridge
thin stratus
#

You are setting them in the lobby?

#

Are you moving the value over to the new playerstate in CopyProperties?

grand kestrel
grand kestrel
#

If it gets out of sync at all it's pretty catastrophic until they realign

thin stratus
#

Just make sure you don't actually replicate those values

#

They should be non replicated vars

#

And test your stuff on more than 60 fps on the client

real ridge
# thin stratus You are setting them in the lobby?

in lobby you can see I am on right side that means I am blue team It will store my team in MyGameInstance, then I click play and it will join me session, after that I have on event begin play in my player state loading my team and nick for player from MyGameInstance that you can see as player name above me.

Then when its finally in playerstate I am taking this value on choose player start from player state to spawn it.

thin stratus
#

To test combined moves

real ridge
#

oh shit I just realized player state is created/loaded after spawning isnt it ?

#

thats why its empty...

#

F Me

#

I am right?

thin stratus
#

Well no

#

But

#

Your setup uses the GameInstance

#

So you have to first ask the client

real ridge
#

but in game mode I cant cast to game instance

thin stratus
#

That takes way longer than ChoosePlayerStart

#

Yeah of course not

#

You can't use ChoosePlayerStart then

real ridge
thin stratus
#

You need to do that logic when the team is being set

#

So when the client calls back with a server rpc

real ridge
#

I cant bro because my lobby is offline and session online

#

I am telling my lobby is made with websockets

#

I have teams and nicks in own database

#

only way how to store and pass it is game instance

#

it persist after join

thin stratus
#

I never said anything else

#

I only said you need to move the logic you have in choose playerstart, as well as your spawning logic, to when the client tells the server the team

#

Otherwise this will never be timed correctly

real ridge
#

ahhhh

#

and if I will add 1 sec delay ?

#

on choosing start

thin stratus
#

You can't

#
  1. It's a function, no delays allowed
  2. This is a ping problem, if you have a lag it will break again
real ridge
thin stratus
#

Somewhere you are setting the team

real ridge
#

this is very first time team is being set for server

#

and name

thin stratus
#

After retrieving it from the client

real ridge
#

in player state

#

it s here

#

i am casting to instance and setting it for state

#

(there is custom event) because after respawn I was loosing name

thin stratus
#

The setPlayername rpc

#

That's where you set the team on the server

#

In that RPC you can notify the gamemode and then do your spawning logic and choose playerstart stuff

#

Eh

#

Wait

#

You need an RPC that tells the server the team

#

The Team in the GameInstance is not available to the server. You need to RPC it to the server the same way you send the name

#

And then in that RPC after setting the team you can do your spawning

#

Then it'll be timed correctly

real ridge
#

okay will try

#

thank you for tip ser

#

player state is both client/ server do I Need rpc or just multicast?

#

okay tried it

#

F same result

grand kestrel
#

@thin stratus do you know of any docs for sending the adjustment? It comes from ServerMoveHandleClientError, and I made a derived FClientAdjustment with the float/bool in it, but I'm wondering if I'm meant to handle it separately from what CMC does natively, or if I tack on my own functions/RPC/etc and handle it separately

#

I've done it before but don't remember where 😄
E: seems like I just route an RPC to/from the Character from SendClientAdjustment and ignore engine PendingAdjustment stuff

real ridge
#

I even treid state is loading before game mode and despite that I cant get there value watafak

#

i just tried load also name and nothing

thin stratus
#

And tell CMC to use that

#

You don't need to perform additional rpcs for this

grand kestrel
thin stratus
#

Iirc you make a member property with your custom child

#

And then in the constructor you just call the method that expects a pointer to the steuct

#

Struct

#

I just can't recall the name atm

#

You also send those packed structs in Server Move by now instead of just the flags as it was before

grand kestrel
#

I've got it using my custom FNetworkPredictionData_Server_Character with it's custom FClientAdjustment, just trying to find where you tell it which adjustment to use

thin stratus
#

Na Not that one

#

Give me a few min then I give you some code

#

Get a coffee or so in the meantime

grand kestrel
#

ServerFillResponseData! ..I think?

#

Mm nope that's not it. I'll wait 😄

#

Coffee.. that's a brilliant idea

twilit radish
grand kestrel
#

That's definitely a start

plush crow
#

hi guys, any tips on how to make a client travel to a certain level after joining session? not really sure what I'm doing wrong here 😵‍💫

I have setup my create session to load the customization map, but when the host has transfered to the gameLevel, the clients when joining are being redirected to the gameLevel map instead of the Customization map.

here's a snip of my blueprints

#

create session:

#

join session:

thin stratus
#

Are you trying to have a Client be on a different Map than the Server while being connected?

plush crow
#

button to game_level:

plush crow
thin stratus
#
  1. If a Client is actively connected (Session doesn't matter), they will and have to be on the same map as the Server. Minus the exception of Seamless ServerTravel where they are temporarily parked on a Transition Map.
  2. If you use the "JoinSession" node, it will result in the Client connecting to the Server via Client Travel after resolving the Connection String of the Session they joined. That's all happening in the Join Session node. So after calling that you will be connect to the Server and point 1. will take effect
#
  1. ServerTravel is only meant to move Server + Clients from Map A to Map B together. And only the Server should call this.
#

Also not sure what your Reliable Server RPC with "GM" in its name is supposed to be

#

Given you are probably not connected yet in the same frame, this is still your pre-game GameMode. Also RPCs on GameModes are redundant.

#

And if you Client Travel after Joining, you will be disconnected from the Server

#

In other words:

  • Either you handle your Customization stuff before even Joining the Server
  • Or you handle your Customization on the Gameplay Map after Joining the Server
  • Or you handle Join Session yourself and you don't connect to the Server at the end of the JoinSessionCompleted call and do that later
#

Third option is probably the best for your flow (if that works) but requires C++

#

@grand kestrel Loads of info coming in:

#

Struct you should inherit from is called FCharacterMoveResponseDataContainer

#

You should override ServerFillResponseData and Serialize

#

And implement your own stuff there

#

Example:

struct FVRTCharacterMoveResponseDataContainer : FCharacterMoveResponseDataContainer
{
    typedef FCharacterMoveResponseDataContainer Super;

public:
    virtual void ServerFillResponseData(const UCharacterMovementComponent& CharacterMovement, const FClientAdjustment& PendingAdjustment) override;
    virtual bool Serialize(UCharacterMovementComponent& CharacterMovement, FArchive& Ar, UPackageMap* PackageMap) override;

    bool bIsDashing;
    float DashPower;
};
#
void FVRTCharacterMoveResponseDataContainer::ServerFillResponseData(const UCharacterMovementComponent& CharacterMovement, const FClientAdjustment& PendingAdjustment)
{
    Super::ServerFillResponseData(CharacterMovement, PendingAdjustment);

    const UVRTCharacterMovementComponent* VRTMoveComp = Cast<UVRTCharacterMovementComponent>(&CharacterMovement);
    const AVRTCharacter* VRTCharacter = Cast<AVRTCharacter>(VRTMoveComp->GetCharacterOwner());

    bIsDashing = VRTMoveComp->IsDashing();
    DashPower = VRTMoveComp->GetDashPower();
}
real ridge
#

I am lost every time when I am trying to get any variable from player state in game mode its empty.... what I am doing wrong meh

thin stratus
#
bool FVRTCharacterMoveResponseDataContainer::Serialize(UCharacterMovementComponent& CharacterMovement, FArchive& Ar, UPackageMap* PackageMap)
{
    if (!Super::Serialize(CharacterMovement, Ar, PackageMap))
    {
        return false;
    }

    if (IsCorrection())
    {
        Ar << bIsDashing;
        Ar << DashPower;
    }

    return !Ar.IsError();
}
#

You make a member variable of that struct FVRTCharacterMoveResponseDataContainer VRTMoveResponseDataContainer;

#

You call this in your Constructor SetMoveResponseDataContainer(VRTMoveResponseDataContainer);

#

You override

#

virtual void ClientHandleMoveResponse(const FCharacterMoveResponseDataContainer& MoveResponse) override; in the CMC

#

You cast the Response to your version const FVRTCharacterMoveResponseDataContainer& VRTMoveResponse = static_cast<const FVRTCharacterMoveResponseDataContainer&>(MoveResponse);

#

And then update your CMC from it

#
                if (VRTMoveResponse.bIsDashing != bIsDashing)
                {
                    if (VRTMoveResponse.bIsDashing)
                    {
                        StartDashing();
                    }
                    else
                    {
                        StopDashing();
                    }
                }
                
                DashPower = VRTMoveResponse.DashPower;
#

I had to more or less copy paste the parent version of ClientHandleMoveResponse

plush crow
thin stratus
#

Because the parent function does some extra things and has some ifs and else that had no individua lfunctions

#

I call Super at the end of my override

#

And wrap the code into

if (MoveResponse.IsCorrection())
    {
        if (!MoveResponse.bRootMotionSourceCorrection && !MoveResponse.bRootMotionMontageCorrection)
        {
#

There is a tad more to it, the ClientHandleMoveResposne function is probably the most annoying one to share

#

I'm doing a lot of the stuff that Epic does before I actually correct the CMC state

#
            bool ValidMoveResponse = true;
            if (!HasValidData() || !IsActive())
            {
                ValidMoveResponse = false;
            }
#
// Make sure the base actor exists on this client.
            const bool bUnresolvedBase = VRTMoveResponse.bHasBase && (VRTMoveResponse.ClientAdjustment.NewBase == NULL);
            if (bUnresolvedBase)
            {
                if (VRTMoveResponse.ClientAdjustment.bBaseRelativePosition)
                {
                    ValidMoveResponse = false;
                }
            }
#
            // Make sure the SavedMove still exists
            const int32 MoveIndex = ClientData->GetSavedMoveIndex(VRTMoveResponse.ClientAdjustment.TimeStamp);
            if (MoveIndex == INDEX_NONE)
            {
                ValidMoveResponse = false;
            }
#

And then the code I posted first with the Start/StopDashing is wrapped in if (ValidMoveResponse)

#

That's more or less what you find in the parent functions

#

Now filling the data

#

let me check where that was

#

Ah actually I posted that already

#

That's the ServerFillResponseData part of the struct itself

#

That should be more or less it

#

The only other thing I do in all cases is to Override ClientUpdatePositionAfterServerUpdate

#

Because Epic does stuff like this:

const bool bRealPressedJump = CharacterOwner->bPressedJump;

#

Where they save the current state of the key press and then do all the SaveMoves and then restore it

#

I needed that too and there are no overridable functions for that (as usual)

#

So copy paste native it is

#

And then added this before looping the saves

    /// SaltyPandaCedric - Keep track of other Flags
    const bool bRealDash = bWantsToDash;
    const bool bRealBoost = bWantsToBoost;
    /// SaltyPandaCedric - Keep track of other Flags
#

And this at the bottom before returning

    /// SaltyPandaCedric - Keep track of other Flags
    bWantsToDash = bRealDash;
    bWantsToBoost = bRealBoost;
    /// SaltyPandaCedric - Keep track of other Flags
#

Also make sure that you store your float in the saved moves

#

And use CombineWith to restore it

#
void FSavedMove_VRTCharacter::SetInitialPosition(ACharacter* Character)
{
    Super::SetInitialPosition(Character);

    const UVRTCharacterMovementComponent* CharacterMovementComponent = Cast<UVRTCharacterMovementComponent>(Character->GetCharacterMovement());
    if (IsValid(CharacterMovementComponent))
    {
        bSavedWantsToDash = CharacterMovementComponent->WantsToDash();
        DashPower = CharacterMovementComponent->GetDashPower();
    }
}

void FSavedMove_VRTCharacter::CombineWith(const FSavedMove_Character* OldMove, ACharacter* InCharacter, APlayerController* PC, const FVector& OldStartLocation)
{
    Super::CombineWith(OldMove, InCharacter, PC, OldStartLocation);

    const FSavedMove_VRTCharacter* OldVRTMove = static_cast<const FSavedMove_VRTCharacter*>(OldMove);

    UVRTCharacterMovementComponent* CharacterMovementComponent = Cast<UVRTCharacterMovementComponent>(InCharacter->GetCharacterMovement());
    if (IsValid(CharacterMovementComponent))
    {
        CharacterMovementComponent->DashPower = OldVRTMove->DashPower;
    }
}
#

That's because on Client Side UE processes Move X and if it can Combine it with the next one, saves and merges it, and then calls again next frame and process Move X and Move X + 1 together, which means Move X gets processed twice. So the Combine With function has to restore the float value back to what it was before Move X was processed

#

Otherwise the Client will, when combining moves (more than 60 fps for example) drain the float too fast

#

AND that's it. Good luck

grand kestrel
#

Thanks so much for that, it saves me an incredible amount of time 😄

twilit radish
#

Network compendium 2.0 has just been released.

#

😂

grand kestrel
#

I'm actually not following with the parent function for ClientHandleMoveResponse, I don't see how it fits in

thin stratus
#

I will send you my consultation fee. - Mercy

grand kestrel
#

I suspect Epic might have changed it since, there's no .IsValidMoveResponse, but there is .IsGoodMove

thin stratus
#

Could be, this is 5.1 though iirc

grand kestrel
#

Yeah I'm on 5.1 too, maybe I'm in the wrong place

thin stratus
#

Yeah so

#

You'd theoreitically override the bottom most one

#

But you'll notice that it has no access to the Move Response

#

Cuase some genius parsed it

#

So you are stuck with overriding this monstrum

#

And ensuring that you perform the same checks before applying your corrections

#

That's why my function is so big

grand kestrel
#

So the entire body here... I replace ClientAdjustPosition_Implementation( with?

thin stratus
#

No, you still call super at the end

#

Eh

#

Wait

#

Yeah I don't override ClientAdjustPosition_Implementation

#

I override ClientHandleMoveResponse

grand kestrel
#

Yup that's what I overrode

#

But it calls it at the end

grand kestrel
#

Ahh I get it now (hard not to since its on a silver platter but...) 😄

thin stratus
#

You need access to the MoveResponse to get your stuff. But ClientAdjustment stuff doesn't have that as a param

#

So yo ugotta override the function before that which is client handle move response

#

But then you are stuck with adding back all those checks they do before applying the corrections

#

CMC needs some more cut apart functions to easier extend it

#

Not a single project I worked on got around copy pasting native code cause there was no proper override available

grand kestrel
#

I've always felt that way about CMC

thin stratus
#

The proper way imo would be to add all the specific checks into the else of the ClientHandleMoveResponse, before calling ClientAdjustPosition and its siblings

#

And then passing the Response Container into them

#

So you can just blindly override those and place your code there

#

But well

#

It is what it is

grand kestrel
#

I always did it for inputs

thin stratus
#

No

#

You have to carefully think about what parts have to be restored or not

#

When the Client processes the SavedMoves, it will basically replay everything it did after the corrected Move

#

So the Correction gives you a corrected value of e.g. 73 Stamina

#

Now your Client will replay 10 moves and land on e.g. 54 Stamina

#

That should be the correct value

#

If you restore Stamina after that you will be out of sync again

#

You only restore the "I want to Sprint" state, because if the last Move had that as "false" but the Client is currently pressing it, it would cause them to not sprint anymore and they have to press the key again

#

so only local input state is really something to save and restore around the saved moves

#

Not the values

grand kestrel
#

Ah yup that makes sense

#

Thanks so much for this

#

Its time to proceed to phase 2 ; test it, and then spend the next 3 days trying to find the one tiny thing causing the desync

thin stratus
#

Yeah the Debug Window of the NPP would be nice for the CMC

#

To see the State at each Timestamp, which are predicted and which were corrected

#

I'm not sure if one can add something like this to the existing CMC due to how many variables and functions one would need

#

Probably via some Child Class

grand kestrel
#

Haven't thought about how you'd go about it tbh, it would be a mission in of itself, next engine release it breaks 😄

thin stratus
# real ridge I am lost every time when I am trying to get any variable from player state in g...

You gotta keep in mind when what is calling. Something like "ChoosePlayerStart" for example probably calls directly after the Player joined. If you first have to ask the Client for a Value they have in their GameInstance, then that's too early. That also goes for events like PostLogin etc. As soon as you have to first ask the Client for their stuff, you will have to move all your initialization code to call after the Client send all that data.

#

Your best bet is to let the PlayerController, locally, call an ServerRPC on BeginPlay (with IsLocalPlayerController ) and sending all required data via that ONE RPC.

#

And then in that RPC you set all the Values and then start your spawning process.

#

I can't give you more than this info. It should theoretically be enough to do what you want. The rest is up to you.

real ridge
#

okay

#

then get those variables from player controller in game mode not from player state

#

right?

grand kestrel
#

Is this the right way to handle IsImportantMove and CanCombineWith for Stamina?

    if (!FMath::IsNearlyEqual(Stamina, SavedAckedMove->Stamina, StaminaImportantThreshold))
    {
        return true;
    }
#

I guess I just set the threshold to a value that works for whatever the max acceptable latency is

#

@thin stratusready for my extremely technical analysis? It isn't working right 😄 <- there it is
At the start, the server inits the Stamina to MaxStamina (20), client inits to 0 and ends up immediately drained, server never corrects stamina amount or drained state.
And, client consumes stamina ~0.5x the server's rate pandahmm (server has correct rate)

verbal tendon
real ridge
thin stratus
#

So the Stamina should also not count into if something is an important move or not

thin stratus
#

YOur problem should only exist for Clients

grand kestrel
#

Should I be checking it for CanCombine

thin stratus
thin stratus
grand kestrel
#

I accidentally pressed a key that put these white boxes above the chests (they have GAS related stuff that might be trying to debug), its causing a huge leak and my framerate rapidly drops, happen to know what I did? 😄

thin stratus
#

No clue

grand kestrel
#

Fun 😄

real ridge
#

ugh

grand kestrel
#

Hmm client still runs down stamina at half the rate and the correction isn't happening

#

Ah should I be putting it in PrepMoveFor and SetMoveFor..

real ridge
#

even I set it like this

thin stratus
#

The stuff you theoretically need for a "Sprinting with Stamina" setup:

  • SavedMove needs bSavedWantsToSprint and Stamina values

  • SavedMove needs to set the CompressedFlags for bSavedWantsToMove

  • SavedMove needs to save Stamina in SetInitialPosition to be able to fix Combined Moves

  • SavedMove needs to set the CMCs Stamina back to the saved value in the OldMove in CombineWith

  • When processing saved moves in ClientUpdatePositionAfterServerUpdate, you should save the real bWantsToSprint value and restore it at the end of the function

  • You should override SavedMoves Clear to reset your bool and stamina float.

  • You need a custom FCharacterMoveResponseDataContainer for corrections

  • You need to have a member variable of the custom type and call SetMoveResponseDataContainer in the Constructor so it is used

  • You should store the corrected Stamina value in this struct

  • You set the value in ServerFillResponseData

  • You fix the CMC value in ClientHandleMoveResponse

  • You usually drain the Stamina in PerformMovement

  • You need two functions for Start and two for Stop of your Sprint
    -- The first two are to set the bWantsToSprint boolean to true and false
    -- The second two are to actually set a bIsSprinting boolean to true and false that you use to actually increase movement speed, as well as in PerformMovement to drain Stamina

  • You should call StopSprinting when Stamina is 0 in PerformMovement
    -- You usually also should set bWantsToSprint to false in StopSprinting, so the Client has to press the key again and can't just hold it, but that's design choice

  • You need to override UpdateCharacterStateBeforeMovement to process StartSprinting and StopSprinting similar to how the parent class does it for crouching.

  • You need to override UpdateFromCompressedFlags to set the bWantsToSpring bool from flags.

  • You might want to override StopMovementImmediately to call StopSprinting

#
  • You can have some convenience functions for "CanStartSprinting" "ShouldStopSprinting" similar to Crouching.
#

@grand kestrel

#

That's the most comprehensive I can explain it

real ridge
thin stratus
#

And why the event that is called server?

real ridge
thin stratus
#

Yeah and?

#

Why do you need a Multicast here

#

One ServerRPC is what I wrote

real ridge
#

doesnt rpc mean multicast + server call 😄

#

?

thin stratus
#

no

real ridge
thin stratus
#

RPC means Remote Procedure Call

#

That can be a Client, Server, OR Multicast

thin stratus
#

You are on the Client here

#

Also that is not correct

#

You can't just pull the reference from there

#

You have to get the PlayerState member variable of the PlayerController anew

#

The RPC moves between PCs

#

The top part is not even executed on the PC that executes the bottom part

real ridge
#

this

#

so its totally wrong

#

?

thin stratus
#

Yes

real ridge
#

i need make new cast then?

#

i am doing it in multiple blueprints

grand kestrel
thin stratus
#

BeginPlay -> IsLocalPlayerController -> GetGameInstance -> CastGameInstance -> ServerRPC -> Pass in data from GameInstance into ServerRPC

ServerRPC -> GetPlayerState -> CastPlayerState -> SetValues on PlayerState that the ServerRPC has as inputs

Additionaly in the ServerRPC -> GetGameMode -> CastGameMode -> call some event that now spawns the Player based on those values

thin stratus
grand kestrel
#

...before it was setup properly it was the right place ;D

real ridge
#

uh my game mode still getting empty player state i dont understand

thin stratus
#

Additionaly in the ServerRPC -> GetGameMode -> CastGameMode -> call some event that now spawns the Player based on those values

real ridge
#

maybe getting that values in wrong way?

thin stratus
#

Buddy

#

I hate repeating myself for you every time

real ridge
thin stratus
#

You can't use Choose Player Start

real ridge
#

why I would make new 😄

#

why

thin stratus
#

Because it calls too early

#

If you do that shitty GameInstance solution cause you have to, then you can't use Choose Player Start

#

You have to do this manually

real ridge
#

ok then question if I will use own event cant I use find player start function inside?

thin stratus
#

You can

real ridge
#

i have tagged player starts by numbers

thin stratus
#

If it's Blueprint Callable

#

Otherwise write your own and call it slightly different

#

You also have to remove the Character/pawn from teh DefaultPawn class in your GameMode and spawn it by hand fwiw

real ridge
thin stratus
#

Cause the automatic stuff again calls too early

#

Your whole GameInstance ServerRPC stuff adds a random dalay to the setup that the GameMode doesn't know about

real ridge
#

should I add player controller of current player in custom event for spawning?

#

and use it as variable to possess?

#

then

#

or find player start will possess it automatically

thin stratus
#

Timeline from left to right

#

Top is Server, bottom is Client

#

Red is when your GameMode tries to spawn and calls ChoosePlayerStart

#

Green is when the Local PlayerController is replicated and calls BeginPlay

#

Blue is when your RPC arrives

#

As you can see, hopefully, there is a ping delay which you can't bridge with a delay.

real ridge
#

thats why second and other players had no problem

#

after first spawned

thin stratus
#

Respawning at least should be fine

#

But the initial spawn would not work

#

That's why you do the spawning after the RPC arrives

real ridge
#

is this good for sending game mode my controller?

#

so it will know

#

who is going to spawn

thin stratus
#

You are in the PlayerController or not

real ridge
#

yes

thin stratus
#

Just send "self"

real ridge
#

was not sure if I can use it

#

ok now question is this enough just tell find player start to spawn me without spawning by myslef + possesing it or its totally wrong

#

still didnt delete default pawn

thin stratus
#

No you have to actually call SpawnActor

#

And remove the default pawn

#

There is also the option to simply call "RestartPlayer" on the PlayerController

#

You can try that I guess

real ridge
#

I am already using it for dead

thin stratus
#

You can try that here too

real ridge
#

should be same yea?

thin stratus
#

As it will call the whole Find Player Start etc. logic again

#

Just make sure you somewhat filter the original call where they didn't have a team yet

#

e.g. return nothing if no team

#

(in Find/ChoosePlayerStart)

real ridge
#

what if I tried this?

#

it already has start spot

#

okay its not working its spawning nothing

thin stratus
#

Just calling restart player should be enough

real ridge
#

but it seems if i will let set default pawn as my player

#

its working