#multiplayer

1 messages Β· Page 231 of 1

wicked whale
#

oh no, that's not what I meant. my RPC just sends a float or perhaps a vector, depending on how I do it. I'm just trying to reduce the amount of RPCs to send it

thin stratus
#

Then you'll need to limit it with your own timer, yes

lethal wraith
#

Hey guys. I was doing some code and I was wondering. Is it alright to call 2 different server RPCs inside a function?

bright summit
#

Yes you can

dry pebble
#

thanks guys! Did you end up writing a tutorial on that or nah? I was never able to get to it

thin stratus
#

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.

dry pebble
limber gyro
#

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

fiery wadi
#

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.

limber gyro
#

u need to get the anim instance

fiery wadi
#

Ahhh ok thanks! πŸ™‚

#

Hmm i cant seem to plug the anim instance into the montage node.

haughty ingot
# fiery wadi Hi, I am wondering how you would go about doing server functions within the cont...

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/

fiery wadi
#

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. πŸ™‚

haughty ingot
#

It exists on the server and the connection that owns it

fiery wadi
#

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 πŸ™‚

limber gyro
fiery wadi
#

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 ?

dark parcel
#

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.

fiery wadi
#

Ahh so a multicast will never work on a player controller because it is not the server right?

limber gyro
#

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

dark parcel
limber gyro
#

if u want montage animations to play on every character they should be called inside a character

dark parcel
#

12 times , practice, fail then repeat.

limber gyro
#

since those exist in every other client

fiery wadi
#

So how do i send an Input Enhanced Event from a Controller to a Pawn to then play a montage and spawn something ?

limber gyro
#

u just call the rpc chain on the character

#

rpc to server -> multicast to clients

fiery wadi
#

but the controller still needs a reference to the character to be able to call the RPC even inside the Charatcer yet ?

limber gyro
#

ur not gonna call the rpc inside the controller

dark parcel
#

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.

fiery wadi
#

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.

dark parcel
#

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.

fiery wadi
#

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 πŸ™‚

dark parcel
#

wizardcell and exi's compedium

fiery wadi
#

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. πŸ™‚

vapid gazelle
#

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?

haughty ingot
#

It is

dark parcel
# haughty ingot It is

Did you manage to get it working? Setting the vissibility on server only does it for it self to me.

haughty ingot
#

I can’t remember off the top of my head but I believe I only applies to the root component

dark parcel
#

Ok nvm it is replicated

#

i didn't tick component replicate on the component πŸ€¦β€β™‚οΈ

vapid gazelle
#

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?

limber gyro
fiery wadi
#

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.

fossil spoke
#

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

vapid gazelle
#

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?

fossil spoke
#

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

vapid gazelle
#

Roger. bHiddenInGame is at the actor level, bVisible is for scenes within the Actor, if I recall correctly?

limber gyro
#

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

dark parcel
#

Look at the call stacks?

#

run on debug

limber gyro
#

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

fossil spoke
# limber gyro

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

limber gyro
fossil spoke
#

Well if the PC is gone when the AsyncTask executes, then thats a problem isnt it

limber gyro
#

well but it shouldnt execute if it doesnt exist

#

am i missing something?

fossil spoke
#

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

limber gyro
#

so it can exist in a thread and not in another?

#

you can probably tell that i never coded with threads

fossil spoke
#

Also not sure why you are even passing this into the lambda

#

Your not using it

lethal wraith
# thin stratus Sure but depends on why

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

limber gyro
#

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.

fossil spoke
#

TWeakObjectPtr<APlayerController> WeakPC(PlayerController);

#

In the same way I posted above

#

With this

limber gyro
#

IsValid doesnt like weakPointers

fossil spoke
#

You have to convert it into a strong pointer

#

if (UPGAsyncAction_ListenForGameplayEventMessage* StrongThis = WeakThis.Get())

#

So basically going back to a raw APlayerController*

limber gyro
#

first time in my life im hearing about strong pointers

#

so strong pointers are just the defautl ones?

fossil spoke
#

Not necessarily. Typically it just indicates that they will hold onto the resource.

limber gyro
#

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?

fossil spoke
#

Weak meaning, it wont stop the resource from being removed

fossil spoke
#

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

limber gyro
#

does this look alright to you?

fossil spoke
#

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.

limber gyro
fossil spoke
#

This is just an exercise in better practice.

#

It could fix it 🀷

limber gyro
#

can we do an exercice in fixing the crash? πŸ˜‚

fossil spoke
#

But lets cross that bridge when we get to it

limber gyro
#

im gonna try this and see if it works

thin stratus
#

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

lethal wraith
#

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));
    }
}```
lethal wraith
thin stratus
#

Which removes the need for the client RPC

limber gyro
#

@fossil spoke i tried a bunch of times and its not crashing

limber gyro
#

im still not 100% sure

#

thanks for the help tho

#

hopefully its fixed and im just paranoid

lethal wraith
fossil spoke
#

But its what stands out given the code you were originally using.

lethal wraith
#

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?

fossil spoke
#

When working with Lambdas and any latent/async actions, its much better/safer practice to pass WeakPtrs into them

limber gyro
fossil spoke
#

You will have a much easier time doing all of this if you use that instead.

#

Just my opinion.

limber gyro
#

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

fossil spoke
#

Yeah, you would be unable to get it properly working for 26

#

Its way out of support now for that version

vapid gazelle
#

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();
    }
}
fossil spoke
vapid gazelle
#

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.

fossil spoke
vapid gazelle
violet walrus
#

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

dark parcel
#

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

violet walrus
#

Yeah, only host has a save. My question was "how would you handle it when host tries to load from that save"

dark parcel
#

Or just the host

violet walrus
#

Like "reload previous checkpoint"

dark parcel
#

The save file should contain all the data you need to reproduce the same state.

violet walrus
#

Yeah, minus the part after you saved

#

But you can't simply re-open same level in MP, can you?

#

What happens to clients?

dark parcel
#

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.

fossil spoke
#

@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.

dark parcel
#

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?

fossil spoke
#

Calling ServerTravel just causes the Server to switch levels, it has nothing to do with a hard or seamless travel.

violet walrus
#

So can I just reload same level to reset state just like in Singleplayer?

#

(Using ServerTravel)

fossil spoke
#

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

violet walrus
#

So can it reset the world just like re-opening same map?

fossil spoke
#

Every Actor has Reset called on it

violet walrus
#

Never used it

fossil spoke
#

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

violet walrus
#

So it's manual implementation

fossil spoke
#

But those issues might be fixed

fossil spoke
violet walrus
#

Not like calling AGameModeBase::ResetLevel does a lot. It just same thing as I'd implemted similar interface and called reset on each actor

fossil spoke
#

Instead of doing a full level transition

#

It is very manual yes.

pseudo wagon
#

On mobile, does game receive reliable RPC when app is background?

fossil spoke
#

Since im not sure what state the App is in when its in background mode for Mobile.

violet walrus
fossil spoke
pseudo wagon
fossil spoke
#

Good luck 😦

#

lol

dark parcel
violet walrus
#

UE + Mobile + MP

fossil spoke
#

Yeah pretty much

#

Thats like the worst use case

#

Maybe tack on 2D as well

#

Just to be sure

#

lol

dark parcel
#

I feel bad for people doing 2D in unreal and pixel streaming

#

at least epic nuked the web support

#

while the other just abbandoned.

pseudo wagon
#

Oh no, the project I am working on is multiplayer rouge-like mobile game. crying

dark parcel
#

how does match making even work for mobile

pseudo wagon
dark parcel
#

As long you have someone to share the pain, it can be fun lurkin

pseudo wagon
#

Nah, my team mate prefer use dirty instead of fix from root cause, that make me in pain.

dark parcel
#

πŸ˜”

unkempt tiger
#

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 πŸ€”

odd hamlet
#

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
karmic briar
#

Rep notify?

nova wasp
#

you have not shown that

odd hamlet
odd hamlet
nova wasp
#

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...

odd hamlet
#

I am prettty sure i ain`t using hot reload

odd hamlet
nova wasp
#

do not use that button to compile any header changes

#

it will break your project in subtle ways

odd hamlet
pseudo wagon
odd hamlet
#

wtf?

#

close it and open again?

nova wasp
#

run + build from an IDE

odd hamlet
nova wasp
#

no, clicking on the project is also wrong as that will use the latest development editor binary by default without changing it

odd hamlet
#

what clicking on the project bro

dark parcel
stuck hare
#

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?

dark parcel
#

are you gonna have players hosting the server them self (listen server)

#

or you want to deploy your own dedicated servers

stuck hare
#

I'd like the least complicated option to setup
From what I could gather that seems to be listen server?

dark parcel
#

well dedicated gonna cost you money.

stuck hare
#

yeah no this is just a super simple sample project I'm doing in my free time

dark parcel
#

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.

exotic wasp
#

dedicated servers don't have to cost money. they can still be hosted by someone normally from their own machine

stuck hare
exotic wasp
#

listen is by far the most convenient for players

dark parcel
stuck hare
#

Cool, is there a specific tutorial you would recommend?

dark parcel
#

there are tutorials out there

#

you just have to pick one and hope it work I guess

lament flax
#

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

thin stratus
#

@lament flax Idk, that whole idea sounds flawed. Physics in Multiplayer. Multiple players interacting with it.

#

This is correction heaven

lament flax
#

or, without considering heavy lag, is the idea still flawed ?

#

does physics have no correction ?

vapid gazelle
#

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"),
};
lament flax
crisp shard
#

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

dark edge
#

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

crisp shard
# dark edge just possess it

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

dark edge
crisp shard
# dark edge assuming your system doesn't depend on the character being currently possessed b...

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

dark edge
#

if a car you drove got destroyed on the other side of the city, who cares

crisp shard
#

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

dark edge
#

if it's Cyberpunk you'd die

crisp shard
#

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

dark edge
#

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

crisp shard
#

very dope indeed, i like it. going to give some things a try and report back in a few days w findings

vapid gazelle
#

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?

quasi tide
#

GameMode spawns the player. HandleStartingNewPlayer or something like that.

vapid gazelle
thin stratus
#

@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.

vapid gazelle
#

That's very helpful, thank you πŸ™

lament flax
#

so i didnt thought it would be an issue

thin stratus
#

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.

limber gyro
#

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

thin stratus
#

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

vapid gazelle
#
  1. 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

  1. 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?

  2. 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?

thin stratus
# vapid gazelle 1. Generally speaking, how many times can I expect an OnRep function to be calle...
  1. 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.

  2. 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.

  3. 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

stuck hare
#

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?

vapid gazelle
vapid gazelle
thin stratus
#

Yeah, knowing all of that and taking care of it is basically the next level :P

#

You never stop learning after all

limber gyro
#

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

limber gyro
#

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?

fossil spoke
limber gyro
#

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

fossil spoke
#

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.

limber gyro
#

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?

dark edge
#

dedicated servers are

limber gyro
#

so dedicated servers make that much of a diference?

quasi tide
#

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

graceful flame
#

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?

nova wasp
#

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

graceful flame
#

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.

nova wasp
#

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

limber gyro
nova wasp
#

a lot... πŸ˜…

limber gyro
#

out of the box that is

nova wasp
#

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

limber gyro
nova wasp
#

yes but it should be visible in Acharacter NetworkSmoothingMode

limber gyro
#

i think i might be looking for this

nova wasp
#

what that means is that if you have two positional updates more than 384 cms apart

#

it should never smooth between them

limber gyro
#

ye exactly

#

cms?

#

isnt it unreal units?

nova wasp
#

generally it can be assumed to be in unreal units

#

from 2 seconds of reading the source it is indeed just unreal units

limber gyro
#

for reference with my character

nova wasp
#
        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();
        }
limber gyro
#

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?

nova wasp
#

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

nocturne quail
#

why an object is auto destroyed on client when scaling in a NetMulticast event?

nova wasp
#

like setting the transform scale?

nocturne quail
#

yeah

nova wasp
#

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

nocturne quail
#

yeah is is replicated and i am scaling it using timeline

nocturne quail
nocturne quail
#

scale is applied in the progress function of timeline

nova wasp
#

looks okay to me... override OnEndPlay and breakpoint it

silent valley
#

Setting visibility to false on the server ends up destroying the actor on clients. IIRC it's the same for a scale of 0.

nova wasp
#

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

exotic wasp
#

setting visibility to false disables replication right?

lament flax
#

I don't see why it would

#

Visibility isn't replicated iirc

dark parcel
#

you just have to tick component to replicate

#

actually not sure about Actor vissibility, was thingking of component's

thin stratus
#

@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.

nocturne quail
thin stratus
#
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?

thin stratus
nocturne quail
thin stratus
#

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);
nocturne quail
#

later it is handled

thin stratus
#

Ah in StartShrink

nocturne quail
#

yeah

StartScale = BlueZoneSphere->GetComponentScale();
FinalScale = FVector(NewFinalDiameter, NewFinalDiameter, BlueZoneSphere->GetComponentScale().Z);
#

on server it works perfectly

thin stratus
#

You wrote the Actor gets destroyed. Is it also destroyed on the Server?

nocturne quail
#

on client it get destroyed on second phase

nocturne quail
thin stratus
thin stratus
nocturne quail
thin stratus
#

Doesn't answer my question.

#

What is its default value?

nocturne quail
#

int32

thin stratus
#

That's the type

nocturne quail
#

default is 0

thin stratus
#

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

nocturne quail
#

yeah its fine

#

tested with default val -1

#

still destroying

thin stratus
#

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

nocturne quail
#

i changed it wo strict test later CurrentActivePhase == 7 return

#

so it never reach outof bounds

thin stratus
#

I can only comment on the code your shared

#

And there it's wrong

#

But the EndPlay breakpoint will tell you more

nocturne quail
thin stratus
#

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

nocturne quail
#

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

thin stratus
#

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.

nocturne quail
thin stratus
# nocturne quail

Yeah so it gets destroyed due to something related to replication.

nova wasp
#

surely not relevancy, right?

thin stratus
#

DistanceBased Relevancy could be it given the randomized location of the actor @nocturne quail @nova wasp

#

Make sure to mark the Actor as AlwaysRelevant

nocturne quail
dark parcel
nocturne quail
#

U can generate it in like 10 minutes

dark parcel
#

im interested in your arma mod

nocturne quail
nocturne quail
#

seems very smooth now

dark parcel
#

If you are wat about late joiners

nocturne quail
dark parcel
#

You probably want to make them always relevant too

#

But that will come with draw back for large map I guess.

nocturne quail
#

I collect 300 of them in the lobby, and put them in Titanic Ship and land them in a different zone πŸ˜„

dark parcel
#

battle royal?

nocturne quail
#

then all run away and find loot

nocturne quail
lament flax
#

is there a "simple" way to have more CompressedFlags in the CMC saved move ?

opal pulsar
#

cant you just inherit the saved move struct and put your own stuff ontop

lament flax
opal pulsar
#

so add another int for more flags and correctly ensure they are serialized

odd iron
#

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

little pumice
odd iron
little pumice
#

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 deadge

lament flax
#

I still dont know how Fortnite broadcasted LIVE a show from time squares

#

Its was sadly a bit low res

odd iron
#

@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

lament flax
#

i got no clue sorry

thin stratus
#

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

odd iron
#

@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.

hybrid zodiac
#

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?

thin stratus
#

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)

hybrid zodiac
#

@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)

quasi tide
#

Why did you go that route rather than the route Cedric said?

#

It is practically a built-in version of what you're doing.

hybrid zodiac
#

@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

thin stratus
#

But HasActorBegunPlay is handling the edge case

quasi tide
#

I know the situation, but my question is - why did you decide to make a seemingly redundant boolean

thin stratus
#

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.

hybrid zodiac
#

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

thin stratus
#

But that's kinda what it's doing

hybrid zodiac
#

Oh I see

thin stratus
#

Sure it will always go that path with this example, but it still solves the issue

hybrid zodiac
#

Yes sorry

#

Your code snippet made it clearer what it's doing

#

Does this not mean though that it might be double-called?

thin stratus
#

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

hybrid zodiac
#

Yeah OK I see

#

Sorry, I misunderstood your original suggestion

thin stratus
#

No worries. Your solution is slightly different and has a slightly different effect fwiw

hybrid zodiac
#

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 πŸ™‚

errant charm
#

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

modest crater
#

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

errant charm
#

honestly just going to use level streaming

quiet yarrow
#

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

dark parcel
#

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

quiet yarrow
#

thats true

dark parcel
#

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

quiet yarrow
#

but

dark parcel
#

If you attach to a socket or bone, there shouldn't be issue though?

quiet yarrow
#

unless I update the location manually if the other clients never knew about the attachment how would they know the location of the object?

dark parcel
#

What sorts of attachment is it

#

A weapon?

quiet yarrow
#

actor component

dark parcel
#

Accessories?

quiet yarrow
#

its just a battery

#

purely visual

dark parcel
#

Actor component don't have physical presence, they don't have transform

#

Static mesh comp perhaps?

quiet yarrow
#

yes sorry, thats what i meant

#

I could try attaching to a socket

#

ill let you know if that works

#

it is a staticmeshactor

dark parcel
#

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

warm roost
#

Has anyone tried to make multiplayer in VR? What online subsystem could you suggest for VR multiplayer over internet (not LAN)?

quiet yarrow
sonic obsidian
#

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

hoary spear
#

Consider value to the player vs the cost.

#

Is it likely the player will even notice this?

kindred widget
#

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.

chrome bay
#

If I wanted to destroy foliage I definitely wouldn't replicate those actors directly either way.

#

wayyyyy too much for networking to deal with

weak plover
#

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?**

nocturne quail
#

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)){

    }
}
blazing bear
#

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

chrome bay
#

Controller executes the AI

#

pawn is the body, controller is the brain

#

AI always runs on the Server only

blazing bear
#

gotcha, makes perfect sense.

#

thanks

crisp shard
#

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)

chrome bay
#

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

crisp shard
#

what are some semi user friendly exisiting services ?

#

i've heard of playfab, never looked into it, i think that's for this

chrome bay
#

not aware of any but I'm sure some exist

crisp shard
twin juniper
#

How can I create a mod for unreal engine 4 that adds a multiplayer game if the game is single-player?

keen adder
#

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

lost inlet
#

Also #rules since I assume this is unauthorised modding

sharp hamlet
#

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

thin stratus
#

Also make sure this is called only on the Server (Point Damage).

sharp hamlet
sharp hamlet
#

getting "0" in this print string

#

getting appropriate value in this print string

lament flax
#

oh damn, mantling sounds awful to manage for decent networking

#

same for rootmotion

lament flax
#

nb 5

exotic wasp
#

not even going to question how modding==piracy

thin stratus
#

There is a good chance you are printing the values of 2 different instances for whatever reason.

thin stratus
lament flax
#

yeah stuff like that

#

rootmotion stuff

graceful flame
# sharp hamlet getting "0" in this print string

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.

sharp hamlet
thin stratus
graceful flame
#

Right so that explains it

thin stratus
#

Especially if you use the CMC it should be fairly straight forward.

graceful flame
sharp hamlet
#

So I shud server->mc that?

thin stratus
#

No, the value is marked as replicated. You need to set it on the Server, that's it.

graceful flame
#

Don't need to multicast

thin stratus
#

Given the Actor itself is marked as replicated.

sharp hamlet
#

Let me try this. Thanks a lot

thin stratus
#

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.

sharp hamlet
#

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

thin stratus
#

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.

sharp hamlet
#

Yea just like weapons right?

thin stratus
#

Yeah, anything that sort of gets more specific down the tree.

#

Weapon -> Melee -> Sword1
Weapon -> Melee -> Sword2
Weapon -> Ranged -> Bow1
Weapon -> Ranged -> Crossbow1

sharp hamlet
#

Would u suggest that I fetch it from a savegameobj?

thin stratus
#

Character -> Lucy
Character -> Riot
Character -> XYZ

thin stratus
sharp hamlet
#

I have a master bp for weapons, i have to create one for characters as well

thin stratus
#

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.

thin stratus
#

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
sharp hamlet
#

I actually am fetching the character mesh frm savegameobj. I have to rewrite that whole code to fetch from the child character bp?

thin stratus
#

To ensure that general Character stuff can live in BP_Character. And Player vs Enemy is split.

thin stratus
#

Unless BP_PlayerCharacter_Lucy can have different Meshes for the same Lucy character.

sharp hamlet
#

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

thin stratus
#

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.

sharp hamlet
#

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

thin stratus
#

I mean, SaveGames are usually for.. saving the game.

thin stratus
#

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.

thin stratus
#

But that's then more about your save game stuff and not really about the original point of Inheritance anymore

sharp hamlet
#

So I shud make a new system for these stats by using a master bp, and different characters in its child. Am I right?

thin stratus
#

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)

thin stratus
#

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

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.

dark parcel
#

Probably want to understand OOP before knees deep into your project

sharp hamlet
#

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

thin stratus
#

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.

sharp hamlet
sharp hamlet
thin stratus
#

Yeah it can be used for that to

sharp hamlet
limber gyro
#

does the server have interpolation at all?

grand kestrel
#

@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

dark parcel
limber gyro
#

just moving side to side

thin stratus
#

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.

grand kestrel
#

I'll keep looking

thin stratus
#

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.

grand kestrel
dark parcel
limber gyro
#

it just looks jittery on the listen server

#

and from what google tells me im not the only one noticing this

grand kestrel
#

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

dark parcel
#

Something to do with the tick pose

limber gyro
dark parcel
#

Kaos settings help migitate the effect.

limber gyro
#

why the heck wouldnt the listen server have interpolation?

thin stratus
#

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.

thin stratus
#

Doesn't really help with the fact that it does indeed make Clients look laggy on the Server

limber gyro
#

so is there anything u can do?

#

i mean, its not the end of the world in custom games

#

but still

dark parcel
#

Kaos post .ini setting and it helps

#

Going dedicated solve this specific issue though

thin stratus
#

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

lament flax
#

how much does CMC handle anims/root motion anims ?

thin stratus
#

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.

lament flax
#

okay, so i need to play them on both

#

multicast incoming

thin stratus
#

So probably local + ServerRPC ? :D

lament flax
#

yeah ill do that

#

thanks for the headsup

vapid gazelle
#

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?

fossil spoke
#

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.

vapid gazelle
vapid gazelle
#

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.

https://www.youtube.com/watch?v=ueEmiDM94IE

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.

β–Ά Play video
fossil spoke
#

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.

swift sorrel
#

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

dark parcel
#

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

limber gyro
#

could he get something similar if he treated the ball as a projectile?

#

projectiles are syncd between everyone aren they?

subtle kernel
#

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

fossil spoke
#

It cannot be changed.

#

At least not without modifying the engine.

subtle kernel
fossil spoke
#

You should setup your own soft form of mechanic that mimics its effects.

subtle kernel
#

yea, I will do it later, don't want to waste time on it right now

blazing maple
#

One message removed from a suspended account.

nocturne quail
#

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

nova wasp
#

There's also FApp::CanEverRender I guess

#

but generally you just GetNetMode to determine if it is dedicated

nocturne quail
nova wasp
#

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

nocturne quail
lament flax
#

or compare GetNetMode() with a int

#

if GetNetMode() < NM_Client

chrome bay
nova wasp
#

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

chrome bay
#

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

median igloo
#

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)

median igloo
#

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 πŸ˜‚

nova wasp
#

how would player 2 get the second player index controller when they only have one controller on their client

median igloo
nova wasp
#

ah, I'm a dingus and missed the "local" part

median igloo
#

im only a first year im not doing all that πŸ˜‚

dark parcel
#

not a lot of people doing local mp fyi

#

so it may take some times to get answer

median igloo
#

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

dark parcel
#

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?

median igloo
#

yeah

#

i gave it possession and added the input context yeah

dark parcel
#

how and when do you bind the input mapping context?

median igloo
#

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

dark parcel
# median igloo

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

median igloo
#

i just moved the mapping to the player blueprint

#

thoes are the two blueprints involved

median igloo
dark parcel
#

you should do for player 1

#

imo, I will just move the binding in the OnPosses event

median igloo
dark parcel
#

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.

median igloo
#

and i can just run that in their respective blueprints?

#

is OnPossess what the node is called? i cant find it 😭

dark parcel
median igloo
#

OH i see

#

event possessed

#

found it

dark parcel
#

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

median igloo
#

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

dark parcel
#

Is player 2 different bp?

rapid mango
#

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?

tardy fossil
#

try doing [OnlineSubsystem] DefaultPlatformService=Null cause I dont think "lan sessions" is a thing.. but i could be wrong

rapid mango
#

I tried, but this did't help

rapid mango
#

I've got this.

SessionSettings->Set(InSettingKey, InSettingValue);

should look like this :

SessionSettings->Set(InSettingKey, InSettingValue, EOnlineDataAdvertisementType::ViaOnlineService);
glossy wigeon
#

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?

upbeat basin
glossy wigeon
upbeat basin
#

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

glossy wigeon
#

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.

upbeat basin
glossy wigeon
upbeat basin
glossy wigeon
#

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?

upbeat basin
dark parcel
#

you can design it how ever you want

#

the easiest one is obviously just to accept that client did a hit

glossy wigeon
glossy wigeon
dark parcel
#

next level from that is some server validation

glossy wigeon
#

It's just if someone is cheating bad right?

dark parcel
#

server chekc if the hit is possible or not

dark parcel
#

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

glossy wigeon
#

so basically just a way of checking if the hit that the client said it did is not to far of right?

dark parcel
#

who has the say and so on.

upbeat basin
#

Yup it all depends on the needs, every solution has it's own pros and cons concerning development time, cpu usage, cheat protection etc.

glossy wigeon
#

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

upbeat basin
#

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

glossy wigeon
#

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 πŸ™‚

pale hazel
#

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

crisp shard
#

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

pale hazel
# upbeat basin Are you testing on PIE?

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

upbeat basin
pale hazel
#

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 πŸ˜…

upbeat basin
#

Hmm I feel like I remember a conversation about this

upbeat basin
pale hazel
#

Hm, that's a good guess for sure, thanks for the help!
I'm just happy that it works for now haha

crisp shard
glad escarp
#

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.

haughty ingot
glad escarp
haughty ingot
#

Some stuff won’t be possible without C++ (like forcing actors to be stably named).

glad escarp
glad escarp
#

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.

nocturne quail
glad escarp
nocturne quail
#

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

glad escarp
#

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.

nocturne quail
glad escarp
nocturne quail
crisp shard
# crisp shard update: i just stored the new pawn on the controller do the work in the game mod...

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

glad escarp
grand kestrel
#

Ahem, sorry, ignore that @, Cedric
I was actually 99.9% of the way there

thin stratus
#

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

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

thin stratus
#

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

grand kestrel
# thin stratus Hm yeah. Not sure about the ServerMove part
    // 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()

median igloo
#

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

thin stratus
#

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

lament flax
thin stratus
#

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

oak night
#

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?

fossil spoke
#

Is it owned by a PlayerController?

oak night
#

Its not a replicated actor

fossil spoke
#

Then it cannot send RPCs

#

If its not owned by a PlayerController then it cannot send an RPC to the Server.

oak night
#

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.

fossil spoke
#

Well then CheckPlayers is being called by both of them.

oak night
#

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?

fossil spoke
#

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.

oak night
#

Ok give me a sec

fossil spoke
#

If asking for help, its important to provide as much context as possible.

oak night
#

And thanks guys

fossil spoke
#

Otherwise we just waste time playing 20 questions

oak night
#

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

fossil spoke
#

This is doing what I would expect it to do if the default value of the PlayerNumbers is 0 and you have just clicked once.

#

What are you expecting to happen?