#multiplayer
1 messages Β· Page 231 of 1
Then you'll need to limit it with your own timer, yes
Hey guys. I was doing some code and I was wondering. Is it alright to call 2 different server RPCs inside a function?
Yes you can
Sure but depends on why
thanks guys! Did you end up writing a tutorial on that or nah? I was never able to get to it
Not that I'm aware of. This whole thing is an general topic of GAS and CMC using two different (their own) approaches for Prediction.
The NetworkPredictionPlugin was a good candidate to solve that, but in the end is basically more on the side of the CMC in its approach, and still mostly incompatible with GAS in that regards.
Even if you put the Stamina into the CMC, you can't use GAS directly to alter it.
The only thing you can do is have a LOCAL ONLY Ability to start sprinting, or whatever consumes the Stamina.
And then have the CMC handle all the prediction etc. itself.
There was one solution to this on a Client's project, but it was rather complicated and I don't remember how that exactly worked.
Let alone feel good about sharing that exact solution. The idea behind that was to listen to GAS Adding and Removing Gameplay Effects, and housekeeping a local copy of whatever they caused in the CMC.
There was still the issue of Removal not being properly predictable fwiw.
ah thanks cedric, defs sounds best to keep them seperate still, thanks for sharing those details, there's a lot of nuance with multiplayer in UE sometimes
First time doing this kind of stuff, i have a game instance subsystem where i do my steam stuff, which in turn is gonna call my lobby player controller for the callbacks, does this code look OK? im worried my PC is not gonna exist and cause issues
Hi, I am wondering how you would go about doing server functions within the controller of a pawn instead of doing it all inside a character blueprint ?
What I mean is that I have all the input mapping context inside the controller so the Input Enhanced Events and when I try to play an animation montage on all connected clients only the server see's the animation the clients do not.
I think the reference to the TopDown Charater is the main issue but im not sure what I would plug in here to call these events from the player controller and not inside the character itself. Thanks.
i have code for that in c++ gime a sec
u need to get the anim instance
Ahhh ok thanks! π
Hmm i cant seem to plug the anim instance into the montage node.
There's a few things wrong here if your intention is to play an animation for all connections.
1.) You're only setting your `"As BP Top Down Character" on the server, "Event On Possess" does not get called from the controller's owning client.
2.) You're trying to call a multicast RPC on something that doesn't exist for anyone but the server and the owning client.
3.) You're calling another server RPC from a multicast RPC.
There's some basics you're not quite grasping here. I'd recommend reading up a bit more.
Here's a good starting point: https://cedric-neukirchen.net/docs/category/multiplayer-network-compendium/
I figured that the controller would only exist on the server but just wondered if it was possible to do it this way instead of doing all the server calling within the character itself but will take another look at that article again. π
It exists on the server and the connection that owns it
I,ll take a read of that article i find it quite hard to learn from documentation as it kinda takes a little while to "click" if you know what I mean sometimes you can read it but you cant see how you "apply" it in a real world scenario but i,m sure its a great article once i have abetter understanding. π so thank you π
could someone with experience with steam/threads/subsystems look at this and tell me if this could some how go wrong pls?
I find this article is quite interesting but it doesnt really show you a real world example or anything its more of a "This does this" more than this is how you can use "this" pretty much the same way a dictionary tells you the definition of a word.
"The Pawn/Character. They are possessed by the PlayerController and during that time, the PlayerController is the owner of the possessed Pawn. This means the Connection that owns this PlayerController also owns the Pawn."
But if I want to play a Montage from the Controller to it,s Controlled pawn (Or spedicially the mesh of tthe controlled pawn) I would imagine that you can use GetControlledPawn and then cast to the pawn's class and then get the mesh from that?
If the playercontroller owns that pawn then it should know about it right? or am i thinking wrongly ?
You are trying to multicast on player controller but remember that clients only know their player controller.
So even if you manage to play the montage on server, it will not play on other clients.
Ahh so a multicast will never work on a player controller because it is not the server right?
rpcs have to follow a chain to get to where you want them to go
so if the PC only exists on the client and u call that rpc on the PC only that client will get the rpc
read the pinned material like suggested earlier
if u want montage animations to play on every character they should be called inside a character
12 times , practice, fail then repeat.
since those exist in every other client
So how do i send an Input Enhanced Event from a Controller to a Pawn to then play a montage and spawn something ?
but the controller still needs a reference to the character to be able to call the RPC even inside the Charatcer yet ?
ur not gonna call the rpc inside the controller
you don't want to use multicast on anything stateful btw
don't pay heed to bp youtube multiplayer tutorial too much
mostly just straight up wrong and usses multicast for the wrong reason
If you want everyone to stay in sync and see the montage, then multicast is not the way
and you can read the pinned material why that's the case.
Ok so I would call Input Mapping Context and stuff inside the character instead of the controller then so i can use the Enhanced Events inside the Character.
I can see that you are trying to do a casting animation. It's going to saves you a lot of time from reinventing the wheel to learn GAS. It comes with multiplayer flavour too
but just learn the basic replication from the pinned material for a start, it's the best source.
I,ll try to understand that documentation at wizardcell also as I said though its kinda like reading a dictionary, I guess read and lots of trial and error is due π
wizardcell and exi's compedium
I think the main issue is that trying to understand what you need to do and where you need to do it. π
Thank you for the advice. π
Could use a sanity check. Am I correctly understanding that SceneComponent's bVisible is replicated?
/** Whether to completely draw the primitive; if false, the primitive is not drawn, does not cast a shadow. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, ReplicatedUsing=OnRep_Visibility, Category = Rendering, meta=(AllowPrivateAccess="true"))
uint8 bVisible:1;
For some reason I had always assumed that visibility was not replicated and was to be set locally, but it looks like I might have been mistaken?
It is
Did you manage to get it working? Setting the vissibility on server only does it for it self to me.
I canβt remember off the top of my head but I believe I only applies to the root component
Ok nvm it is replicated
i didn't tick component replicate on the component π€¦ββοΈ
Is the idea with bOwnerNoSee and bOnlyOwnerSee which are not replicated that the server will replicate the visibility to all of the clients (bVisible is replicated as we've established), and then locally you can fine-tune that visibility further by using the concept of network ownership?
E.g. maybe you want first person weapons to be visible, set on the server, but you want only the owner of the weapon to see the first person version of that primitive component?
i think its meant for first person weapons and meshes like you said, not sure if they had all that "refine visibility" in mind when they created those vars, i dont know tho but i would say they are just there because unreal was originaly an FPS engine?
13.1 Multiplayer Golden RulePermalink
This is a super important rule, that diverges into three golden subrules of multiplayer, of which you should live by:
1 : Use replicated properties for replicating stateful events. (Rep Notify)
2 : Use Multicast/Client RPCs for replicating transient (not stateful) or cosmetic in nature events. (Multicast/Run on Owning Client) (Mainly for particle effects or nothing that impacts gameplay) ?
3 : Use Server RPCs to make the client communicate with the server (basically itβs the only way), and validate the passed data if needed. (Run On Server)
I think the bracketed things is the functionality that they are describing there. Just asking to ensure that I am thinking correctly about what t hey are saying.
Those flags are local only, in that, if the Actor they are attached to has an outer chain that does/doesnt flow back to the local player, it will affect visibility.
They have nothing to do with replication of visibility.
The typical usecase is First Person
Where you might have a First Person Weapon as well as a Third Person Weapon.
Obviously you want to have fine grained control over which context sees what Weapon
Understood. Is sounds like for FPS games the combination of bVisible with bOnwerNoSee and bOnlyOnwerSee is most of what you'll typically need to manage weapon visibility, or is there something else that people often reach out for?
bVisible and bHiddenInGame are pretty much the only options you have.
The owner visibility flags are less useful and more niche.
Ive pretty much only used them a handful of times outside of the FPS usecase above
Roger. bHiddenInGame is at the actor level, bVisible is for scenes within the Actor, if I recall correctly?
Guys im stuck on this since yesterday, my blueprint implementable events crash randomly
for some reason unreal cant find the functions
i moved all the steam related stuff to a subsystem yesterday
call stack doesnt tell me anything rly
i know where the function is
and where it is being called
i rly have no idea where to look
You should be passing weak pointers into the async task.
Also you still need to check the PC is valid in the Async Task before using it
do you think that may be causing the crash?
Well if the PC is gone when the AsyncTask executes, then thats a problem isnt it
You are changing threads
That doesnt happen instantly
TWeakObjectPtr<UPGAsyncAction_ListenForGameplayEventMessage> WeakThis(this);
ListenerHandle = Router.RegisterListener(ChannelToRegister,
[WeakThis](const FGameplayEventMessage& EventMessage)
{
if (UPGAsyncAction_ListenForGameplayEventMessage* StrongThis = WeakThis.Get())
{
StrongThis->MessageReceived(EventMessage);
}
});
Its much safer to use a Weak Ptr
so it can exist in a thread and not in another?
you can probably tell that i never coded with threads
Basically I am new to replication and I was doing an inventory system. I have a server rpc that adds the item to the player inventory and another server rpc that destroys the item that was picked up. Not sure if it is the best approach. I am also doubting that I should not use an RPC to update the inventory but i need to make some verifications in the server before adding the item to inventory, however I am not sure if replicating the inventory array without properly verifying if the item can be added to the inventory in the server can be problematic
some one helped me with the threads code
so i just went with it
ok so how do i make a weakpointer of the PC?
docs are saying i need to build them out of Shared References, Shared Pointers, or other Weak Pointers.
TWeakObjectPtr<APlayerController> WeakPC(PlayerController);
In the same way I posted above
With this
IsValid doesnt like weakPointers
You have to convert it into a strong pointer
if (UPGAsyncAction_ListenForGameplayEventMessage* StrongThis = WeakThis.Get())
So basically going back to a raw APlayerController*
first time in my life im hearing about strong pointers
so strong pointers are just the defautl ones?
Not necessarily. Typically it just indicates that they will hold onto the resource.
i can do my first valid check on the regular pointer then? convert it, pass it, convert it back to strong and then check again?
Weak meaning, it wont stop the resource from being removed
Yes
That pattern is ideal when moving threads, or any latent actions.
Since the latent action might execute in the future where the resources dont exist anymore
So it would be unsafe to use them
does this look alright to you?
Sure, you can use the StrongPointerPC inside the if instead of the WeakPC at that point
Id remove the this from the lambda capture to.
Just FYI, this is probably not going to fix the crash.
im gonna cry
can we do an exercice in fixing the crash? π
But lets cross that bridge when we get to it
im gonna try this and see if it works
You usually only RPC things the server doesn't already know.
If you pick items up with an overlap for example, then no RPC is needed
If you pick them up with a button press, then you RPC the button press and do the rest on the server. Including determining what to pick up, modifying the inventory and destroying the actor
I am using a button to pickup.
The problem is that when I add the whole logic into the server RPC it seems that it is not replicating the things correctly and I am not being able to destroy the item as the client and the item is not added correctly. The BP_Pickup implements an interact interface.
This is an image of my pickup bp, I get the data to spawn using an Id.
void UInventoryComponent::AddItemToInventory(const FName ItemId)
{
auto ItemData = ItemsData->FindRow<FSItem>(ItemId, "");
if (ItemData)
{
for (auto& item : InventoryItems)
{
if (item.Id == ItemId)
{
// Leave function if item is at max quantity
if (ItemData->MaxQuantity == item.Quantity)
{
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red,
FString::Printf(TEXT("Cannot add %s to inventory, inventory is full: %d"), *ItemData->Name, item.Quantity));
return;
}
// Add an item if there is already an item in the inventory
item.Quantity++;
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red,
FString::Printf(TEXT("Added %s to inventory: %d"), *ItemData->Name, item.Quantity));
return;
}
}
// Create the item in the inventory if it does not exist
FInventoryItem InventoryItem;
InventoryItem.Id = ItemId;
InventoryItem.Quantity = 1;
InventoryItem.MaxQuantity = ItemData->MaxQuantity;
InventoryItems.Add(InventoryItem);
GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red,
FString::Printf(TEXT("Added %s to inventory: %d"), *ItemData->Name, InventoryItem.Quantity));
}
}```
I can just execute the function in the server but I do not get the replicated version in my client. I could add another client rpc to get the replicated version but I think it should be avoided when possible as far as I know (btw this is the continuation of the above message)
The inventory variable, usually an array, would be marked as replicated
Which removes the need for the client RPC
@fossil spoke i tried a bunch of times and its not crashing
Thats good.
im still not 100% sure
thanks for the help tho
hopefully its fixed and im just paranoid
It is, somehow it is not replicating. I created a function that prints the inventory of every client in the server and it is not being replicated
As I said, that might not necessarily have been the issue.
But its what stands out given the code you were originally using.
Also not being able to destroy the actor :/ I guess it has to do with the fact that my player does not have ownership over the item?
When working with Lambdas and any latent/async actions, its much better/safer practice to pass WeakPtrs into them
i will keep that in mind going forward, i dont know much about multi threading, if it starts crashing i will bother people here again. Hopefully its fixed and i dont have to deal with steam ever again
Im pretty sure i recommended the RedpointEOS plugin to you earlier?
You will have a much easier time doing all of this if you use that instead.
Just my opinion.
you did, but im using .26 and between not knowing if it is even compatible and re doing the whole social stuff i decided to try to fix it
i even bookmarked it for future projects
Yeah, you would be unable to get it properly working for 26
Its way out of support now for that version
Is an Actor Reset() function typically only called on on the server, or do I simply have things misconfigured on my end? I'm calling Reset Level from my Game Mode, which runs only on server, but I'm wondering if I should be expecting that Reset to be replicated to clients as well somehow? Or is this left up to the programmer to decide?
From looking at the source of GameModeBase, it doesn't look like it cares much for whether the Actor is replicated from the server, so I'm guessing that's left up to the implementer. Hoping to sanity check with those who might know.
void AGameModeBase::ResetLevel()
{
UE_LOG(LogGameMode, Verbose, TEXT("Reset %s"), *GetName());
// Reset ALL controllers first
for (FConstControllerIterator Iterator = GetWorld()->GetControllerIterator(); Iterator; ++Iterator)
{
AController* Controller = Iterator->Get();
APlayerController* PlayerController = Cast<APlayerController>(Controller);
if (PlayerController)
{
PlayerController->ClientReset();
}
Controller->Reset();
}
// Reset all actors (except controllers, the GameMode, and any other actors specified by ShouldReset())
for (FActorIterator It(GetWorld()); It; ++It)
{
AActor* A = *It;
if (IsValid(A) && A != this && !A->IsA<AController>() && ShouldReset(A))
{
A->Reset();
}
}
// Reset the GameMode
Reset();
// Notify the level script that the level has been reset
ALevelScriptActor* LevelScript = GetWorld()->GetLevelScriptActor();
if (LevelScript)
{
LevelScript->LevelReset();
}
}
Reset is only called on the Server, that is correct.
Say I have an Actor with a Collision component, both set to replicate. Do the collision settings of said Collision component replicate from the server to the client, or are to be set locally by each instance of the game? Unfortunately not super obvious just by looking at the source given that it's not as simple as a couple of properties to check, from what I can tell.
My impression is that the answer is no, collision settings are to be configured locally to each instance, but I would love to sanity check.
Collision settings are not replicated.
Thank you.
In a Multiplayer co-op game where you have a save file, what would you do to reload from that save file?
Assuming there is clients connected already and you are already in gameplay
In singleplayer you would simply re-open same level and let it load like it's first time
Thats entirely up to your design won't it.
Some games only allow the host to save. Others everyone keep a copy
I guess we are talking about listen servers only.
I'm not sure if everyone keeps a copy in baldurs gate
Yeah, only host has a save. My question was "how would you handle it when host tries to load from that save"
Or just the host
Like "reload previous checkpoint"
The save file should contain all the data you need to reproduce the same state.
Yeah, minus the part after you saved
But you can't simply re-open same level in MP, can you?
What happens to clients?
There are hard travel and server travel.
Forgot how they work again.
But with server travel no one gets disconnected.
Don't quote me on hard travel (open level) but I think everyone gets disconnected then reconnected π€·ββοΈ
I think you hard travel once when you host and opened a level. And when client joins for the first time.
afterward you should use server travel
For the server only.
Will jump the server to a new world/level.
All connected clients will follow.
This is the way multiplayer games travel from map to map, and the server is the one in charge to call this function.
The server will call APlayerController::ClientTravel for all client players that are connected.
I would guess that it would be like re-opening the same level if you jump to the same level.
@dark parcel @violet walrus A hard travel causes Clients to disconnect. A Seamless travel does not.
Seamless travels can only occur when the GameMode has that feature enabled (its enabled by default) and they only occur for the Server you are connected to.
For example
A hard travel always occurs when you first connect to a Server
When that Server switches to a new level, it will perform a Seamless travel for all Clients.
If a Client leaves that Server, that Client hard travels again to whereever they are going.
Awesome, so I shouldn't over think it.
Hosting new game = Hard travel for server
Joining a game = Hard travel for client
from there on just server travel
I guess?
Calling ServerTravel just causes the Server to switch levels, it has nothing to do with a hard or seamless travel.
So can I just reload same level to reset state just like in Singleplayer?
(Using ServerTravel)
From memory, that was never a good solution.
Typically you should just call Reset
For example, we use AGameModeBase::ResetLevel to do match "rounds"
Like in CoD or CS
So can it reset the world just like re-opening same map?
Every Actor has Reset called on it
Never used it
Its a function that the GameMode calls
On all Actors
So you can determine what state that Actor should return to when the level is reset.
If you want a total clean slate, then yeah, maybe reopening the level is better
But as I said earlier, from memory, that had issues
So it's manual implementation
But those issues might be fixed
Using ResetLevel gives you more control, as you can persist state much easier.
Not like calling AGameModeBase::ResetLevel does a lot. It just same thing as I'd implemted similar interface and called reset on each actor
On mobile, does game receive reliable RPC when app is background?
It should eventually.
Probably better to ask in #mobile
Since im not sure what state the App is in when its in background mode for Mobile.
Is it server only or replicated?
Its only called by the Server.
From my testing, it's seem not.
Then there is more to it that I dont know. I have not developed for Mobile in UE
Good luck π¦
lol

Yeah pretty much
Thats like the worst use case
Maybe tack on 2D as well
Just to be sure
lol
I feel bad for people doing 2D in unreal and pixel streaming
at least epic nuked the web support
while the other just abbandoned.
Oh no, the project I am working on is multiplayer rouge-like mobile game. 
Solo dev?
how does match making even work for mobile
You can call it is an indie company. π€£
As long you have someone to share the pain, it can be fun 
Nah, my team mate prefer use dirty instead of fix from root cause, that make me in pain.
π
Is there some flag I can check to see if an actor fully got its first net bunch?
Oh I guess I can check if HasActorBegunPlay according to this function π€
Did anyone encounter this error?
it appears at this part of the code
void AThirdPersonCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AThirdPersonCharacter, PlayerLobbyInfo);
}```
And it's strange, because sometimes it runs as it should, and sometimes not
Rep notify?
you are gauranteeing that a field called PlayerLobbyInfo exists in code, if this fails you probably messed up the declaration of PlayerLobbyInfo
you have not shown that
yep
and this is my PlayerLobbyInfo
hot reloaded dll
never use hot reload after making header changes
you must build and run from your IDE if you don't know what you are doing to not corrupt things like this... check the pins in #cpp for more details
afaik patch_n implies hot reloading but I could be wrong...
I am prettty sure i ain`t using hot reload
just using this button
do not use that button to compile any header changes
it will break your project in subtle ways
oh so how am I suppose to compile then ?:))
Turn UE off and on.
run + build from an IDE
like close, clean and rebuild, and then open again, and it`s like it compiles itself automatically?
no, clicking on the project is also wrong as that will use the latest development editor binary by default without changing it
what clicking on the project bro
Gain monthsβ worth of Unreal C++ experience in a single article.
Hi, I'm new at working with multiplayer
I've made a project with client/server stuff, everything works fine in editor
I have no clue where to go from there, and how to make a working executable with my project that will connect players to the server
Are there any ressource someone could recommand that explains how to do this?
decide on the server first?
are you gonna have players hosting the server them self (listen server)
or you want to deploy your own dedicated servers
I'd like the least complicated option to setup
From what I could gather that seems to be listen server?
well dedicated gonna cost you money.
yeah no this is just a super simple sample project I'm doing in my free time
You can use steam, I reckon that would be the most viable option
testing is free, but you will have to cough $100 when you want to publish the game.
dedicated servers don't have to cost money. they can still be hosted by someone normally from their own machine
true
I don't plan on publishing, but I do want to be able to send this to someone else and have them test it on their side
listen is by far the most convenient for players
you can use steam and use their test app
Cool, is there a specific tutorial you would recommend?
if you do a system where a player can push slowly a cube using addforce on tick (using player inputs as direction), how would you do so the player CMC speed is always not to high/low so it can stay close enough to the cube ?
for now im moving my cube with AddForce while simulating physics (because the object can fall, go up, etc)
since its MP it means that multiple players can "grab" the cube, and as said all the grabbing player inputs are used to move the cube. The more the players going forward in the same direction, the faster will the cube move
the hard part that i still didnt yet tackle is, how to make the pushed cube not increase in speed (because for reason, the velocity increases even with constant AddForce)
for the CMC i wonder if not using it while moving but just use a SET LOCATION would work, but i guess ill miss all the networkd correction/prediction part
@lament flax Idk, that whole idea sounds flawed. Physics in Multiplayer. Multiple players interacting with it.
This is correction heaven
what would be a cheap solution ?
or, without considering heavy lag, is the idea still flawed ?
does physics have no correction ?
In the Network Emulation settings of the editor, what exactly does the Emulation Target enum do as far as introducing latency? I'm not fully grokking what it means to apply it to server only, client only, or both.
UENUM()
enum class NetworkEmulationTarget
{
Server UMETA(DisplayName = "Server Only"),
Client UMETA(DisplayName = "Clients Only"),
Any UMETA(DisplayName = "Everyone"),
};
also, is there a clean way to override CMC velocity ?
i've never tried to make something where you would change pawns, but im curious on how much of a task it is to implement something like this ? would i need to change controllers or would it just be pawns and would you lose any data / variables from changing from one to the other ?
for example, something as simple as controlling a vehicle or turret like weaponry or soemthing, not sure how crazy that would be to change the pawn, or maybe i wouldn't even need to do so, maybe just do some weird stuff in the character
just possess it
say it was GTA, you could do "get in the car and drive it" as:
Play animation
Attach character to car pawn
Possess car
Now you're driving the car
oh very nice, simpler than i imagined. so i could still deal dmg and what not to character or any char related events via that controlled pawn
assuming your system doesn't depend on the character being currently possessed by a player, sure
nice, and let's say you're controlling something that can go far away from the originally controlled character, would relevancy / anything like this be something i should be aware of ? for example, the character gets killed while controlling the pawn , i.e. do the events on that character still fire on the client that is controlling the other pawn ? and this way if you die, you'd lose control of the pawn and i could destroy that or whatever the logci would be
Depends. You'd probably want some sort of persistent link to character that you wouldn't necessarily want for a car
if a car you drove got destroyed on the other side of the city, who cares
right, and in the scenario where the character is not being controlled ( the character is controlling another pawn) but still in world, and i go far away from my character relatively, if the character were to get attacked and killed bcasue it would just be sitting there and not controlling itself, i'd just want to make sure that client's character doesn't die and they are still controlling some other pawn
I mean it depends
if it's Cyberpunk you'd die
yea for sure, in my case i just want the character to stay vulnerable as if they werent controlling the pawn so that if they don't pay attention i suupose they will die lol , and thus losing control of the other pawn
Yeah it could be as simple as having a char ref somewhere MyCharacter which is valid even when not possessed, you could then be bound to an OnDeath or OnDamage dispatcher on it
OnDeath -> unpossess MyCurrentPawn -> show death screen
that would work for the case where you're piloting your meat suit and for when you're elsewhere
very dope indeed, i like it. going to give some things a try and report back in a few days w findings
Could use some advice for this bizarre issue.
How do I track down what is spawning a player character in my codebase? When I turn on network emulation and joinmy game as a client, then once in a while I end up with an extra ACharacter being spawned at 0,0,0 in my map with no indication of what actually spawned it, how it ended up there. I put breakpoints on every single Spawn Actor call I could find and it doesn't appear that the extra character is created through any of them, only what I expect to be spawned spawn there.
It appears to be the Default Pawn Class of my Game Mode, when I change it, that's the class of the actor that gets dropped in the middle of the map once every few restarts.
Apparently if I set my Default Pawn Class to None this doesn't reproduce anymore, but I wish I had a better understanding of why that happens. Maybe some race condition around the game mode spawning the player character for my controller to possess by default and then not having the time to clean up when I don't end up using it?
GameMode spawns the player. HandleStartingNewPlayer or something like that.
Yeah, oddly enough I have Start Players as Spectators turned on, which is why I think this doesn't reproduce consistently.
@vapid gazelle Not really much to suggest here, other than what you already figured out.
If you are manually spawning your Characters, then you usually set the DefaultPawn to None, cause otherwise, each Client (ListenServer included) gets a Pawn spawned by that.
In a lot of cases, spawning the Character by hand isn't needed though as you have all sorts of overrides in the GameMode to define the actual DefaultPawnClass dynamically, and also figure out where to spawn the Character/Pawn.
Your best guess will be breakpointing the SpawnDefaultPawnForPlayer functions (idk if that's the exact name) and see when they are called and when not.
That's very helpful, thank you π
for some reasons i thought UE had some built in correction for physics
so i didnt thought it would be an issue
Na, quite the opposite
All of your Players have predicted Movement, which will move the Block locally first and then tell the Server to do the same, which then gets send to the Clients.
Which means every Player will think they are right, and none will be.
Is "initNewPlayer" called after a recconect or just the first time a player connects?
also when is "CopyProperties" called?
im trying to figure out the proper way to set data on disconnects and reconnects
Best way to answer that is to go to the function and look for its usages in the code-base
I can't presicely answer that without doing the exact same now, so I think it's probably better if you do it yourself to learn
- Generally speaking, how many times can I expect an OnRep function to be called on the client for a particular replicated property, assuming there's some latency and packet loss involved? I'm noticing that some of the time the OnRep gets called more than once, even though there was only one update on the server to that particular property. Even more times depending on how poor the emulated network conditions.
I'm assuming there's no theoretical upper limit to this, and to be resilient clients should expect to have OnRep fire many times
-
Am I correctly understanding that the server will not trigger replication if a replicated property is never modified at runtime? I suppose there is no need for replication in that case because the constructor will have made the same exact copy on the client and the server?
-
I have this corner case where I'm repping a TList which points at Actors that are replicated to the client. Sometimes the list is replicated before the Actor has had a chance to be. It seems like the engine will re-play the OnRep function once the Actor pointed at by the TList finally replicates. Am I just hallucinating this?
-
In theory only once per change, unless the packages arrive in the wrong order, which I'm not sure would actually matter and have that effect.
The only other case is if you actively set it to Notify Always and you are constantly setting it to the same value somewhere. -
If the value of the variable is set by the Server on spawn of the Actor, then you gotta mark it as replicated. Otherwise the Client will load the Actor with the default value.
-
Yes, cause the List or Array will replicate with its changed size, but with a nullptr in it, due to the client not being able to resolve the instance the NetGUID is supposed to point to yet. Once the Actor gets replicated, the OnRep should call again, now with the correct pointer.
One could argue that point 3. means that for 1. there is another case, but ultimately the OnRep for the Array calls for different reasons and not the same value twice.
I think the same can happen with a normal pointer, assuming it is pointing to ActorA, if the Server spawns ActorB and sets the pointer to it, it might first OnRep with a nullptr and then with the actual actor pointer.
Generally suggested to test your pointers for being valid inside OnReps
Also keep in mind that OnReps might call before BeginPlay for connecting players, which might cause changes in the OnRep to not fully work if they are guarded if HasBegunPlay.
In that cause you'd need to call the OnRep manually on BeginPlay (Client only fwiw).
That's an edge case fwiw
Hi, working on a multiplayer card game
I finished making the game, and everything worked fine when testing in editor with two clients
I'm now trying to implement the Advanced Steam Sessions plugin
I've managed to make it work somewhat, but now one of my client is not a client anymore, and seems to only be showing stuff that's on the server (it doesn't show some of the info that's client-side only, client functions don't work, etc)
I'm very confused atm, can someone explain to me what I'm missing?
Really useful context, thanks a ton. Saving that for my records.
It almost feels like there should be a checklist of these rules to go through any time you make a new Actor with replication inside. It's so easy to forget to bulletproof the class against some of these race conditions and then spend hours hunting for them days or weeks later when someone's packet sequence gets sufficiently unlucky and they repro the corner case.
Yeah, knowing all of that and taking care of it is basically the next level :P
You never stop learning after all
In case any 1 wants to know "overrideWith()" is called on postLogin if i didnt read it wrong.
so data is re added AFTER "ChoosePlayerStart()", so if any 1 has issues with the player not going to the proper player start on reconnect u might need to call "ChoosePlayerStart()" again manually, thats what i am going for anyways
When players with not so good connectinons host a session characters become jittery, is there a var that i can change to help with this?
Not really. You cant make a bad connection better by magic.
well but there has to be something that would make those corrections less noticeable no?
like a correction distance or something
altough im calling them corrections they are not corrections i think
its just the regular interpolation
at least i am assuming it is
Corrections are based on updates incoming from the Server, if the Server has really choppy updates there isnt anything you can change to fix that.
what if the client is bad and is sending choppy data, is there anything that can be done?
overwatch for example, every enemy character and team mate feels smooth and i dont belive every player i encountered in that game has a good connection so there has to be something that can be done
is it a unreal limitation?
players aren't hosting Overwatch
dedicated servers are
so dedicated servers make that much of a diference?
They can
Also, their prediction/rollback could be implemented in a different way (it is, after all, it is ECS) and be more lenient/strict
So for example if a client is running the game at only 20fps but the server has a tick rate of 60, then other players will see the player with low FPS still having smooth animations but they'll appear to be standing around or react slower than those at a higher framerate because inputs sent from the client to the server won't be received as often as they could be.
Is that correct?
It depends on what exactly is being sent from that client to the server... there are a few things that will definitely get horrible at low client fps
Makes sense, I guess that's why prediction methods such as dead reckoning exist for like driving games or boat games. Just use whatever the last input the client sent and presume it remains the same until some new input is received aka keep going in a straight line or keep making a left turn etc.
this is also called extrapolation if that helps... the default CMC setup will actually do exactly this more or less
a lot of different things come into play here
for example higher acceleration will mean differences and mispredictions will have larger differences from the current
and you can sacrifice recency for smoothness a bit
lots of different tweakable things can change how cmc smoothing works
what can i tweak exactly?
a lot... π
out of the box that is
To start with you can change the math sim proxies use to smooth other players
network smoothing mode
there are lot of magic numbers you can tweak to change threshholes for what you consider too far etc
there are quantization levels to sacrifice bandwidth for more accuracy
One thing that helps a lot is to smooth incoming values with interpolation
Unreal does this by default for many things including aim rotation
is this in the cmc component BP?
yes but it should be visible in Acharacter NetworkSmoothingMode
what that means is that if you have two positional updates more than 384 cms apart
it should never smooth between them
generally it can be assumed to be in unreal units
from 2 seconds of reading the source it is indeed just unreal units
for reference with my character
const float DistSq = NewToOldVector.SizeSquared();
if (DistSq > FMath::Square(ClientData->MaxSmoothNetUpdateDist))
{
ClientData->MeshTranslationOffset = (DistSq > FMath::Square(ClientData->NoSmoothNetUpdateDist))
? FVector::ZeroVector
: ClientData->MeshTranslationOffset + ClientData->MaxSmoothNetUpdateDist * NewToOldVector.GetSafeNormal();
}
it is quite a lot so there is no interpolation in that distance
it might be what makes it look choppy
this one, if its further away than this its gonna cause a teleport?
It's easier to just read what smoothclient does in code tbh
with that one it appears to be a kind of max distance you can be from the next target endpoint during an interp
but I haven't read what it actually does
why an object is auto destroyed on client when scaling in a NetMulticast event?
scaling?
like setting the transform scale?
yeah
I would need more info to know what's going on here... is the object replicated?
you can probably just breakpoint the object being destroyed and see the callstack for why the net connection decided to send a destroy command
yeah is is replicated and i am scaling it using timeline
i can share the code in a moment
scale is applied in the progress function of timeline
looks okay to me... override OnEndPlay and breakpoint it
Setting visibility to false on the server ends up destroying the actor on clients. IIRC it's the same for a scale of 0.
I do not like making a new ShrinkCurve object with nothing keeping track of it... does the timeline reference it for GC?
the scale can scale the timeline and float sample
of an asset ptr curve float instead of this dynamically created one
yeah i made uproperty
setting visibility to false disables replication right?
it is
you just have to tick component to replicate
actually not sure about Actor vissibility, was thingking of component's
@lament flax @dark parcel
AActor has no Visibility. Only USceneComponent.
AActor does have bHidden, which is used in IsNetRelevantFor. So setting that to false (in addition to the RootComponent having Collision disabled!) would cause it to stop replicating.
I can't find anything relating to Scale or Visiblity of the RootComponent affecting replication.
@nocturne quail TimelineProgressUpdate.BindUFunction(this, FName("TimelineProgress")); if you need to use BindUFunction instead of e.g. BindUObject, you might want to use GET_FUNCTION_NAME_CHECKED(ADangerZone, TimelineProgress) instead to at least get the sanity check of not typoing it.
On top of that, it might be better to simply replicate the state of the DangerZone instead of using a Multicast to start it locally. That would ensure that it stays in sync. Would need some form of smoothing though, cause the replicated state could come in choppy as usual.
DangerZoneSphere->SetWorldScale3D(FVector(InitDiameter, InitDiameter, 10000.0f));
Is InitDiameter a Scale value? feels like you are making this actor quite too big.
Also kinda confusign what is going on with the initial Scaling and the FinalScale.
this covers the whole map, and the diameter is 3000.0f sets in the bp actor
its EditDefaultsOnly var
DangerZoneSphere->SetWorldScale3D(FVector(InitDiameter, InitDiameter, 10000.0f));
FinalScale = FVector(InitDiameter, InitDiameter, 0.0f);
StartScale = DangerZoneSphere->GetComponentScale();
You are scaling the Z component from 10000 to 0. Is that on purpose?
Right, but 3000 is a scale in that function.
yeah its the z value 10000.0f and a constant will never be changed
Well your final scale has 0 in it
So it is being changed
DangerZoneSphere->SetWorldScale3D(FVector(InitDiameter, InitDiameter, 10000.0f));
FinalScale = FVector(InitDiameter, InitDiameter, 0.0f);
StartScale = DangerZoneSphere->GetComponentScale();
const FVector NewScale = FMath::Lerp(StartScale, FinalScale, Value);
DangerZoneSphere->SetWorldScale3D(NewScale);
later it is handled
Ah in StartShrink
yeah
StartScale = BlueZoneSphere->GetComponentScale();
FinalScale = FVector(NewFinalDiameter, NewFinalDiameter, BlueZoneSphere->GetComponentScale().Z);
on server it works perfectly
You wrote the Actor gets destroyed. Is it also destroyed on the Server?
on client it get destroyed on second phase
nah, on server not destroying
Did you override EndPlay and breakpoint it o see where the destroy call comes from?
still compiling
What is the default of CurrentActivePhase?
this used to read phase data from phase array
int32
That's the type
default is 0
i want to know the value
Ok
That seems wrong then though or not
Cause you ++ it directly on BeginPlay
Means you actually start on Index 1
And then here
void ADangerZone::TimelineFinished()
{
if (HasAuthority())
{
CurrentActivePhase++;
if (CurrentActivePhase > ShrinkPhases.Num())
{
After the TImeline finished teh first time, you would increment to 2, but 2 is not greater than 2, so it will try to read Index 2 from your Array
The if is thus wrong
Needs to be >= or not?
Your Array only has 2 entries, so the indices are only allowed to be 0 and 1.
So yes, you gotta start the value at -1 if you increment it directly and you gotta test against >= Num
i changed it wo strict test later CurrentActivePhase == 7 return
so it never reach outof bounds
I can only comment on the code your shared
And there it's wrong
But the EndPlay breakpoint will tell you more
i have actually 7 phases, so yeah according to the code i shared it is now CurrentActivePhase > 1
Even with 100 phases, if you Increment the Phase Integer on BeginPlay, it needs to default to -1.
And the test needs to be >= Num
Another thing that is not really great is your usage of Multicast + Replicated Variables
You set all the Replicated Properties and then Multicast StartShrink.
There is no guarantee that the variables arrived before the Multicast.
If you need that, you gotta send them directly via the Multicast instead of replicating them
Preferably neatly packed into a struct.
/// Bad
StartPosition = GetActorLocation();
FinalPosition = NewFinalPosition;
StartScale = DangerZoneSphere->GetComponentScale();
FinalScale = FVector(NewFinalDiameter, NewFinalDiameter, DangerZoneSphere->GetComponentScale().Z);
MulticastStartShrink(NewActivePhase);
/// Better
FDangerZoneShrinkSettings Settings;
Settings.StartPosition = GetActorLocation();
Settings.FinalPosition = NewFinalPosition;
Settings.StartScale = DangerZoneSphere->GetComponentScale();
Settings.FinalScale = FVector(NewFinalDiameter, NewFinalDiameter, DangerZoneSphere->GetComponentScale().Z);
MulticastStartShrink(NewActivePhase, Settings);
There is also the point of the second Multicast potentially arriving before the Client even finished the TImeline.
If the first Multicast got send with a higher ping and the second one with a lower, the second Multicast will arrive before the Tmeline finished.
But I don't think that could actively cause any trouble here, as you fully restart the Timeline and only the server calls the Finish delegate.
Still worth noting as people tend to forget about this shit
You should 100% change your setup with the replicated variables though. That's not just a tip but a bug hazard
I recently changed it to that
if (HasAuthority())
{
ShrinkTimeline->PlayFromStart();
}
so now everything is in server controll, and also the endlplay is overrided
lets see what is calling the destroy
compilation is finished
testing now
call stack loading
Yeah that works, but you probably still want all the different values to arrive at the same time, so if your Timeline drives replicated variables, it's best to bundle them into a struct.
And then use an OnRep of that struct to drive the visuals of the DangerZone
You also gotta realize that this whole thing is a STATE and the Multicast is actually just totally wrong
A late joiner or anyone who needs to listen to the Multicast again, won't get that and will never start shrinking the zone
This should be set up to be fully Server driven, with the Client only receiving the minimum of information to drive the visuals via an OnRep.
Yeah so it gets destroyed due to something related to replication.
surely not relevancy, right?
DistanceBased Relevancy could be it given the randomized location of the actor @nocturne quail @nova wasp
Make sure to mark the Actor as AlwaysRelevant
Thanks it works, no more destroying
so yeah AlwaysRelevant was a thing needs to be true π
show more 
its just a sphere shrinking π using timeline
the code is shared above already
U can generate it in like 10 minutes
im interested in your arma mod
its not a mod, its made from scratch π
one more capture
seems very smooth now
Are you still using multicast?
If you are wat about late joiners
yes multicast, and late joiners are not allowed π
Well don't forget players outside relevancy
You probably want to make them always relevant too
But that will come with draw back for large map I guess.
I collect 300 of them in the lobby, and put them in Titanic Ship and land them in a different zone π
battle royal?
then all run away and find loot
kind of yeah
is there a "simple" way to have more CompressedFlags in the CMC saved move ?
i found https://docs.google.com/document/d/1UO6Ww6Lfpti3YElVdo9uioTUtQJQ9CoSLvd9kF8hvJo/edit?usp=sharing but its heavy
Custom CMC Network Data Discord Permalink This document will cover how to use and send custom network data between the server and client through the Character Movement Component, beyond just custom flags. This could include sending additional compressed flags, additional input vectors, etc. No...
cant you just inherit the saved move struct and put your own stuff ontop
it still looks like it uses compressed flags
so add another int for more flags and correctly ensure they are serialized
Hi,
I have a question guys
Is there anyway that I can spawn players on multiple server instances but they can keep presistant and see each other ?
And interact with each other ?
I want to achieve a virtual event like Fortnite one but with big amount of players can see each other
Isn't multiple servers approach have issues when a lot of players gathers in same location? I mean the key requirements for server meshing like Ashes of creation uses is to have players distributed across multiple zones/grid cells so it can be handled by different "server instances". (not an expert)
I was thinking about the server meshing but i missing the concept, like how can i make them see each other
IDK what Fortnite's events is capable of, but I assume smth like music concert or similar art performance are fully scripted from start to end, so it can be played independently on different servers i.e. players on server A and on server B might experience same show without communication between A and B. Though if performance is live i.e. some special player do actions/inputs then it should be replicated to all other server, also if viewers have some way to impact show it will make things even more complicated cuz these actions should be networked to the main server 
I still dont know how Fortnite broadcasted LIVE a show from time squares
Its was sadly a bit low res
@lament flax @little pumice I have an idea for this but I tried to ask here maybe there is another way to do it.
but the idea i have .
adding the event to the level and connect it with NodeJS or any backend server this server controlling and syncing all instances for example you will start play in the backend server to start a music it will start in the server and it will send the current duration and current progress to all running instances this way it can be synced.
I hope there is other idea xD
i got no clue sorry
I think the issue is mostly that UE servers aren't meant to work like that.
In your scenario you'd need a third party that actually communicates between the servers and sends the locations and what not
What you are suggesting would work fwiw
Some socket connection between a MasterServer and multiple UE servers. Does of course add even more latency
And you'd need to handle all the spawning and destroying of the other players that aren't actually connected to the given server
Sounds like replacing UEs replication system, at least if you want to have a complex version of this, is the smarter idea
Not sure what will come from fortnites side
@thin stratus Thanks for suggestion ..
I was looking for way or method won't cause high latency and keep maybe 10 Instances in sync or at least they can see same event at same time.
At least...not until UE6
Hi all, hopefully a straight-forward question: Is it possible for a ReplicatedOn function to be fired before BeginPlay is called on an Actor? I think the initial bunch can be sent before, so all replicated variables might already have been synced before BeginPlay is called, but will OnRep functions trigger before then as well?
Yes
Will often not break anything, but if you happen to use a function in that OnRep that requires the Actor the have BegunPlay, then it would cause a bug.
At which point you'd want to call the method by hand on BeginPlay and add an if (HasActorBegunPlay()) check at the start of the OnRep (or inverted with early return)
@thin stratus Thanks! I have gone with a boolean called bInitialStateSet which is set to true when the onrep function is called. Then in BeginPlay I only need to "manually" call OnRep if the variable has been changed from the default but bInitialStateSet is still false (i.e. the variable was replicated but OnRep wasn't fired because it was too soon)
Why did you go that route rather than the route Cedric said?
It is practically a built-in version of what you're doing.
@quasi tide the reason is I want the onrep to run as normal every time, I just need to handle the edge case where the value was replicated without onrep being invoked on the initial bunch, which seemed to be happening
But HasActorBegunPlay is handling the edge case
I know the situation, but my question is - why did you decide to make a seemingly redundant boolean
I mean I guess the BeginPlay call would be unfiltered in that version.
But in a lot of cases you can determine if you want to call it based on the actualy replicated variable
And it also doesn't really hurt in most cases to call it anyway.
void AMyActor::BeginPlay()
{
Super::BeginPlay();
if (IsValid(ReplicatedActorVariable))
{
OnRep_ReplicatedActorVariable();
}
}
void AMyActor::OnRep_ReplicatedActorVariable()
{
if (!HasActorBegunPlay())
{
return
}
}
Something like that, if you really want to filter.
Maybe I misread, but the solution proposed was if I don't want onrep to do anything if begin play hasn't been called. I actually want it to always fire and do it's thing, but I noticed occasionally it will be missed. So this is about detecting when onrep failed to fire on initial bunch and manually calling it
In beginplay
So kind of the opposite issue
But that's kinda what it's doing
Oh I see
Sure it will always go that path with this example, but it still solves the issue
Yes sorry
Your code snippet made it clearer what it's doing
Does this not mean though that it might be double-called?
What you wanted to do is only call in on BeginPlay if it didn't call at all.
While the above solve that and it calling too early
No, cause of the HasActorBegunPlay condition
No worries. Your solution is slightly different and has a slightly different effect fwiw
I'll try your way in my next branch
For full context, when a player joins a game their state is set to "just joined" and it displays a welcome widget on the screen. The state is initialised to "none" in the constructor. Hence why I need to ensure it's always onrep'd otherwise no welcome screen appears, but I don't want it double-called so it wastefully clears and redisplays the widget twice
But your way makes sense too without the manipulation of booleans
Thanks @thin stratus and @quasi tide , I just misunderstood the original suggestion π
in a listen server, how can i open a level without level streaming and load all the players into it?
or would i have to use sub levels
I recall a while ago there was whispers of new RPC types coming - or perhaps it was a PR I dont remember exactly but does anyone know what happened with that?
Such as multicasts for proxies for example
Here it was https://github.com/EpicGames/UnrealEngine/pull/11578, still open 
maybe data layers?
honestly just going to use level streaming
So I cant figure out for the life of me why my attach actor to component wont work with network emulation on
It works perfectly with low ping
but in high ping the object attaches, but its location is wildly off for no reason that I can find
Don't know what sort of attachment but why don't you do the attachment locally?
Only thing you replicate the is the object you are attaching
thats true
It might be that the attachment takes the info from the server.
When arrived at client since there is delay
The position wouldn't be the same
Kinda like running a line trace on every machine
You won't get the same result
but
If you attach to a socket or bone, there shouldn't be issue though?
unless I update the location manually if the other clients never knew about the attachment how would they know the location of the object?
actor component
Accessories?
Actor component don't have physical presence, they don't have transform
Static mesh comp perhaps?
yes sorry, thats what i meant
I could try attaching to a socket
ill let you know if that works
it is a staticmeshactor
Ye attaching to world position would give you different result most likely.
By the time the location is replicated the actor would be in different place.
The higher the ping the more apparent the distance is
What you can do is probably pick a point from the parent mesh and set the location relative to the point (sockets / bone) perhaps.
Or just relative to a component location
Has anyone tried to make multiplayer in VR? What online subsystem could you suggest for VR multiplayer over internet (not LAN)?
looks like setting the actors relative transform after the attach actor fixed the issue. I guess attach actor snap to target isnt good enough
hey all looking for some advice on net relevancy for my foliage actors like trees etc.. im wondering if i should make them always relevant so players in the distance can still see the actor being destroyed these foliage actors arnt replicating movement or anything just abit concerned about the network performance with this as i have a large amount of those actors
Consider value to the player vs the cost.
Is it likely the player will even notice this?
I was about to make a point that you'd probably hit GPU issues before network ones, but then I remembered that everything is Nanite anymore.
If I wanted to destroy foliage I definitely wouldn't replicate those actors directly either way.
wayyyyy too much for networking to deal with
I have a portal system taken from Lyra that works fine (replicated) when on the same level. But when a player (client) goes through the portal and it leads to another level, all other players (both client and server) is also teleported to the new level lol.** Anyone have any good tip on this or where i can learn about the topic?**
is there any function like FindCrowdedSpotInMap() π ?
if not how i can implement it?
my guess is to store the locations of all players in an array, and then look if the more locations with less difference in distance should be that spot
FVector FindMostCrowdedSpot(const TArray<AArmaCharacterBase*>& Players)
{
FVector MostCrowdedSpot = FVector::ZeroVector;
int32 MaxPlayerCount = 0;
for (const auto& Player : Players){
int32 PlayerCount = 0;
for (const auto& OtherPlayer : Players){
if (Player != OtherPlayer){
PlayerCount++;
}
}
if (PlayerCount > MaxPlayerCount){
MaxPlayerCount = PlayerCount;
MostCrowdedSpot = Player->GetActorLocation();
}
}
return MostCrowdedSpot;
}
void ADangerZone::TryNukeCrowdedArea()
{
if (!NuclearBombClass) { return; }
NotifyAllClients("Attention: Crowded area will be nuked in next 3 minutes...");
TArray<AArmaCharacterBase*> Players;
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
FTransform BomberTargetTransform;
FVector MostCrowdedSpot = FindMostCrowdedSpot(Players);
BomberTargetTransform.SetLocation(MostCrowdedSpot);
if (ADropNuclear* BomberTarget = GetWorld()->SpawnActor<ADropNuclear>(NuclearBombClass, BomberTargetTransform, SpawnParams)){
}
}
To those who have worked with AI, do you run logic in the pawn class of the AI as well? And if so, only from the AI Controller calls to make sure it's ran by the server right? I'm trying to understand what's the relationship between the pawn and ai controller, but as far as I've gotten to understand it, is that the AI Controller is the authority, besides setting the blackboard values for the behavior tree, it also tells the pawn and calls its functions right?
I'm saying this because I've tried putting logic in the pawn and have it ran by itself but apparently the pawn in the client's machine is owned by the client so there is no server/client relationship when it comes to solely to the pawn
Controller executes the AI
pawn is the body, controller is the brain
AI always runs on the Server only
curious on ppls opinions, is a dedicated server and save games enough for persistent storage of a player's data ? and if not, what are some simple options i can look into ? (hopefully dev friendly)
you can't store save games on a dedicated server no
you'll need some kind of persistent backend of your own, or use an existing service
i figured, i had an SQL database workign for a while and that was going to be my answer to the important data, but it doesn't scale well (at the least the way i was doing it). it wasn't really possible to load all the data at once, would cause crashes and other issues. might have also just been the particular plugin i was using to faciliate it
what are some semi user friendly exisiting services ?
i've heard of playfab, never looked into it, i think that's for this
not aware of any but I'm sure some exist
EOS might have it too. Try #epic-online-services
yea im actually using EOS and i do know they have something like it but i have heard it's not the most reliable, as in i think it still is subject to tampering
How can I create a mod for unreal engine 4 that adds a multiplayer game if the game is single-player?
You canβt. To get multiplayer working youβd pretty much need to redesign the entire code architecture. Ex: you cant use returns on online functions.
Unless you have access to the source code and want to essentially remake the game
Even bungie said they couldnt make halo 1 online multiplayer when xbox live released because they would have been essentially remaking the whole game β and they were the creators lol
hello, this DEF variable is giving me "0" value which is the default value. but at character begin play i m setting the DEF value appropriately which I confirmed by using print string. pls help
Print the Value on BeginPlay and in PointDamage and print the DisplayName of the Blueprint (self) in addition to check if you are really setting it correctly.
Also make sure this is called only on the Server (Point Damage).
i checked i used a print string after this function, its returning me "0" but if I printstring from a debugkey, its showing me appropriate value
PointDMG is server only
getting "0" in this print string
getting appropriate value in this print string
that's a rule?
nb 5
not even going to question how modding==piracy
Please print the name of the BP (self) alongside that.
There is a good chance you are printing the values of 2 different instances for whatever reason.
You mean mantling on top of obstacles?
How / when are you setting the value of DEF? Is the value being set on the server then replicated over the network to the client? If you set it on the client it won't be replicated upstream to the server.
Yes i m setting on the owning client
Why would that be problematic?
Right so that explains it
Especially if you use the CMC it should be fairly straight forward.
Replicated data only travels down from server to client never the other way around.
So I shud server->mc that?
No, the value is marked as replicated. You need to set it on the Server, that's it.
Don't need to multicast
Given the Actor itself is marked as replicated.
Let me try this. Thanks a lot
If you still have issue, please share the code that sets the DEF variable value.
Currently you only shared the part where you use it.
Yessssss
It workssas
Aaaaaaaa
@thin stratus & @graceful flame thank u so so much
Sry fr image quality, my ethernet is gone
This is where I was setting the value
Right okay. I would suggest you to learn a bit about inheritance, cause what you are doing there doesn't scale at all.
These different stats should be set in a Child Class (e.g. BP_Character_Lucy).
And then just in the default values and not in runtime code.
Yea just like weapons right?
Yeah, anything that sort of gets more specific down the tree.
Weapon -> Melee -> Sword1
Weapon -> Melee -> Sword2
Weapon -> Ranged -> Bow1
Weapon -> Ranged -> Crossbow1
Would u suggest that I fetch it from a savegameobj?
Character -> Lucy
Character -> Riot
Character -> XYZ
If those stats can change in the future then you'd at some point save and load them yes
I have a master bp for weapons, i have to create one for characters as well
The can totally be done during runtime, but for the actual base values, you'd just set them as default values in the different characters.
You usually do that for a lot of things.
Object Oriented Programming makes a lot of use of Inheritance
Doesn't always need to be one single master BP either
Like with the Weapons, some more specific code can live in a Melee and a Ranged child
From which then the more specific child class inherit
Most people have something like this:
- BP_Character
- BP_PlayerCharacter
- BP_PlayerCharacter_Lucy
- BP_EnemyCharacter
- BP_EnemyCharacter_Skeleton
- BP_PlayerCharacter
I actually am fetching the character mesh frm savegameobj. I have to rewrite that whole code to fetch from the child character bp?
To ensure that general Character stuff can live in BP_Character. And Player vs Enemy is split.
Can't really answer that. I don't see why the Character Mesh would live in a SaveGame tbh
Unless BP_PlayerCharacter_Lucy can have different Meshes for the same Lucy character.
Noob programming on my part in the very start, but theres a lot of code after that in the mainmenu apart from savegameobj
I will rewrite this. Thank u
Usually you code most of your game before adding the SaveGame stuff.
The SaveGame stuff should just be a minimal version of information to recreate the state of the game.
If your Character has any runtime data that changes, like health or so, that would go into it.
If the Mesh of the Character is set it stone due to it being BP_Character_Lucy, then that doens't need to go into the SaveGame.
What would go into the SaveGame is that the player is using BP_Character_Lucy in the form of the Class of the Blueprint.
So I should not save info in the savegameobj from a http get request from a server? But I also wrote a code to validate the values too
I mean, SaveGames are usually for.. saving the game.
This cleared my confusion
If you save the game into some backend server with some HTTP request, then that doesn't really change WHAT you are saving.
You'd still save the Health, and the BP Class
And the Stats
And the Armor that is equipped, etc.
Doesn't really matter if SaveGame or HTTP Request to a Database.
Combining HTTP Request and SaveGame can make sense if you want to support offline gaming and sync it with the backend later.
Not my aim
But that's then more about your save game stuff and not really about the original point of Inheritance anymore
So I shud make a new system for these stats by using a master bp, and different characters in its child. Am I right?
Yeah, just don't think about it as ONE Master BP.
You can branch off a bunch of times if you want to have specific grouping of code
E.g. Player vs Enemy
Melee vs Ranged (Weapon)
Pls i didnt understand this
You don't need to do this:
- BP_Character
- BP_Character_Lucy
- BP_Character_Riot
- BP_Character_XYZ
- BP_Character_Skeleton
You can (and often should) do this:
- BP_Character
- BP_PlayerCharacter
- BP_PlayerCharacter_Lucy
- BP_PlayerCharacter_Riot
- BP_PlayerCharacter_XYZ
- BP_EnemyCharacter
- BP_EnemyCharacter_Skeleton
- BP_PlayerCharacter
You don't have to instantly split it like this, but you should keep it in mind.
There might be code that is only relevant for Player Characters, and there might be code that is only relevant for Enemy Characters (AI code for example).
And if it makes any sense, you can add even more in-between classes.
Probably want to understand OOP before knees deep into your project
Thank u so much for explaining.
Rn, my code is this:
in mainmenu, in char selection, select char and save to savegameobj.
Ingame, fetch savegameobj and get the mesh, then set mesh
Yeah, I see, you are trying to persist the data between MainMenu and Gameplay map.
And that's also totally fine. Just the stuff in the SaveGame could just be the Character BP Class
And BP_PlayerCharacter_Lucy has the default values for the stats then.
And this helps the user to load the game and have their previously selected char to be currently selected
Yes, this is what i shud do
Yeah it can be used for that to
I have this system for the weapons though. Will make one for the characters
does the server have interpolation at all?
@thin stratus I'm unable to get the same result as compressed flags with move containers. They result in unrecoverable de-sync in rare cases. Do you have something like a basic sprint implementation that uses move containers instead of compressed flags? I feel like I must be missing something obvious
What's the context?
just moving side to side
The majority of my last year was Mover. I don't have anything at hand for CMC, sorry.
Unrecoverable de-sync sounds bad though, that shouldn't happen.
The Container should be the same as the Flags.
Old setup send the Flags via the ServerMove call. New setup send the container struct.
That's kinda all there is.
I'll keep looking
The Flags might be in the SavedMove of course, to replay moves, but I assume you added whatever booleans you set in the container for the input flags also to the SavedMove.
In theory if I replace the compressed flags with move containers nothing else should be required?
https://github.com/Vaei/PredictedMovement/blob/main/Source/PredictedMovement/Private/Sprint/SprintMovement.cpp
Are you having particular issue? Movement pretty much handled already and you shouldn't have jitter or snappy movement if everything is set right.
it just looks jittery on the listen server
and from what google tells me im not the only one noticing this
It would be exceptionally difficult to repro with sprint tho
I'm testing with a slow fall/levitate instead, and the de-sync happens in really rare cases, likely when one thinks its on ground, other doesn't
Something to do with the tick pose
Kaos settings help migitate the effect.
why the heck wouldnt the listen server have interpolation?
In theory you would need to:
- Put the Flags into the Container
- Add something that works like
USprintMovement::UpdateFromCompressedFlagsbut for the Container - Add something that works like
FSavedMove_Character_Sprint::GetCompressedFlagsbut for the new flags from the Container
The flags aren't that magical that they could break something and cause a de-sync, imo.
FSavedMove_Character_Sprint saves a boolean for FSavedMove_Character_Sprint::bWantsToSprint and sets the Flag in GetCompressedFlags if that boolean is true.
USprintMovement uses the Flags to set USprintMovement::bWantsToSprint.
CMC uses FSavedMove_Character::SetInitialPosition to set bJumpPressed instead of SetMoveFor. But it does use SetMoveFor for the Crouch stuff.
Not sure if your specific stuff there should do anything with ImportantMove or bForceNoCombine.
Main reason is that the Server doesn't tick the Pose of the SkeletalMesh on Tick, but rather with each received ServerMove RPC.
Reason for doing that, from Epic's side, is to keep the Animations in sync with Movement iirc.
Doesn't really help with the fact that it does indeed make Clients look laggy on the Server
so is there anything u can do?
i mean, its not the end of the world in custom games
but still
Kaos post .ini setting and it helps
Going dedicated solve this specific issue though
A few years ago the usual option was to inherit from CMC and Character in C++, override the parts in Character that set the ticking to manual back to automatic and remove the parts in the CMC that tick the pose manually.
But the CMC seems to have gotten more complex in that (who would have thought) and I'm not sure it's that straight forward anymore.
I'm pretty sure The Ascent shipped with that fix :D
i dunno i feel i will get some desync
how much does CMC handle anims/root motion anims ?
Puh, not so straight forward to explain.
It doesn't handle Animations. Only RootMotion and RootMotionSources.
And the RootMotion it usually grabs from AnimMontages that are currently playing.
RootMotionSources is something you mostly get into contact with when using GAS, but you can also use them outside of GAS (just Epic never exposed them).
If you play a Montage with RootMotion on Server and Client, then it will keep you in sync.
I mean, we are talking CMC and predicting usually.
So probably local + ServerRPC ? :D
I got a dummy question for y'all. Say I'm implementing a game like Rocket League where I have a ball that's being kicked around by a bunch of players, and I want the ball's movement to feel buttery-smooth on every one of my clients.
My impression is that if I just naively say "the server will tell you the position of the ball every step of the way" then inevitably the ball will be jittery as heck for everybody, my client could be running at 240fps but I may be only getting 30 transform updates per second for the ball, no good.
What's a practical solution for this in UE? How do developers go about making sure the bouncy ball being whacked around looks great for every player? My guess is that every client locally has to apply the same impluse on the ball and locally simulate its physics and trust the server to keep it honest at regular intervals, but... what does that actually look like in practice?
Replicated Physics movement of anything is extremely difficult.
Im not entirely familiar with Rocket League or how they manage it.
But I wouldnt be surprised if they did big modifications to the engine to setup some sort of deterministic physics across the network.
The easiest solution which will get you close but still look somewhat rough, would be to smooth between the network updates.
Sounds like there's nothing obvious off-the-shelf in UE that is magically plug and play and will give me this sort of functionality I'm looking for, right?
No
There's this talk from several years back which I need to revisit, but I was mostly digging around to see if perhaps since then something new showed up in the toolbox that solves it. IIRC Rocket League is on UE3.
In this 2018 GDC talk, Psyonix's Jared Cone takes viewers through an inside look at the specific game design decisions and implementation details that made the networked physics of Rocket League so successful.
Supposedly Chaos Physics is meant to be able to manage this type of thing in the future.
But its a long way off from my understanding.
from my (limited) research, there is no easy way to get replicated physics. you will always be fighting against server-authoritative network prediction with CMC/any other built-in movement system you're using. you'd have to create your own framework pretty much
Pubg doesn't even predict it.
The ball got kicked 1 second later
Iirc the dudes from rocket league made video and speech on how they do it
You may get the overview but it's not gonna be a simple steps
could he get something similar if he treated the ball as a projectile?
projectiles are syncd between everyone aren they?
BallCharacter 
hey guys, I notice that once my actor becomes irrelevant(IsNetRelevantFor returns false) it will be destroyed from a client with a delay. And delay seems to be bigger then my network latency. Is it so? Is there any way to control this delay? Thanks
The delay is on purpose. It is a buffer, this helps reduce the potential for the Actor to constantly be switching between being relevant and not, which would be expensive.
It cannot be changed.
At least not without modifying the engine.
I'm just using relevancy as one of my game mechanics for prototype, not sure if it's a good idea though π but I will give it a try
I would not rely on relevancy as a game mechanic.
You should setup your own soft form of mechanic that mimics its effects.
yea, I will do it later, don't want to waste time on it right now
One message removed from a suspended account.
This !HasAuthority() check will also avoid something to be executed on dedicated server or i have to check for if (GetNetMode() != NM_DedicatedServer) ?
my guess is that !HadAuthority is enough
but not sure
listen server players have authority over replicated actors
There's also FApp::CanEverRender I guess
but generally you just GetNetMode to determine if it is dedicated
Solved lots of confusions thanks
if you will NEVER have listen servers you can ignore this, but I recommend you keep listen servers working just for the sake of how useful it is to see authority things rendered
i will do
if (GetNetMode() != NM_DedicatedServer || !HasAuthority())
This. It's actually not as hard as people think to support both too
It's not but it does add a bit of an extra situation to consider in some larger manager things
but even if you can just keep like... the cmcs moving around etc it will still be useful to see what is happening
Yeah, if you can support both you defo should. There's no substitute sometimes for being able to actually see what's happening server side
im trying to make local multiplayer for a school project, when spawning my second player it doesnt have any controls :) any pointers?
also for some reason another copy of player controller 0 spawns (the one listed as my default pawn)
https://wizardcell.com/unreal/multiplayer-tips-and-tricks/#2-beware-of-getplayerxxx0-static-functions
(woops, they meant local!)
yeah so what i have going right now is that the Game mode spawns player 0 which works with controlls just fine but player 1 doesnt work at all with controlls
perhaps I have set up the controlls wrong? i copied and pasted the first player bp and changed the keybinds π
how would player 2 get the second player index controller when they only have one controller on their client
its local multiplayer, theyre the same client
ah, I'm a dingus and missed the "local" part
im only a first year im not doing all that π
i know unreal tries to do a lot for you when it comes to lmp but like, it would help a lot if i could just copy and paste the player 1 bp and change keybinds and call it a day
when you say it doesn't have any controls, you mean it's not taking input?
have you bind the inputs to the 2nd player?
how and when do you bind the input mapping context?
its not in that screenshot i just realise
give me 2 seconds ill open it back up
something i will add
is that the get controller call fails
i think this is because im in my level blueprint, and the level blueprint isnt direived from pawn
however im very much shooting in the dark there
can you show the whole bp? I can[t tell when this is executed
btw don['t use level blueprint
also you might be mapping it when the controller is not even spawned yet
dunnoe if that matter, since I never do local multiplayer my self
you probably want OnPosses -> Add Mapping Context
i just moved the mapping to the player blueprint
thoes are the two blueprints involved
i dont do C++ yet :( is this a blueprint node too?
yes, pertty much what you are doing for player 0
you should do for player 1
imo, I will just move the binding in the OnPosses event
its spawned by the game mode as its the default char
i'm just saying that you might have to bind the input for the player 1 too
imo, you can probably just bind on posses
so regardless which controller get spawned or you want to set.
everytime a controller posses a pawn, they will bind the input.
and i can just run that in their respective blueprints?
is OnPossess what the node is called? i cant find it π
it's an event that gets called when a controller posses a pawn
you probably want to make a function in your character to bind the input if you are using Input Action in the character.
then from the controller, when on possess is called, get controlled pawn -> cast to your character -> bind input
okay i understand, i will try now quickly
if not i will ask my teacher what the fuck to do
i was at this all night
yeah im still getting nothing from that player, something weird is that even when i make player 2 the default pawn and spawn it its not moving
so i wonder if its an imc problem?
not that theres anything here to go wrong
Show your codes
Is player 2 different bp?
Hi guys.
I faced issue with OnlineSessions.
I added Custom Settings with code like this :
IOnlineSubsystem* OnlineSubsystem = Online::GetSubsystem(GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull));
IOnlineSessionPtr Sessions = OnlineSubsystem->GetSessionInterface();
if (!Sessions.IsValid())
return false;
FOnlineSessionSettings* SessionSettings = Sessions->GetSessionSettings(NAME_GameSession);
if (SessionSettings)
{
SessionSettings->Set(InSettingKey, InSettingValue);
return Sessions->UpdateSession(NAME_GameSession, *SessionSettings, true);
}
return false;
After find sessions node in blueprints i call this :
if (!InSession.OnlineResult.IsValid())
return false;
return InSession.OnlineResult.Session.SessionSettings.Get(InSettingKey, OutSettingValue);
but SessionSettings.Settings are always empty.
I check with breakpoints and SearchObject in FindSessionsCallbackProxy just don't download them.
I use OnlineSubsystemNull and Lan sessions
.ini :
[OnlineSubsystem]
DefaultPlatformService=LAN
Sessions are downloaded successfully, but without my custom settings.
Any ideas?
try doing [OnlineSubsystem] DefaultPlatformService=Null cause I dont think "lan sessions" is a thing.. but i could be wrong
I tried, but this did't help
I've got this.
SessionSettings->Set(InSettingKey, InSettingValue);
should look like this :
SessionSettings->Set(InSettingKey, InSettingValue, EOnlineDataAdvertisementType::ViaOnlineService);
Hey guys, currently I'm doing a Capsule Trace in the GameplayAbility, to check for melee hits, and doing it only if HasAuthority is true.
But I want to move it, maybe into a AnimNotify, but then this would not be executed on the server and so I can't check for HasAuthority there.
What/How would or could I do there, what would be a good solution for that?
Are AnimNotifies not run on both dedicated and listen servers by default?
I'm not sure, I'm quite new to Multiplayer, I would have assumed that the Animation is not played on the server and hence the Notify is also not done on server.
But if they are executed on server and client this would be awesome!
It should be playing for the sake of notifies at least. There is also an option to disable the notify trigger on dedicated servers (which is enabled by default)
What server should be missing is actually updating the bone locations for the mesh according to animation since it's not being rendered, which is the case for dedicated server only, since a listen server would still render the scene
And often times we did enabled the bone location update on server too. On FPS projects, disabled bone update causes the player mesh to stay in T pose for server, which makes it not consistent between server and client to shoot that player for example
So your animation timeline and events (Montage start/end/blend and notifies) should still run on any kind of server by default
Wow ok thats amazing, so I could probably just check for authority in the notify and then do the capsule trace right?
Also the info regarding the bones is also really good to know, maybe at the moment I don't need it but when time comes its really good to know.
Yes. AnimNotify itself might not have the auth check node/function since it's a UObject based type but you can get the owning mesh component and it's owner actor to check if you're on server or not
ohhh i see and then since the animation is also played on the server, it will check there.
It was a painful process for us to figure out why a seemingly valid trace on client was not hitting the character on the server and a simple dropdown option on the SKM component was the fix back in the days. So I try to add this bit of information every time, even if it's not relevant to the actual question
But the only downside regarding this, if a client hits, and he is delayed or something, and on server the characters are already positioned different, the client would see a hit but it wont register
but i guess this is not to bad and no realy way around that right?
Well yes, this is a whole different topic about prediction and rollback, which I'm also not so much experienced with
you can design it how ever you want
the easiest one is obviously just to accept that client did a hit
Yea I wonder how complicated it is and if it's worth getting into that or maybe just if it hits problems.
You mean do it client sided and send a event to the server right?
yeah you can do that
next level from that is some server validation
It's just if someone is cheating bad right?
server chekc if the hit is possible or not
then you want to step up your game
but if cheating is not a concer, there's the path of least resistance
The server validation can be as simple as, checking if there's anything blocking the trace, or if it's close enough.
the other one would be to save Character's hit box every frame
doing some rewinding on the server to see if the hit is possible or valid
so basically just a way of checking if the hit that the client said it did is not to far of right?
how you want to do it is up to you
who has the say and so on.
Yup it all depends on the needs, every solution has it's own pros and cons concerning development time, cpu usage, cheat protection etc.
yea thats true
I'll maybe try something out like the client solution or doing it just server sided, maybe wit ha capsule trace, there ight not even be such a big issue even for some ping difference
It could be enough if it's not a fast paced competitive fps game or a personal/learning project
You can always upgrade/refactor the logic when you want/are required to step up your game as ColdSummer said
Yea, I mean if there will be some cheating, the ofc some more logic has to be implemented, but idk.
i mean in lyra the melee hits are only done with authority.
But having a complex system like ColdSummer mentioned, might be safe solution but on the other hand it probably takes quite some time to do and then to get right as well.
but thank you guys a lot for the help and info π
Can anyone help me figure out why my listen server seemingly is not properly working?
I create a session and then call GetWorld()->ServerTravel("/Game/Maps/MyMap?listen")
This works so far and the ListenServer loads into the map
But when I now try to find the session and connect with a client, it joins the session successfully, but the ClientTravel fails. The connection times out and it never successfully connects to the listenserver
I use GetResolvedConnectString() to get the address to connect to, and it returns an IP that has :0 at the end, so port 0. I guess this is the issue?
I should add im using OnlineSubSystemNull, and trying to do it in LAN
Are you testing on PIE?
so i've successfully setup possession of a pawn and have some controls for it and what not, and im trying to think of best way to go back to original pawn
i have a widget that spawns and possesses the second pawn, this changes the widget to essentially view the pawn via a render target. you can't move , just look around, and do whatever else, but im not certain on best method of going back to original pawn
i found that best way to spawn and possess was doing it via game mode but i dont necessarily want to store the additional pawn on the game mode, as i could see this getting messier than it needs to, by storing an array of pawns / actors to keep track of, but im not sure how else i'd get reference to the controlled pawn as it was never stored as a ref anywhere. not sure if the game mode woul djust be the best place for that, but yea any thoughts would be cool
No, I'm testing packaged builds.
So I got it to work, but not sure why:
Instead of using GetWorld()->ServerTravel(...) to open the level on the ListenServer, I use UGameplayStatics:OpenLevel(...), and now it works
Oh I guess if it was causing a problem it would not give you any sessions after find session to begin with
Yeah
If you have any insight on why GetWorld()->ServerTravel(...) wouldnt work I'd love to hear it, the Tutorial I was following used it and it worked fine for them π
Hmm I feel like I remember a conversation about this
I don't have any official statement or explanation to quote but it seems like ServerTravel doesn't change the NetMode for the target world(?)
I am also currently using GEngine->Browse to open the listen server and then ServerTravel to take players from menu to game level
Hm, that's a good guess for sure, thanks for the help!
I'm just happy that it works for now haha
update: i just stored the new pawn on the controller do the work in the game mode again by sending it to the game mode then calling unpossess event in new pawn from game mode, that works
Hey all. I need some tips for multiplayer spawning. I am experimenting with a procedural level generator and even if I weren't, I would like to learn the proper way to handle spawning in multiplayer if there is a best practice beside letting the GameMode manage it automatically.
A lot of times you can just pass the seed you use for generation to the connections that need it, have them generate itself and use stably named actors. I think thereβs a blog post about around here somewhere
Rad. Thanks.
Now to read this and translate to BP
Some stuff wonβt be possible without C++ (like forcing actors to be stably named).
Guess I'll have to do some C++ classes then.
Side-note. I'm trying to test some stuff in multiplayer now but my server and client are not together. I have it set to play in New Editor Window (PIE), Number of players is 2 and Net Mode is "Listen Server" but when I hit play, they do not spawn into the same map together.
I do have startup movies enabled and in my Maps and Modes I've set the defaults to the current map I'm testing instead of my title screen. Not sure if either of those things makes a difference to what's going on in my editor.
enable replicated on character
The Player Character is replicated of course.
if you are playing as listen server with two number of clients, one will be server and second will be your client
so server and player should both see each other, at least server will see the client in any case
else you are in standalone mode
check it again
I just did. The player character is replicated and I am in PIE not standalone. It loads the same map but the players do not appear to be together or see each other. It's very strange as I have tested everything before and this wasn't happening.
you have a different server map in your maps/mods ?
I don't have a server map in there. I was under the impression that was for dedicated servers so I left it blank.
print something when you press 1 key on a multicast event and check what you will see
Update: I changed that. Now itβs stored in the original character, so that if dies it knows youβre controlling the other pawn and will switch back so you no longer control pawn.
Any controller related events on char I had to opt out of if the controller is controlling a separate pawn , so again ref on chat helped w this just checking if valid. All other events stay as they seem to work fine
The print strings only occur on the individual instances of the game. It prints Server: Hello on the server and then just Hello on the Client but doesn't print Client: Hello on the server or Server: Hello on the client.
Ahem, sorry, ignore that @, Cedric
I was actually 99.9% of the way there
I wonder if you want the CanCombineWith code oyu commented out
iirc the parent does that via the Flags != other.Flags
At the same time you don't want to have the CombineWith stuff do anything with bWantsToSprint
This is an important move after all
You only combine if the result of the two moves together is the same as if they are done one by one
But if you start sprinting in one but not the other, then you can't combine them
@grand kestrel
@thin stratus I think you're right, they shouldn't be combined
Move Containers vs Compressed Flags
Where we use GetCompressedFlags(), we now use FCharacterNetworkMoveData::ClientFillNetworkMoveData()
This is where the client packs the inputs (e.g. bWantsToSprint) for sending to the server, and there is a matching required Serialize() function as well.
Where we use UpdateFromCompressedFlags(), we now use UCharacterMovementComponent::ServerMove_PerformMovement() (Super should occur after your code!)
This is where the server unpacks the inputs that was sent from the client
So long as you replace these two functions, the remainder of the predicted movement code can be identical to using compressed flags!
You can do more, like having the server send the client data by using FCharacterMoveResponseDataContainer::ServerFillResponseData() and implementing the matching Serialize(), and the client receives this in UCharacterMovementComponent::ClientHandleMoveResponse()
You can further use UCharacterMovementComponent::ServerCheckClientError() to compare the difference between server and client and force a net correction by returning true if it differs -- I do this for Snares which can be applied externally! Then you can handle the correction on the client in UCharacterMovementComponent::ServerMoveHandleClientError()
@thin stratus that is my understanding thus far
Hm yeah. Not sure about the ServerMove part
iirc the Server will set the Current NetworkMoveData 3 times or so.
Based on getting an old move, the current one or something else
can't recall
I think there might be a different spot, earlier to PerformMovement, where you could unpack it
But maybe it's fine
Would need to look at it again. I only have Mover in my head atm
@grand kestrel
// CallServerMovePacked β ClientFillNetworkMoveData β ServerMovePacked_ClientSend (client sends to server) β
// ServerMovePacked_ServerReceive β ServerMove_HandleMoveData β ServerMove_PerformMovement β
// MoveAutonomous (UpdateFromCompressedFlags)
Basically it leads into MoveAutonomous which immediately calls UpdateFromCompressedFlags()
Which means if you do it before calling Super::ServerMove_PerformMovement(), you're doing it one step before UpdateFromCompressedFlags()
i hate how much unreal does for you
i cant make a 1 keyboard 2 player game its nearly impossible
because they handle allll the imput for you
i cant just add a camera and 2 players with programmed inputs becuase of that fucking input system
Is that just some random actor?
It will be pretty difficult to get actual physics working in Multiplayer fwiw.
Even if you get the events sorted, there is no proper prediction, reconcialiation and lag compensation. Especially not in Blueprints.
But that's besides the point and just the usual copy paste to warn people about Multiplayer + Physics.
Back in the day there were Facebook Groups I guess. Maybe there is something on Reddit.
Size-wise you can probably only really find this and the Forums
There is an Indie Server officially by Epic fwiw, but I doubt it really gives you more in terms of help
of course you can
I mean, in general multiplayer terms you would want to call the impulse locally and then a server RPC with the same value
And the cube has to be owned by the client to allow server and client rpcs
Other than that not a lot can go wrong
Actor replicated and movement replication I gues
If you just want a throwable object with some bounciness you might be better off using an actor with a projectile movement component. That's how I usually fake throwable physic actors like balls
Works quite fine and comes with a bit of smoothing
Player numbers is not replicated.
So why is my "Run On Server" event updating a local variable thats on the client, and not the server?
I expect to update the varaible on the server, then send that to the owning client which takes the updated variable and uses it.
"No i cant use a replicated "player numbers" variable for this." π
I just dont get why, when i call this event from the client, it uses the clients variable on server, and not the server variable.
Can someone explain?
Is CameraActor itself a Replicated Actor?
Is it owned by a PlayerController?
Its not a replicated actor
Then it cannot send RPCs
If its not owned by a PlayerController then it cannot send an RPC to the Server.
But when i do this, the host does show a print string, and the client does show a print string on th owning client event as well.
Well then CheckPlayers is being called by both of them.
Left host, right client.
Yellowish string is the run on server event.
Purple is the owning client event.
To me this looks like rpc is working?
If a actor is not replicated, does the local player not automatically "own" it?
No
Depends on what its Owner is.
Which is determined by how you spawn it.
It would be helpful to see all of the calls to CheckPlayers and the implementation of RetrievePlayers as well.
Ok give me a sec
If asking for help, its important to provide as much context as possible.
And thanks guys
Otherwise we just waste time playing 20 questions
I understand, but know how much context is needed is difficult when experience on the subject is limited on my end π
Ok so im doing this from my default pawn called CameraActor.
Which is apparently replicated, i was unaware. (woopsy)
I have these events in it that i call on left mouse click.
I expect the server to add 1 to player numbers and send that back to the client.
Dont know what context should be needed more