#multiplayer

1 messages · Page 281 of 1

torpid lantern
#

Can somebody please sanity check me:

  • Create BP actor, print "hello" on BeginPlay
  • Drag actor into level
  • Play as client; observe Server & Client "hello"
  • Set replication = True on actor, play as client; observe Server only "hello"

Is this expected behaviour? I'm completely lost as to why BeginPlay is not firing. If I runtime spawn the actor, then BeginPlay triggers. It looks like it only affects manually placed actors.

quasi tide
#

No - that is not expected behavior.

#

BeginPlay will execute on all actors for all machines.

nova wasp
torpid lantern
#

Negative, net load is True

#

I am using vanilla Iris, not sure if that does anything. Also on 5.7.1, might be a bug.

nova wasp
torpid lantern
#

For the print? I was looking at the viewport, but the a breakpoint isn't triggering on client either.

strange apex
#

Hello, I would appreciate little bit of guidance on Replication.

Currently I am trying to pick up an actor into my hands and then drop it on the floor, this already works the problem is when i try it in multiplayer.

this is my pickup setup and the drop setup

I already tried using "custom events" that run on server at different locations but nothing seems to get it to work properly, also from what i understand line trace should be done on client and the actual pickup should be done on server.

nova wasp
torpid lantern
#

Will give it a shot, trying with a fresh project first.

#

Works fine in a new project, no output log of begin play from client on my project.

torpid lantern
#

Observations changed based on map, wtf?!

In my world partitioned map, BeginPlay for the replicated actor triggers on both client and server
In my non-world partitioned map, begin play only triggers on server

What am I missing here?

Edit: Deactivating Iris appears to have resolved the issues :(

strange apex
#

( this is the local version also tried the custom event version )

#

this is running inside event graph of the master item actor

nova wasp
nova wasp
#

when you show stuff like this it helps to describe which parts happen on which side, or which do not

#

otherwise it will 30 minutes of asking "which side did this happen on"

strange apex
#

I fixed it, had two issues

  1. I was running my "set Bool" on server and not locally
  2. I Was trying to destory the actor within the actor, now it destroys it within the player bp
nova wasp
#

yeah I wasn't sure if the boolean was supposed to be local only or replicated

nova wasp
#

be more specific

#

and show what you are actually doing

#

they do work if you actually dirty things correctly and use pushmodel

nova wasp
#

AGun must also be replicated

#

unless a pointer is stably named (an asset path, something in a level) it generally needs to be a replicated object

#

to be sent across

#

not what I meant (but yes, the replicated property must be replicated)

#

I mean the ACTOR must be replicated

#

if you are new to multiplayer I would suggest reading the pins, they should help a fair bit if this is new stuff

#

or help with some assumptions about things that aren't intuitive (rpc rules etc)

#

Transient just means you don't want to save that property in asset instances of that object generally

#

not sure if it affects replication in any way or not

#

I am surprised that affects a replicating pointer

#

does adding it back break it again?

#

I am curious if its not just compilation issues

#

Is it set during editor time?

#

(outside of the game running in the details panel etc)

nocturne iron
#

TL;DR: Sorry for wall of text. How do I replicate a nested inventory system where item and inventory are UObjects?

I am trying to make an inventory system where items can have their own inventories (for weapon attachments, containers, etc). Both the logical inventory and the logical item is UObject (UItem and UInventory).

The inventory contains a size + list of item pointer. The item contains the dynamic item state, fragments and reference to it's definition.

My issue is this. I have no idea how to cleanly replicate this?

My instinct was that the Item can be replicated subobject of the Inventory, but after looking at source, that it not supported.

An alternative would be to have a global AInfo actor spawned by subsystem or a GameState component replicate them. But that introduces new issues as well (e.g. messy GC). This is the best solution I have found so far. The original design was doing this, and I went away from it because I did not like that everything depended on it.

I really like both UInventory and UItem being UObjects , because it makes the blueprint API, and logical model very simple.

nocturne iron
#

@violet sentinel I read Jambax blog post on replicating uobjects that you mentioned, but as I see it, the problem remains. Nesting of items and inventories is kinda what creates the issue.

I also don't know the implications of moving items from one actor channel to another (i.e. moving item to another inventory). Is there a way to transfer the ownership without the objects being recreated on the client? I would imagine werid stuff happening if I were to do RemoveSubObject from inv1 and then AddSubObject on owner of inv2? (can client keep the context?)

(sorry for ping, but cannot reply since message was in other channel)

violet sentinel
#

so your inventories are global and can move between actors?

nocturne iron
#

Since items can have inventories, yes. If a "container" item is transfered between inventories.

#

And I guess the same kinda goes for equipment items. Like backpacks, depdening on implemention.

#

Is there any reasonable way around having a replication proxy/game state component in this case? I really hate the concept of it since it will tangle everything, but I just don't see another way.

violet sentinel
#

UInventoryComponent with replicated UItems, Component has unique identifier.
Player could have UInventoryComponent for own
Weapon or any other item else could have either own UInventoryComponent or GUID to global storage
Any stray item in world most likely be an Actor with Inventory Component or GUID to global storage
GlobalStorageActor (possibly Managed by WorldSubsystem) could have many UInventoryComponents and can be quieried/removed by guid

#

example

#

if you don't want to mess too much with subobject replication

nocturne iron
#

How would this work for containers, like a bag in the inventory with no world representation?

Currently my version of UInventoryComponent, just wraps a UInventory object.

nocturne iron
violet sentinel
#

bag would hold identifier "my inventory is guid xxx" and the actual data picked from global storage

#

yea

nocturne iron
#

I see.

violet sentinel
#

isntead of gamestate - separate actor

nocturne iron
#

Maybe it's best.

nocturne iron
round summit
#

i want to show buffs on my characters. i was planning to use widget component on each character but i wanted to know if there is a better way right now its purely single player game

nocturne iron
nocturne iron
#

I really hate this approach, but maybe it's just what needs to be done here.

#

It also make automated testing way more messy.

violet sentinel
#

do you set up inventories purely in runtime or on level too ?

#

and no, everything should be done via world subsystem, actor as a backend for replicating work

nocturne iron
#

But we could just add some layer on top for editor. It will be needed at some point.

nocturne iron
round summit
nocturne iron
hazy scroll
#

I'm confused. I am trying to get the line trace working in multiplayer. With this setup the line trace position is correct in local pie but wrong in multiplayer pie. The start and end of the trace is not proper replicated and I don't know why

lost inlet
hazy scroll
# lost inlet this looks fairly jank to begin with? why would the trace start/end be replicate...

I did the variable replication as a test because it did not work without it. But it changed nothing. Same issue on every pie mode except standalone (local). To clarify it. This a weapon bp with a skeletal mesh (actor + movement replicated). The player poses are correct replicated (clients see it). So for example i make a left attack the trace positons are not on the socket positions in world space (but both clients see the weapon swing)

exotic wasp
#

I have an UInventoryComponent, UInventory, and UItemInstance as my main types

#

Subobjects must replicate through a component or actor

#

So the manager component is the outer of all of these subobjects and handles all transactions between inventories so that it can add/remove subobjects

nocturne quail
#

using an array of weapons, is it even possible to do it the optimized way to find the preferred slot?

uint8 UWeaponManager::FindSlot() const
{
    // CASE 1: Character has no weapons attached
    if (!IsValid(EquippedWeapons[0]) && !IsValid(EquippedWeapons[1]) && !IsValid(EquippedWeapons[2]))
    {
        return 0; // Attach first weapon to hands
    }
    
    // CASE 2: Character has two weapons and both are on spine (slots 1 and 2)
    if (!IsValid(EquippedWeapons[0]) && IsValid(EquippedWeapons[1]) && IsValid(EquippedWeapons[2]))
    {
        return 1; // Replace weapon in spine slot 1
    }
    
    // CASE 3: Character has one weapon in hand and one on spine
    if (IsValid(EquippedWeapons[0]) && (IsValid(EquippedWeapons[1]) || IsValid(EquippedWeapons[2])))
    {
        // Find which spine slot has a weapon and replace it
        if (IsValid(EquippedWeapons[1])) return 1;
        if (IsValid(EquippedWeapons[2])) return 2;
    }
    
    // CASE 4: Character has only one weapon (in hand)
    if (IsValid(EquippedWeapons[0]) && !IsValid(EquippedWeapons[1]) && !IsValid(EquippedWeapons[2]))
    {
        return 1; // Put new weapon on spine slot 1
    }
    
    // CASE 5: Character has weapon only on spine (hand is empty)
    if (!IsValid(EquippedWeapons[0]) && IsValid(EquippedWeapons[1]) && !IsValid(EquippedWeapons[2]))
    {
        return 0; // Put new weapon in hand
    }
    
    if (!IsValid(EquippedWeapons[0]) && !IsValid(EquippedWeapons[1]) && IsValid(EquippedWeapons[2]))
    {
        return 0; // Put new weapon in hand
    }
    
    // Fallback: spine slot 1
    return 1;
}
exotic wasp
#

There's no nodal system so you have to basically just loop through all objects and add/remove them if you add an inventory

lost inlet
exotic wasp
#

I have really tried to find alternatives to this solution but they almost all make you lose control over relevancy which is very important for an inventory system IMO

nocturne quail
nocturne quail
#

another approach but still not feels good

uint8 UWeaponManager::FindPreferredSlot(const EWeaponType Type) const
{
    if (Type == EWeaponType::E_HANDGUN) return 3;
    if (Type == EWeaponType::E_THROWABLE) return 4;
    
    const bool H = IsValid(EquippedWeapons[0]); // Hand
    const bool L = IsValid(EquippedWeapons[1]); // Left back
    const bool R = IsValid(EquippedWeapons[2]); // Right back
    
    // Truth table for all 8 possible states (H L R)
    if (!H && !L && !R) return 0; // 0 0 0 → Hand
    if (!H && !L &&  R) return 0; // 0 0 1 → Hand  
    if (!H &&  L && !R) return 0; // 0 1 0 → Hand
    if (!H &&  L &&  R) return 1; // 0 1 1 → Replace Left
    if ( H && !L && !R) return 1; // 1 0 0 → Left back
    if ( H && !L &&  R) return 2; // 1 0 1 → Replace Right
    if ( H &&  L && !R) return 1; // 1 1 0 → Replace Left
    if ( H &&  L &&  R) return 1; // 1 1 1 → Replace Left (fallback)
    
    return 1;
}
dark edge
#

my items are just structures but yeah same idea, just have a global mapping of what contains what and you can represent arbitrarily deep nesting of inventories.

exotic wasp
dark edge
exotic wasp
#

ah

dark edge
#

You don't know what's in a thing until you look

#

but you could certainly just replicate the entire state of the world

#

depends on if you're doing a small roguelike or Factorio

exotic wasp
#

if it's a global mapping though, how do you control who gets what? when you say query is it all RPCs?

dark edge
exotic wasp
dark edge
#

Depends on if you want their computer to actually know what's in the treasure chest across the map or no

exotic wasp
#

Because nested subobjects are genuinely painful

nocturne quail
#

in the posted logic only 3 slots are handled currently

#

there is a case where player has 3 weapons equipped, and it will replace one on the back if the 4th pickup weapon is also belongs from primary

nocturne iron
exotic wasp
#

Maybe you should have a TMap<ESlotType, TArray<Slot>> or something

nocturne quail
#

i can map array of structs, but it will be overhead, my inv items are already replicated uobject structs data

exotic wasp
#

All of the slots being in one array strikes me as odd if they don't hold similar things

nocturne iron
nocturne quail
exotic wasp
#

An array of arrays would be the same in this case since you are just keying off of an enum, actually

nocturne iron
nocturne quail
#

seems like I have to drop support for 3 primary weapons slots, its too much... will just do two slots like in typical battle royals like pubg or others

dark edge
#

Why not just loop over all slots and choose the first one the thing can go in, if it can't go in any then do whatever the failure state is

#

should just be a for loop and a bit of logic, nothing crazy here

exotic wasp
#

^

#

Looping over a small number of entries is usually more efficient than a map or something anyway

nocturne quail
exotic wasp
#

Well that's a bug

dark edge
#

a given item can only go in 1 slot type, right?

#

and you got 4 slot types

nocturne quail
#

using two slots simply solve it, where one slot is always empty, it can be leftback, rightback or hand

uint8 UWeaponManager::FindPreferredSlot() const
{
    // Get current weapon states
    const bool HasHand = EquippedWeapons[0];
    const bool HasLeft = EquippedWeapons[1];
    const bool HasRight = EquippedWeapons[2];

    if (!HasHand)
    {
        // Hand is empty - prefer hand unless both back slots are full
        return (HasLeft && HasRight) ? 1 : 0;
    }
    else
    {
        // Prefer left back if available, otherwise right back
        return HasLeft ? 1 : HasRight ? 2 : 1;
    }
}
nocturne iron
nocturne quail
dark edge
#

just order the slots by priority and loop

exotic wasp
dark edge
#

that'll handle the "go in the first empty slot" case
The other case is when all slots it could go in are full, in that case you swap it with whatever is in the first or last slot it could fit in

nocturne iron
nocturne quail
#

for(uint8 curr = 1; curr <2; curr++) isvalid(currentweapons[curr]) return curr; return 0;

dark edge
#

TArray<ESlotType> SlotTypes = {Primary, Primary, Primary, Secondary, Secondary, Sidearm, Sidearm, Melee, Melee}
TArray<UItemThingy*> EquippedItems

for loop over SlotTypes
if NewItem.SlotType = SlotTypes[i]
if !EquippedItems[i]
Equip NewItem in slot i

Could also just be an array of SlotType,UItemThingy tuples if you wanted but you get the idea

exotic wasp
#

So the inventory manager component is attached to actors

#

The manager has a root UInventory

#

UInventory holds UItemInstances

#

All inventories and item instances are subobjects of the owning manager component

nocturne iron
#

I see. How do you transfer the item instances when moved between inventories then?

#

Just remove and re-add?

dark edge
exotic wasp
#

If it's from one manager to another you have to change the outer of all moved objects to be the new manager and also register them as subobjects

#

His edit is true

nocturne iron
#

This is ofc not an issue when using structs.

exotic wasp
#

I believe replication logic handles the renaming of a UObject and moving to be a subobject of something else

dark edge
nocturne iron
#

Are you sure? it seems like one of those assumtions that only fail when live and some dude from russia wanna join the american server.

I am just thinking client gets this order:

  1. Item is removed as subobject:
  2. Client GC destoryed item
  3. Item is added on new inventory
exotic wasp
#

It won't destroy it as long as the item is added to another inventory the same frame

#

Otherwise it will be destroyed on the server regardless most likely

#

GC doesn't sweep until every update

nocturne iron
#

I see, so this works if all item move is done with single request, and the inventory does not actually replicate it's item array directly.

exotic wasp
nocturne iron
#

My mental model was basically

UInventory
  UPROPERTY(Replicated)
  TArray<UItem> Items // or FA, but you get the idea
exotic wasp
#

That works

#

But both the inventory and items are replicated through the owning manager component

#

If an item is moved from one inventory in a manager to an inventory in a different manager, I believe it will not be destroyed

nocturne iron
#

But you just said the manager component was not global, in your case, so it does not?

exotic wasp
#

This is all contingent on relevancy

nocturne iron
#

If you have an in world container. Would it then have it's own manager?

#

Like a chest or something

exotic wasp
#

The chest actor or whatever would have its own manager component in my system

nocturne iron
#

And the manager owns it? I.e. It might be GCed if not in an inventory and no other referneces extist?

dark edge
#

All you care about is that the SERVER state is transactional, and that the CLIENT state is eventually consistent with the server

nocturne iron
#

Then, if you replicate using Replicated specifier in UInventory, then my scenario with a client receiving notice of item removal, then GC's, then recrease is possible, though a small window?

exotic wasp
#

There will be no gc

nocturne iron
exotic wasp
#

If you remove an item and don't add it anywhere it will get gcd

nocturne iron
exotic wasp
#

Order isn't guaranteed, no. But it is guaranteed to occur within the same frame I believe.

#

As long as an object has references to it by the end of the frame, GC should leave it alone

nocturne iron
nocturne iron
exotic wasp
#

It would be nice if it was possible to make uobjects replicate independently by default

dark edge
#

I mean the item might blink out of existance for a bit or be in both inventories at the same time for a bit but never on server

nocturne iron
nocturne iron
#

It's just not perfect xD

exotic wasp
#

Should be cosmetic on clients anyway

nocturne iron
#

Yeah.

dark edge
nocturne iron
#

It is true.

dark edge
#

This is why I like structs

nocturne iron
#

@dark edge , may I ask why you choose global manager over local managers like plinyvic? What are the pros and cons.

dark edge
dark edge
#

food rotting, a cell phone inside a bag inside a box ringing, stuff like that

nocturne iron
#

I started out by doing something 100% transactional with a global game state component and structs as well. But it took too much work making it nice for the designers that we change it to UObjects instead, and diteched transactional rollback etc. Not we are at it again xD

nocturne iron
exotic wasp
#

That's what I meant

#

Yeah

#

Nested subobjects are hell

#

The engine seems to hate them, especially with instanced structs

#

The perfect solution IMO would be a global manager of UObjects where you can control the relevancy

#

But that's impossible without using Iris afaik

nocturne iron
#

Yeah.

exotic wasp
#

It's all down to what data your client needs to see

#

If your items are living objects similar to actors then you need special systems in place that I would think a global manager of structs just can't do

#

This is the path I took but I've been genuinely struggling to see a benefit of it over just structs

dark edge
#

in my case there's 2 states.
Either an item is stored and you just get to know about it when you look (request the contents of its container)
Or an item is instantiated as an actor, in which case it's just an actor with a copy of the structure.

exotic wasp
#

Because almost all logic is done on the server

#

I had item actors in the world just act as an inventory that holds an UItemInstance

#

and if you pick it up it just gets transferred to your inventory

nocturne iron
#

I really wish it was easier to do good blueprint API for structs. We have some special replication stuff on the items to allow for a pretty right fragment system, also available to blueprint. I implemented first variation with structs but API was pain, and we just needed to ship, so changed it for ease of use, so that the desginer would stop complaining. But that might have been shooting myself in the foot.

#

The whole not being able to reference a struct from blueprint is so stupid.

#

Member functions would be nice, but they could also just be static. It's the pointer to a struct thing that really makes it a pain for us.

exotic wasp
#

Structs in BP are a no go for anything meaningful

#

Imo

nocturne iron
exotic wasp
#

It's even difficult using instanced structs in bp because you can't get references...

dark edge
exotic wasp
dark edge
#

can be a TMultiMap on the back end or any other data structure, even just a IDOfParent in items if your count is small

nocturne iron
#

Yeah, I guess with a global manager that is super easy.

dark edge
#

I got a couple ideas surrounding global item IDs that I'd like to flesh out, if everything is a GUID under the hood you can do some very interesting stuff

nocturne iron
#

is the "GimmeTheContents" function on static / global manager or do you have object for inventory. For blueprint API?

dark edge
#

global manager or some proxy of it

nocturne iron
#

Hm- maybe I should go back to something like that. It seems so sane now that I am standing on the other side of the fence again.

#

Always does xD

dark edge
#

If you don't have millions of items and don't mind the state technically being on clients then I'm sure you can just fastarray the global state and make the queries not have to be RPCs

exotic wasp
#

Inventory systems in this engine bother my soul

nocturne iron
exotic wasp
#

I swear I've spent more time on an over engineered inventory system than anything else in my game

#

Need to cut my losses lol

sage lance
#

i use a bpc for my inv. works in multiplayer. array of structs. all blueprint.

nocturne iron
dark edge
#

On a similar topic, anyone have any ideas for partial state replication on subsystems?

#

Basically I have a 1D physics engine which is made up of a subsystem per domain (type of particles) and per device (constraints between particles)

#

The whole thing runs locally on each machine

exotic wasp
#

Partial state?

dark edge
#

but I have some "discrete" state that I want to replicate.
For example, I don't care to replicate the continuous RPM of a driveshaft, but I DO want to replicate the selected gear or gear ratio of a gearbox.

sage lance
#

selectively replicate variables in your system

exotic wasp
#

Maybe I don't understand, but can't you just have some properties be replicated and some not be?

#

^

nocturne iron
#

not sure what the context is

dark edge
#

Kinda an insane architecture but it works great

#

So this is the business end of a subsystem that does all the updates for all gearboxes in the world. Nothing is actors, it's all just structs in arrays

#

But I'd like the clientside version of this scene to have the same gear ratio as the serverside, since that's a discrete value and is driven by continuous "analog" values

nocturne iron
#

It seems like this sort of stuff should be super predictable?

exotic wasp
#

AInfo proxy?

#

Id imagine you can get rpm cosmetic from gear and other state

dark edge
nocturne iron
dark edge
sage lance
#

shouldnt the gears be fixed?

dark edge
#

inputs to the web of devices are synced, and final outputs are synced

exotic wasp
#

So what's the issue with replication?

sage lance
#

i would replicate a state like 1st-6th gear and have the ratios stored with a value reference

nocturne iron
exotic wasp
#

Same difference though

dark edge
#

I think what I'm after is some sort of replication proxy actor per subsystem that can selectively sync up the properties I want

#

Might help to show a bit of it in action

exotic wasp
#

AInfo replicated that the subsystem points to

dark edge
#

Basically the gist of it is that the entire sim between your inputs and the final physics of the vehicle is represented by a web of devices connected port to port

exotic wasp
#

This strikes me as normal replication imo

nocturne iron
#

Ah, that's cool!

exotic wasp
#

Using a subsystem will remove the ability to leverage relevant I believe

nocturne iron
#

Yeah, I don't see why you would replicate it with a proxy.

dark edge
#

Yeah i gotta think about relevency, right now everything is always relevent

dark edge
nocturne iron
exotic wasp
dark edge
#

I wouldn't be opposed to moving this to components on an AInfo or something of the sort

nocturne iron
#

Right for each device.

dark edge
#

I'll have about 40-50 subsystems once done

exotic wasp
#

Ohp

dark edge
#

at like 20 rn

exotic wasp
#

Out of curiosity, why subsystems?

runic crane
#

Any thoughts on why calling a delegate on the Game State from a Client character's OnRep_PlayerState might be crashing the game with the following error?

TDelegateAccessHandlerBase<FNotThreadSafeDelegateMode>::FReadAccessScope::FReadAccessScope()

dark edge
#

I like the automagic instantiation, performance is a concern as this has to crunch a LOT of math

exotic wasp
dark edge
#

It's kinda like a half-assed ECS type thing, the subsystem is the array of C and also the S

exotic wasp
nocturne iron
dark edge
#

you can add a part just by passing a struct to the subsystem

exotic wasp
#

You can have a component that gets all the relevant data from the subsystems and replicates it to clients

#

It would give you relevancy

#

Like if you have a car, put the component on it. Then the component on the server gets all needed state and replicates it

nocturne iron
#

I am only talking about basically having an API layer of actor components, that takes care of most of the replication, assuming relatively deterministic sim. So the mathy part is in a subsystem and the gamey part is architected a bit more traditionally. But maybe I am missing what is going on? xD

exotic wasp
#

An AInfo per system would also work but it would replicate everything to all clients all the time which is probably not desired

exotic wasp
#

And I agree

#

Replication of this is essentially an additional layer

runic crane
exotic wasp
#

I'd reccomend compiling with a debug build and seeing where it breaks with your IDE

nocturne iron
exotic wasp
#

@dark edge id look at how people replicate using mass

dark edge
nocturne iron
exotic wasp
#

a factory is still a unit thing that can get replicated together

dark edge
#

city sim

exotic wasp
#

network ins/outs is still a single unit

#

you might not see everything else but you can see the demand/supply

nocturne iron
lost inlet
#

and yeah this will just be a shot in the dark with no other context

#

like... the code

exotic wasp
#

100% of the time using a debugger in a debug build will yield good info

lost inlet
#

this is a packaged build and it's likely enough to find the cause

runic crane
#

I'm not, but then that brings up my actual issue I guess. I need a reliable spot for the local player to broadcast that their ASC has been initialized locally, so that other actors can compare tags and stuff to determine if they should be visible for the local player.

I should be able to check quickly if the Game State is valid or not though. If it isn't, that would mean it hasn't been replicated yet?

nocturne iron
dark edge
nocturne iron
#

Damn, i see.

dark edge
#

but at the end of the day, all I care about is the final result, the physics state of the car.
Of course there are intermediate cosmetics that have to be consistent but they don't have to be synced

#

the only things in the middle that have to be hard synced are discrete state, things like the state of a flip flop or the gear that a transmission is in

#

because on the server the web of Signal that fed the gearbox might have made it to 1.0 and triggered the change, but on the client it made it to .99 and didn't. Don't want to get stuck like that for ages.

#

It's like analog electronics, with some discrete state here and there. The discrete state is what needs to be hard synced.

exotic wasp
dark edge
exotic wasp
#

You can probably get by with interpolating state

dark edge
#

but if I'm in 3rd gear on the server and 2nd on my screen it's a bad day for a while

#

it has to sim on both sides

exotic wasp
#

But the sim is cosmetic on clients, right?

nocturne iron
#

and physics

#

which is also cosmetic

#

still matters a lot for ux

exotic wasp
#

You want it to be mostly consistent, but there's a level where interpolation will be unnoticeable

dark edge
runic crane
exotic wasp
#

And tbh probably still needed because replicating anything smooth without interpolation feels stuttery

sage lance
exotic wasp
#

Can you just add an event yourself if it doesn't already have one?

lost inlet
runic crane
# lost inlet I'm interested in what you're trying to do (including what your current approach...

It's probably simpler than how I'm making it sound. Basically, there are gameplay tags that represent "dimensions" a unit is in. So if a unit is in the same "dimension" as the local player, it should be visible; otherwise, it shouldn't be.

I'm using the ASC Begin Play to do an initial check, but also sub to events for when a unit's "dimension" changes. I check for a local player state to then get their ASC, since both the actual unit's tags and the local player's tags are relevant to determine visibility. But here's where I'm surely lacking knowledge as it seems Begin Play isn't being called on these units for the local player.

dark edge
#

I'm not doing prediction if that's what you're asking

#

Client character just sends inputs to the cockpit they are sitting in and it's out of their hands and out of their direct ownership after that

exotic wasp
#

(not a mispost)

#

You're basically trying to do the same thing

glossy wigeon
#

I'm currently trying to load a level instance, that also contains some replicated actors.
But when I load the level on the client, the actors are just on client spawned actors not the replicated ones and when I disable Net Load on Client, then they are not loaded on the client.
Any ideas what I can do?

exotic wasp
#

If you set the name override to be identical it should replicate right

glossy wigeon
exotic wasp
#

Yup!

nocturne iron
sage lance
mystic ledge
#

Is there anyone who can help me with an issue regarding inputs?

fossil spoke
#

Don't ask to ask a question.

#

Just ask the question.

#

If someone can answer it, they will.

mystic ledge
#

Pretty complicated issue, I set up an environment with two players. Any inputs I do control both players on the first screen but the second screen stays still until I go to it and it does the same thing and then it doesn't show on the first screen.
it's going to be an online game so i cant have the mouse controlling both players at the same time

glossy wigeon
#

I'm trying Chaos Mover and just have a Actor and added the ChaosMoverComponent and NetworkPhysicsSettings similar to the Mover Examples plugin and put it into flying mode.
But then bumping into it's not smooth at all, the same happens when putting it into falling mode.

Any ideas what cause this?

halcyon ore
#

Feels like more general multiplayer, then online-subsystem.
When you make a session, it has those sessions settings, or whatever they are.
And, when you search for sessions, it returns those session settings (you know, ping, name, player count, hashed password, etc)
Should you be putting a lot of info there?

I was wondering if I could stick a like “whitelisted steam ids” in there, so when joining the client can do a simple check, and bypass the password.

OF COURSE, on join the ID would be checked again, so that the client can’t just spoof there ID on join.

sturdy moat
#

Context:
I'm trying to implement an object pool for bullets to reduce overhead but there is a few issues I see.

In the game players can have multiple weapons on their vehicle with various fire-rates and may switch between them at any time. So if all players play with the lower fire-rate weapon only tens to hundreds of bullets are needed at once while hundreds to thousands of bullets may be required if they use the higher fire rate weapons. So the range of bullets required is broad and not predictable. Furthermore, I want to avoid bullets disappearing before hitting anything & running out of bullets in the pool.

The game is set in decently big, open maps where players are flying around so they would definitely notice bullets disappearing midair.

Options and their downsides I have considered:

  1. Using the upper bound of required bullets for any pool:
  • Avoids the issue of running out of pooled bullets but probably has more bullets initialized then needed for the overwhelming majority of situations.
  1. Using a "dynamic" pool
  • You could start off by initializing one pool of small to medium size and if it is close to running out another pool (or more objects for the existing pool) could be initialized over a few frames and then deleted again if none of the new bullets are used for a while. This seems to kind-off go against the idea of pooling but on the other hand would pretty consistently only have roughly the needed amount of bullets spawned. Would also probably fragment memory but at least in bigger chunks compared to spawning and deleting individual actors.
  1. Faking all the bullets
  • Circumvents the issues but also seems very hard to get right and comes with its own issues and its harder to stick to OOP principles with this approach.

Question:
So I'm wondering what is usually done in this situation as I'm sure I'm not the first to run into this. Also wondering if memory fragmentation is a big concern with UE5 or if the engine handles that itself.

dark edge
#

And right now, what IS a bullet, an actor? A UObject?

nocturne quail
sturdy moat
# dark edge What do you mean by faking?

Instead of spawning actual bullet objects/actors replacing them by line traces executed over the covered distance for each frames delta time + a niagara particle system visually "faking" a flying bullet. Currently the bullets are actors with the projectile movement component but I wouldn't be averse to looking into using UObjects instead, its been a while since I created them anyways and there is some stuff I want to redo.

dark edge
#

And I wouldn't call it fake, it's the exact same mechanic, just much lighter. All a projectile movement component does is the same math but with a collider sweep instead of a trace. For a small enough collider it's identical.

#

I just use POD structs in an array for my projectiles

sturdy moat
#

yea I thought I might have to go that route. Still curious though if there is common practices/solutions when one wants to use object pooling and the possible range of needed objects is very broad

sage lance
dark edge
#

why would the range of object types be broad? I mean they can look different and carry different payloads but there's no reason why all projectiles in your game can't fundamentally be the exact same class/struct

sturdy moat
# dark edge why would the range of object types be broad? I mean they can look different and...

i mean the object count not type. Like as far as I understand the idea of pooling is to save overhead by initializing the required objects at the start and prevent memory fragmentation from constantly creating ad deleting objects. But if the number of required objects could be in the 10s or in the 1000s and you have no good way of predicting how many you actually need, making a small pool might mean running out and making a large one would probably have more objects in memory than required at most times.

glossy wigeon
dark edge
#

you can even make it bigger and after the copy it'll all still be contiguous

nocturne quail
dark edge
#

idk if UObjects can be allocated contiguously or not but I wouldn't bet on it

sage lance
#

equipping certain weapons -> add projectiles to pool

sturdy moat
# sage lance you could adjust the pool size based on demand

yea that was one solution I was thinking of but then I thought it kinda goes against the idea of pooling bc you are now initializing more projectiles during gameplay and end up deleting them when no longer needed which somewhat diminishes the benefits of initializing everything at the start.

sage lance
#

just throttle it

#

so ur not spawning/deleting 1k objects at once

sturdy moat
#

yea

#

I think I have some good starting points now to go off of. Thanks for the advice guys

sage lance
#

you could also try a super large pool and profile its impact on memory

vocal current
dark edge
#

Keep the same energy going, if your projectiles MUST have a diameter that's useful for gameplay then just switch to a sphere trace

vocal current
#

Yeah it's absolutely valid to also fake things like rockets

#

It's just that if you are going to spawn actual actors for your projectiles, rockets and grenades are a more obvious choice, and likely to be less egregious performance wise. Though depends on your player count

#

I mean for a 4v4 arena shooter for example, you probably aren't going to be firing more than 8 grenades/rockets per second

#

And actually hitting 8 per second would be a very unlikely case to hit

dark edge
#

You've never hooked your rocket projectile up to your minigun?

vocal current
#

Haha you could do, but most games don't for reasons other than performance is what I mean

#

Because if you're going to allow people to fire grenades from a minigun you might as well allow your player to call in an airstrike or something

#

Since the results will be similar

#

From a gameplay perspective

#

Though internally (as in things that have never shipped but gameplay programmers made internally to make their friends laugh), I have seen some classic examples of this.

One being an arrow that spawned angry elephants wherever it landed

nocturne quail
vocal current
#

I wonder if there would be any benefit at all to using Mass for this...

I imagine not since ray/shape casting is an inherently CPU cache unfriendly thing to do and therefore there may not be much benefit

#

That's some nice code right there. Very clean

exotic wasp
#

your main speedup would be from running it in parallel

#

but you would have to query the physics scene from other threads which has some quirks iirc

sage lance
#

any ideas why this takes like 3 seconds to start swapping the map?

halcyon ore
#

My guess would be asset loading.
But I could be dead wrong.

sage lance
#

My asset handling is loaded through lyra experiences. The loading screen pop ups before it loads the map and experience. The time gap is between these events.

cursive mirage
#

would like to develop an online multiplayer system using a listen server. In that case, is it difficult to do so without a wired network environment and the ability to run tests using AWS?

I imagine that, in a country like the United States, the distance from one end to the other is comparable to that between different countries, so there would likely be noticeable latency.

nova wasp
#

you can always emulate packet lag and loss in the editor

#

with packet emulation settings

#

"online multiplayer system" to me sounds like you intend to make this like the backend of some sort and not just a typical game server

cursive mirage
nova wasp
#

then yeah, you can emulate packet lag in the editor

nocturne quail
#

can we call this by animnotify with passing arguments?
void switchtoslot(TIndex index);

#

or does it need to catch the index upon pressing key 1/2 etc and use it instead of arg?

nova wasp
nocturne quail
#

caching an external var on server fixed the issue to pass the slot instead of arg

#

but I am not sure if it possible to not use the cach and directly pass arg and make the notify call back listen to it

nova wasp
#

okay I am not sure what the issue was originally?

#

caching where? caching why? what is the actual part that is missing?

nocturne quail
#

to make it simpler, notify callbacks can take custom arguments?

nova wasp
#

the anim notify runs and passes in the notify context which includes what it is running on as a pointer (the skeletal mesh)

you can use that skeletal mesh to find a component on it, an actor, whatever

nova wasp
#

it is better to communicate redundantly than to speak in small pieces, otherwise I am constantly going to be trying to figure out the true intention behind what you meant

nocturne quail
#

yeah I know that we can use that skeletal mesh to cast to its owner
AActor* Owner = MeshComp->GetOwner();

nocturne quail
nova wasp
#

why can't the RPC just set something on the owner?

#

I guess that's what you actually meant by caching it

#

remember that I can only see what you tell me here

nocturne quail
nova wasp
#

also IMO if it is gameplay-critical notifies are not viable as they are never really gauranteed to run

#

timers work every time

#

anim notifies do not

#

you can just read the anim notify out the asset and use the time its at with a playrate to set a timer

#

with some tricks it can be frame-perfect as well

#

but it will be harder if timing changes at random (playrate changing in the middle)

nocturne quail
#

these notfies are responsible to equp/unequip weapons, switch weapons etc on a specific frame

#

and the frames speed is also manipulated by the character current boost consumed by character xp

#

not sure if using timers in this case will be ok, and I don't like timers based game play logics

nova wasp
#

you are already using something far less reliable than a timer though

#

but if they can change speed this will get weird... you can gaurantee that a branching point notify will run but only 1 per frame

#

which is fine in most cases

#

but reality can happen

#

what you could do is use a timer as a "fallback" in case the notify misses

#

as a middle ground

nocturne quail
#

I am using them from a long time and never seen any issue with them

#

this is all the notify is doing

void UWeaponManager::EquipNotifyHandle()
{
    if (CachedSwithedToSlot > 1 || CachedSwithedToSlot >= EquippedWeapons.Num() || !OwningCharacter) return;

    AWeapon* TargetWeapon = EquippedWeapons[CachedSwithedToSlot];
    if (!TargetWeapon) return;

    // Already equipped, nothing to do
    if (TargetWeapon->GetEquipState() == EWeaponEqupState::Equipped) return;

    // Equip the new weapon
    TargetWeapon->SetEquipState(EWeaponEqupState::Equipped);

    // Attach to equipped position
    if (USkeletalMeshComponent* Mesh = OwningCharacter->GetMesh())
    {
        TargetWeapon->AttachToComponent(Mesh, FAttachmentTransformRules::SnapToTargetIncludingScale, "Socket_Equipped_Gun");
    }
}
#

EquippedWeapons is actually the current weapon stack

nova wasp
#

you can keep doing whatever you want but I find stuff like this breaking is very bad as you get invisible weapons etc

nocturne quail
#

in a mp scenario already tested and also works fine on other machines 😄 also

nova wasp
#

this the the kind of thing that doesn't happen all the time

#

the term unreliable here does not mean it breaks ALL THE TIME

nocturne quail
#

notify is just a delegate binded to an animation frame like any other delegate we broadcast it

nova wasp
#

that's not related at all to why this is not reliable... never mind...

#

(unless you were just trying to add to the explanation)

nocturne quail
#

I'm using C++ notifies maybe this is why they are working perfectly fine?

nova wasp
#

there is no distinction

#

it might be okay due to just not ever having cases of overlapping the notifies or having a very long time between anim notify ticks (always ticking notifies etc, not having ANY relevancy etc)

nocturne quail
#

hmm, well if they start breaking things, I can refactor at any time 😄

nocturne quail
#

they got at least 1sec time gap

nova wasp
#

yeah the good news is it's very simple to add a dumb fallback timer that you just cancel when it happens in the intended way

#

so it's not bad to have this as the "common" path

nocturne quail
#

timers will also need to track the frames for a delay float

#

since the action should be exec on the exact frame

nova wasp
#

I meant this as a fallback

#

this is not the default case in my example here

nocturne quail
#

ah , yeah thats a perfect suggestion

nova wasp
#

the idea here being you expect the notify will happen (or pray) and then there's a ~N second fallback timer that is longer than any normal notify state that kicks in to FIX IT if it DOES NOT happen

nocturne quail
#

if the notifiy fails in any way run the timer

nova wasp
#

and you cannot detect it failing

#

so you just... always set the fallback timer

nocturne quail
#

hmm, true

nova wasp
#

and then just cancel the timer when the regular notify fires

#

of course if you have a second swap you must also cancel the existing timer etc

nocturne quail
#

genius

nova wasp
#

and for the exact timer time... try to think of a nice number that's a bit above the slowest notify case so it doesn't fire too soon

#

you could even base it off of the notify but some dumb ~ half second thing might be good enough

pseudo wagon
#

Does 3DTextActor available on dedicated server?

#
{
  "Name": "Text3D",
  "Type": "Runtime",
  "LoadingPhase": "Default",
  "TargetDenyList": [ "Server" ]
},

Nice

hollow crater
#

I am trying to move an item arround - similar to the way it is done in portal.

However using the AttachToComponent / DetachFromActor approach Desyncs all the time whenever I involve Simulating the Physics on the moved actor.

Is there a simple fix to that, or would I best do it another way / is there a certain recommended way to handle this?
(just SetSimulatePhysics(false) before attachment and SetSimulatePhysics(true) after detachment does not seem to solve this)

vital fiber
#

Alright, so i add the force on all machines version of the helicopter but the force is applied based on the servers helikopter location. Do i understand you correctly? I must also say thank you for the support so far!

kindred widget
#

My opinion is that I wouldn't approach that personally. Yet another reason why you shouldn't put stuff in the Controller. Controller should be mostly transient.

There's functionality in GameState/GameMode that keeps the PlayerState around. And if you override the right things, you can avoid PlayerState recreation so that you can just have that player repossess the Pawn associated to that PlayerState.

dark edge
vital fiber
dark edge
#

You can multicast the control value if you want or just replicate it

#

Its replicated state so I'd do that

#

You don't want to add Force every time you receive a control value, you want to add Force every tick, using the latest control value you received

#

That way everyone agrees on the inputs, the throttle and collective and cyclic. They all advance the simulation, and of course there will be some divergence there, and the physics replication system will keep everyone's result aligned with the server's result.

#

You could just run the helicopter Sim on the server and rely on physics replication to make the helicopter move around for everybody else, but that would look like dog s*** because it's not continuously smooth. And also you wouldn't have access to the Sim state for things like cosmetics and sound and other things. It'll work without running the Sim on all machines, but it'll work a lot better running the Sim on all machines.

#

Basically, between replicated physics updates you would just be falling.

tardy fossil
#

when using voip talker for a proximity voice chat, is there any way to not send voice data to players out of range? or does that need something custom

hybrid zodiac
#

Hi all, I have a bit of a complicated problem with prediction and CMC.

My character has energy which they can use to jetpack. Currently this is all synchronised in the movement ticks so that energy consumption and regeneration is always synced across each movement tick between autonomous proxy and server. This ensures no corrections are received when trying to "feather" jets with low energy etc.

I have a problem which is that energy can also be drained through firing certain weapons. I want to predict this change on the autonomous proxy, but the issue is getting it to sync nicely with the server. The main issue is that client and server can disagree slightly on exactly when the weapon was fired, and therefore when the energy was consumed. Sequence currently looks a bit like this:

  • Autonomous proxy fires weapon and deducts 10 energy during the next invocation of PerformMove in the CMC
  • Autonomous proxy sends saved move data to the server for checking
  • Server checks and thinks that 10 energy has mysteriously vanished for no reason, and corrects the client to re-add the 10 back
  • Client applies correction and refunds the 10 energy
  • Server receives the fire request and deducts 10 energy during the next invocation of PerformMove
  • Server checks the client's next saved move submission and realises that they have too much energy now
  • Server sends correction to tell the client to re-apply the -10 deduction

The issue is that this causes the player's energy to kind of flicker and spasm as it removes the energy, adds it back, then removes it again following corrections from the server

#

My plan was to have the autonomous proxy separately track predicted energy changes and not report them to the server, so internally it acts like it has 90 energy or whatever, but tells the server it has 100 energy so corrections don't come it

#

But then I would need a way for the client to remove those predicted changes once the server sends in a correction confirming that the change has been committed

#

So essentially, I need to track which saved move snapshot the predicted energy change was applied, and once a correction comes in which snapshot it was for so I can purge old predicted energy modifications

#

But when I try to call ClientData.GetSavedMoveIndex for incoming correction timestamps, it always returns -1 without exception

latent heart
#

You could have 2 energy values and then a composite value? One tracked by the jetpack for movement and one tracked by everything else. Then when you check energy it uses the composite value for "do I have enough energy?" checks. Not sure if that'd work?

hybrid zodiac
#

I was thinking of doing that, but the main problem is how can the client tell once a predicted energy change has been "confirmed" by the server so they know to remove it, so you don't have a permanent -10 energy deduction being predicted

latent heart
#

Well the server would update both numbers.

#

The extra value wouldn't just be client only.

hybrid zodiac
#

So the client sends predicted energy to the server? That would fix the problem, but could leave it open to exploitation if the client says "oh yeah, I just got this massive +100 boost to energy"

#

The idea I was having is that predicted energy is entirely local, and it waits for the server to say "hey, actually you just lost 10 energy" and then the client can say "yep, I know" and allow the server to correct their energy and remove the predicted value

near coral
#

I would not do the two numbers thing and instead sync when the weapon is fired / consumes the energy trough the networked move data. So the energy is deducted on client and server on the same movement tick.

hybrid zodiac
#

@near coral So have some extra client data submitted saying "btw I fired an energy weapon on this tick"?

near coral
#

Yeah exactly

latent heart
#

And if the server rejects that?

near coral
#

then you get corrected

#

that's what you would want right?

latent heart
#

But then you need to tie everything you do that uses energy into the cmc.

near coral
#

yeah

latent heart
#

Which is not ideal.

near coral
#

True, but Imho, it's preferential to having two seperate systems that need to interoperate

latent heart
#

I suppose you could use saved moves as a conduit just for energy checks and have the other systems reject them for the cmc if they aren't valid.

#

So the cmc isn't doing the work itself, it's offloading it to the other systems.

keen slate
#

Hey, so in the MoverExamples project there's a bunch of references to ProduceInput.
Should "input" be understood here as "a human person pressing a button", or is it more in an abstract sense that the Mover system expects "input" to simulate movement?

I'm asking because these functions (virtual ProduceInput_implementation() override, OnProduceInput(), etc.) are placed in a Pawn class which can be controlled by a human but also by an AI Controller.

#

A little more context is maybe warranted:

/**
 * MoverInputProducerInterface: API for any object that can produce input for a Mover simulation frame
 */
class IMoverInputProducerInterface : public IInterface
{
    GENERATED_BODY()

public:
    /** Contributes additions to the input cmd for this simulation frame. Typically this is translating accumulated user input (or AI state) into parameters that affect movement. */
    UFUNCTION(BlueprintNativeEvent)
    void ProduceInput(int32 SimTimeMs, FMoverInputCmdContext& InputCmdResult);
};

class MOVEREXAMPLES_API AMoverExamplesCharacter : public APawn, public IMoverInputProducerInterface { /* ... */ };
#

It mentions "AI state" here in the comment, but calling it "input" just seems very weird

obsidian cargo
#

What most commonly would prevent network connection between two computers running the game in PIE on a LAN?

I'm using Lyra as a base and was able to get connection with the same game on my home network, but the server can't be found on my work network. I was able to tracert from server to client and from client to server on the work network.

slate phoenix
#

Hello everyone, I’m developing an MMO-style farming/trading/economy multiplayer game on my own. My game will be released on Steam. I don’t have much knowledge about databases or backend APIs, so I’m not sure what to use. What would you recommend for the backend and database? I’d really appreciate your help.

slate phoenix
# dark edge How far have you gotten so far?

I’m doing research, but I don’t want to handle saving data locally because I’ll probably delete it later and switch everything to MySQL. So I’d rather do it directly with a database from the start. The problem is, I’m not sure what I should use or which option is best for me.

dark edge
#

At least farming/trading/economy isn't twitchy

#

If you design your systems right it shouldn't matter too much what your backend is.

nocturne quail
#

Any idea why GetEquippedWeapon() return nullptr in UCharacterAnimInstanceBase::SwitchToArmedState() ?

weapons array is yet not completely replicated?

void UWeaponManager::ServerSetWeapon(AWeapon* NewWeapon)
{
    if (!NewWeapon)
        return;

    NewWeapon->SetEquipState(EWeaponEqupState::Equipped);
    WeaponStack[0] = NewWeapon;

    AttachWeapon(NewWeapon);

    OwningCharacter->SetPlayMode(NewState == EWeaponEqupState::Equipped ? EPlayMode::Armed : EPlayMode::UnArmed);
}

void ACharacterBase::SetPlayMode(const EPlayMode NewPlayMode)
{
    PlayMode = NewPlayMode;
    OnRep_PlayMode();
}

void ACharacterBase::OnRep_PlayMode()
{
    if (!CurrentAnimInstance)
        return;
        
    CurrentAnimInstance->SwitchToUnArmedState()
}

void UCharacterAnimInstanceBase::SwitchToArmedState()
{
    AWeapon* Weapon = WeaponManager->GetEquippedWeapon(); // <------- this returns nulptr
}

AWeapon* UWeaponManager::GetEquippedWeapon() const
{
    for (AWeapon* Weapon : WeaponStack)
    {
        if (Weapon && Weapon->IsEquipped())
        {
            return Weapon;
        }
    }
    return nullptr;
}
#

on server its not nullptr

dark edge
nocturne quail
exotic wasp
slate phoenix
exotic wasp
#

or is it one master server?

dark edge
#

Yeah is it MMO-style or an MMO? What's the most similar project that people would have heard of?

exotic wasp
#

regardless you should store data wherever the server is

#

a database of sorts might give some benefit if you have lots of players on a single master server but that's honestly complex enough to be out of scope for a discord message, imo

thin stratus
nocturne quail
thin stratus
#

Yeah, so the actor hasn't yet replicated to the client when the playmode arrives.

#

Common thing with multiplayer.

quasi tide
#

If the server is spawning it - why would it be calling a server rpc to set it?

nocturne quail
#

ServerSetWeapon is not rpc

quasi tide
#

Okay

thin stratus
#

Yeah was just about to say. Doesn't mean Missty prefixes RPCs with Server. Could just be a way of quickly seeing that a function is only called on the server.

#

I used to put a comment above my implementations for that stuff, to quickly see what is running where.

slate phoenix
#

So it won’t be like a listen server. When a player creates a room, it won’t be something that everyone joins and then gets deleted when the player leaves. If a player creates a world, it should stay in the database because they might have a farm inside it.

exotic wasp
#

but will players host this "single server" that other players then join?

#

because my immediate thought if that's not the case is some sort of custom backend

slate phoenix
nocturne quail
#

just to quickly see this is called by server

exotic wasp
#

you probably need a very custom networking solution then

#

ue5 has no support for multiple worlds at the same time iirc

slate phoenix
#

In MMO games, players can’t host their own servers. What you described is for P2P games — create a room, play, then leave. In an MMO, there is no room-creation system like that.

quasi tide
#

It's not necessarily a P2P game

exotic wasp
#

^ ue5 is not p2p

nocturne quail
# thin stratus Yeah was just about to say. Doesn't mean Missty prefixes RPCs with Server. Could...

now compiling this, to make it sure the actor was replicated late

void UCharacterAnimInstanceBase::SwitchToArmedState()
{
    AWeapon* Weapon = Character->GetEquippedWeapon();
    if (IsValid(Weapon))
    {
        ProcessWeapon(Weapon);
        return;
    }

    UE_LOG(LogTemp, Warning, TEXT("[SwitchToArmedState] Weapon not found. Scheduling retry..."));

    FTimerHandle RetryTimer;
    GetWorld()->GetTimerManager().SetTimer(RetryTimer, [this]()
        {
            UE_LOG(LogTemp, Log, TEXT("[SwitchToArmedState] Retry attempt..."));
            SwitchToArmedState();
        }, 0.1f, false);
}
exotic wasp
#

also if you haven't considered the MMO portion of your game yet it is probably not 60% done...

slate phoenix
# quasi tide It's not necessarily a P2P game

Did you even see my question? Did I say it wrong, or did you not understand? I only asked for a database and backend recommendation. When I asked other AIs, they recommended MySQL and Node.js Express.

exotic wasp
thin stratus
slate phoenix
quasi tide
exotic wasp
#

pretty much any dbms is fine... it all depends on what you write your backend in and if you can have good interop with the engine

thin stratus
#

Peeps, I feel like this will soon stop being a civil discussion.

exotic wasp
#

yes

keen slate
# exotic wasp I believe in an abstract sense. there shouldn't be any different in how AI and p...

I just tried to copy/paste all the "ProduceInput" code from the MoverExamples plugin into my own Pawn class, and Lo' and Behold - it works!

The conclusion seems to be that Mover is designed such that moving entities must implement the IMoverInputProducerInterface interface, and then produce whatever they desire.

Also using NPP Mover, and for my simple use case it works fine though client prediction seems to be quite rough (like the movers quite often just teleport when there's too much network traffic i.e. too many movers). But I can still have more moving entities than with CMC.

dark edge
#

Microsoft Access and raw TCP

exotic wasp
#

all dbms effectively accomplish the same goal

dark edge
#

CockroachDB, for when your virtual farm has to survive a nuclear war

nocturne quail
slate phoenix
thin stratus
thin stratus
quasi tide
#

Isn't it time to walk your dog Cedric?

thin stratus
thin stratus
quasi tide
#

That's not true. I don't have a treat.

slate phoenix
dark edge
#

Ballpark how hard is it to run Unreal as standalone and have some networking with a backend of some sort. Basically single player with custom networking?

nocturne quail
dark edge
#

Say you were making Dark Souls but only wanted the soapstone mechanic

exotic wasp
#

probably not that bad

#

would be no different from any other web service

quasi tide
#

UE supports calling rest APIs - so, it's already supported.

thin stratus
#

Right now you expect the Weapon to be available if the playMode replicates.

#

But it's the other way round (not guaranteed!)

#

So you have to handle that case too.

thin stratus
nocturne quail
#

Ok, I think I got it how to do it, trying it now

thin stratus
#

In theory, UE has that PlayerState stuff already built in.

#

Not sure about re-possessing the pawn, but that might be trivial if you store your own pointer to it on the PlayerState.

#

The GameMode has a setting for keeping the PlayerStates alive.

#

And OnOverrideWith on the PlayerState can be used to transfer data on reconnect.

#

High connectiontimeout?

#

That sounds pretty wrong.

#

Yeah noooo

#

Just use

/** Time a playerstate will stick around in an inactive state after a player logout */
UPROPERTY(EditAnywhere, Category=GameMode)
float InactivePlayerStateLifeSpan;

/** The maximum number of inactive players before we kick the oldest ones out */
UPROPERTY(EditAnywhere, Category = GameMode)
int32 MaxInactivePlayers;
#

Properties of the AGameMode

#

In theory, yes.

#

When the player reconnects and you have an online subsystem that has a unique player ID

#

It will match the connecting player to an inactive playerState

#

Should happen automatically. But again, only if you have unique Ids.

#

Like using Steam for example.

#

Puh, mobile isn't really my ballpark

#

I think on anything but Desktop (which your Server will be though) it would match by NetworkAddress.

#

Nope, that doesn't exist.

#

You'd need some OnlineSubsystem that provides you with a unique ID.

#

Maybe check out Epic Online Services (EOS).

#

Should be free and supports crossplatform. Maybe that can handle your DedicatedServer + Mobile Client case.

#

(Doesn't host servers!)

#

It compares the UniqueNetId, which is tied to the OnlineSubsystem.

#

Which is why I already said that that's needed.

#

That might be possible, assuming you work in C++.

#

FindInactivePlayer is virtual, so you could override that and use the name instead if that's fine with you.

#

No worries.

vital fiber
dark edge
thin stratus
#

It's not really the right way.

#

Like, this isn't meant to keep your PlayerState alive, but is meant to allow x seconds before a connection times out if the person lost connection or are lagging.

vital fiber
dark edge
#

the coefficients and error per linear distance etc

vital fiber
#

is it the physics prediction?

dark edge
#

btw that typo has been there for like 10 years lmao

vital fiber
#

hahaha

#

they're just the default ones rn ofc

dark edge
vital fiber
#

i do want it to stay the same and be very synced for all players becuase it is such an important gameplay object (the physcis simulating helicopter)

dark edge
#

What engine version are you on?

vital fiber
dark edge
#

I wonder why my settings page looks different. Anyways, that's the settings I'm using and I get perfect sync

thin stratus
#

I shall write this down once more.

  • ConnectionTimeout is meant to define the time until a connection counts as "timed out" in case the client lost connection unwillingly.
  • Keeping PlayerStates alive is done through the AGameMode properties.

And then additionally:

  • Keeping the Pawn from being destroyed is done by overriding that part in the PlayerController.
#
void APlayerController::PawnLeavingGame()
{
    if (GetPawn() != NULL)
    {
        GetPawn()->Destroy();
        SetPawn(NULL);
    }
}
vital fiber
thin stratus
#

Override it and don't call super. Tada, pawn survives. Maybe set the pawn to null still fwiw. Or store it on the PlayerState if that's still valid at that point on the PC. Then you can easily find it again with the PlayerState.

dark edge
#

it smoothly pushes it towards the replciated state

#

and if it stays too far away too long, it hard snaps

vital fiber
#

ahaaaa so the hard snaps is what the console command visualised

#

i see

vital fiber
#

ill just try tweaking some values and see what works

#

thanks again for everything

nocturne quail
#

this fixes the issue

#
    // Set the state
    NewWeapon->SetSlot(Slot);
    NewWeapon->SetWeaponState(NewState);
    NewWeapon->bFlashReplication = !bFlashReplication; // this does the trick
    WeaponStack[Slot] = NewWeapon;

    AttachWeapon(NewWeapon, Slot);

    OwningCharacter->SetPlayMode(NewState == EWeaponEqupState::Equipped ? EPlayMode::Armed : EPlayMode::UnArmed);
thin stratus
#

(: I would say that's a good opportunity for you to just open the header of the PlayerState and look.

fluid prawn
#

obscure question. With multiple pie clients do they have unique client IDs in the package map or no? It is just tested

dull ginkgo
#

Hi everyone,
I want to learn multiplayer development in Unreal Engine 5 from scratch. Could you please recommend any good resources that would be helpful for a beginner?

mental fossil
#

hey, in dedicated servers, if the caller doesn't own the world actor, which class do I call from to affect the world actor (like enabling physics)?

#

I asked the AI but it crashed during reasoning

mental fossil
#

I'm just going to spawn them properly so I can set the owner

mental fossil
frosty harbor
#

For people messing around with multiplayer, how are you guys dealing with high ping scenarios? When testing network latency (100 MS both client + server) there's a very significant time between when I click & when the animation actually starts, I can't seem to figure out a way to optimize it further. My GAS combo/abilities are replicated, Instanced per actor & local predicted. I have an input handler to separate taps from holding for charged attacks, and for some reason with high latency the game always detects a hold even after I released the left mouse button.

thin stratus
thin stratus
thin stratus
# frosty harbor For people messing around with multiplayer, how are you guys dealing with high p...

For one, Abilities should probably not be replicated. The replication of them usually happens outside of them.
For example, The Ascent has 0 replicated GameplayAbilities.

High Ping scenarios that feel like the local client is waiting on the initiated action to come back to them is lacking prediction.
Game detecting a hold even after you released the key sounds like a different problem to me.
Or you are doing something with the press/hold and the server that is wrong.

frosty harbor
# thin stratus For one, Abilities should probably not be replicated. The replication of them us...

Well I sort of had to turn on replication for them because I use animation notifies to trigger gameplay events to trigger different things during the animation montage (IE: When to release the hold, when to start stamina drain, etc) andif I didn't run some of these things on server, it wasn't replicating properly for everyone else (and to run it on server the gameplay ability required me to replicate it) it's the screenshot from the other day. This is my base combat ability

thin stratus
#

(and to run it on server the gameplay ability required me to replicate it)
The Ability will be triggered on the Server anyway if it's predicted.
Any stuff that the Client has to tell the Server, which is usually just related to Input, has custom replication paths in the AbilitySystemComponent.
The Ascent was also a Multiplayer project. Sending RPCs in the Ability is the best way to break the Prediction Window.

#

Every single one of your WaitGamepalyEvents breaks the Prediction Window too.

#

You usually recreate that afterwards with a NetWaitSync(OnlyServer).

#

The bottom most WaitGameplayEffects has a SwitchHasAuthority that goes into a ServerRPC, which doesn't really make sense.

#

But all good, if you already comitted to replicated abilities, then that's that.

frosty harbor
thin stratus
#

All of this has no valid Prediction Window anymore.

nova wasp
#

you cannot predict removing effects

#

but you can predict adding new ones that kinda negate them

frosty harbor
thin stratus
#

It's WaitGameplayEvent actually, misread, but the problem is the latent node itself, not which one.

#

I'm not really sure what else to suggest at the moment, because the way you structured all of this is way different than whatever I have ever done with GAS. Not a single time did I have the need to replicate an Ability and iirc Epic isn't even too happy about that feature.

frosty harbor
nova wasp
#

and yeah it is a giant footgun to replicate an ability that is super unintuitive

#

you pretty much never want to do that imo

thin stratus
#

The Prediction Window is basically a "Scoped" in which the Client has a valid Prediction Key.

nova wasp
thin stratus
#

There are several functions in native GAS that make use of that, such as applying an Effect.

nova wasp
#

we cannot see what is happening, we can only see what you show us

thin stratus
#

Or adding/executing a Gameplay Cue.

nova wasp
#

when you say "something is broken" we have no context for what happened and what you wanted to happen

thin stratus
#

In Blueprints, that "Scope" sits around the White Wire that starts at Activate Ability.

frosty harbor
thin stratus
#

If you use a Latent Node, only the top wire of that node is still "in Scope".

nova wasp
#

the immediate calls in the current callstack so to speak then

thin stratus
#

If you need the Prediction Window after a latent node, you need to use WaitNetSync to recreate it.

#

The Scope also survives if you simply call an event from that same Exec Wire, so it doesn't all have to be one large chain.

#

But the Server/ClientRPCs will happen "some time later" due to ping, so there is 100% no Prediction Window available anymore.

#

You basically, more or less, completely f'd the need for the Ability to be predicted with this.

nova wasp
#

even if this wasnt in a prediction context more rpcs = more random stuff it might not arrive in the same frame

thin stratus
#

Yeah, but the initial question was about prediction and some delay they felt that shouldn't be there.

#

So that's why I focus on that specific thing being utterly broken with their current setup.

nova wasp
#

yeah, not discounting anything you said

thin stratus
#

I fully understand why one would dip into turning replication on and sending RPCs.

nova wasp
#

just general advice about stuff I have had to overhaul in realtime game networking given how fickle replication timing is

thin stratus
#

But it's a trap basically.

nova wasp
#

yeah I see why you would want to given nothing else working, not saying it was a bad idea

#

GAS is insanely tough to figure out

thin stratus
#

I think the important thing to learn here is "How can I do the things that I needed the extra RPCs for with what GAS already offers?".

nova wasp
#

true

thin stratus
#

There should be some nodes that allow sending data to the Server, which will wait on that if it encounters the same node.

#

Not sure if that's only TargetData, but even that can be "abused" for a lot of stuff if needed.

#

There should also be some generic "Input Pressed" node, that the Server can use, but it's more or less locked to a single Input, as it's just a boolean that gets flipped.

#

But 99% of a time, that input being just one key is enough for an ability.

#

Does require the C++ side to be set up properly to set that boolean, however. If you use Lyra or something similar as a base, it should be though.

#

Basically the ASC already has a bunch of Systems with RPCs that you can use to do most of the stuff you need.

frosty harbor
#

Wtf, it wasn't working before I swear to god 💀 i spent hours testing stuff and it just wasn't working to remove the effect but I guess now it is somehow?
I should probably rebuild the c++ files surely this cant be right

nova wasp
#

I am still correct that you can't predict removal ahead of time, right? that was still true last I had to deal with this in ~2023

thin stratus
#

Most of the above code will happen on Server and Client, after all.
If the Server runs whatever will in the end trigger those "WaitGameplayEvent" stuff, then this will all "just work."

nova wasp
#

they could have added this and I would have noidea

thin stratus
#

However, the "RemoveEffect" stuff, even if called on Server and Client, will be denied on Clients and just "fail silently."
The Server will execute it though and the rest will "just work" again.

#

So there is no prediction on Removal. And maybe not on Stacking (not sure if that is patched by now).

frosty harbor
thin stratus
#

All good, next time you have a replication issue with GAS where you need something to happen on Server/Client properly, with prediction and what not, just go to #multiplayer or better #gameplay-ability-system and ask.

#

GAS is one of those things if you start using it wrong and you over-commit into a shitty setup, you are as lost as Anakin.

frosty harbor
#

lmao

#

Appreciate it, I really wanna learn these things the right way

nova wasp
#

also if all else fails there's nothing stopping you from trusting the client for stuff that tends to be difficult to make work well with GAS prediction (movement etc) (for a co-op game with no cheating concerns)

frosty harbor
#

gonna get this rebuilding and gonna scroll up to read everything again

thin stratus
#

Speaking of the "right way", to make things more entertaining, there is no "one right way" for a lot of stuff in GAS either :D

#

In theory, GAS and its predicted Abilities follow the same rules as normal Multiplayer.

  • Server has Authority.
  • Only send data/events to the Server that the Server can't know about.
    • E.g., the Mouse Location when targeting in a top down game. This would be one of those things where someone would fall back to an RPC, not realizing that the Target System already has GAS nodes for this that let the Server wait on the Data when it hits the node and handle the ServerRPC in the background for you.

You can picture the Activate Ability flow like a duplicated hallway, where Server and Client walk along.
They encounter the same nodes/things, but some of them need either of them to do something different and some of them have a connection between the hallways. E.g., Server encounters the WaitTargetData and.. waits. Client encounters the WaitTargetData and generates TargetData, then sends it to the Server, at which point the Server continues with the execution, now having the same data.

#

The Prediction Window would be a lot simpler to understand in C++, because there you can't just jump between Functions so easily without actively leaving the Scope of the function.

#
void USomeAbility::OnActivate()
{
  FPredictionWindow Scope(..);

  // Client has a valid Prediction Key as long as we stay within the { } Scope.

  // Function is called within this scope, so all good.
  SomeFunction();

  // Function gets called "later" in a different scope.
  TimerManager.SetTimer(10.f, this, &ThisClass::SomeLatentFunction);

  // The actual function isn't called until "later" and not on the same machine anyway.
  // *Probably some edge case where a Server calls a ServerRPC, which acts like a normal function, but who knows.
  SomeRPCFunction();
}

void USomeAbility::SomeFunction()
{
  // We still have a valid Prediction Key, cause we are still within the outer scope.
}

void USomeAbility::SomeLatentFunction()
{
  // When this calls, the scope of OnActivate is long dead, so no Prediction Key/Window here.
}

void USomeAbility::SomeRPCFunction()
{
  // Definitely no Prediction Key here anymore. This calls somewhere on the Client/Server and is not within the initial scope anymore.
}
#

No Prediction Window => No predicted GameplayEffects (Add), GameplayCues, and probably tons of other stuff.

nova wasp
#

is there a way to have it assert when this occurs?

thin stratus
#

Don't think there is anything built in.

#

In your own functions/nodes, you could potentially write something that checks if the ability is set to predict, the execution is on the client and if a valid prediction key is available.

#

But there is always some edge case where you might be doing this on purpose.

frosty harbor
# thin stratus Every single one of your WaitGamepalyEvents breaks the Prediction Window too.

Coming back to this, so how would I run my current code if WaitGameplayEvents completely breaks the prediction window? It still shouldn't be the reason why the attacks start so delayed instead of instantly or near instantly regardless of ping no? Because these wait gameplay events is pretty much how I'm telling the client/game that the user actually released their mouse button, to proceed with the ability, or that the user actually clicked inside the "combo window", etc

thin stratus
#

In Blueprints is really annoying to keep track of this, cause the { } are basically the Exec Wires.

nova wasp
#

could you kinda just store the prediction key off? does it change with the scope?

thin stratus
# frosty harbor Coming back to this, so how would I run my current code if WaitGameplayEvents co...

I don't 100% know how the attacks get started. You originally wrote something about Hold Inputs being broken.
You need to see that if the Client encounters a GAS node that is supposed to predict something and it has no valid prediction key, it won't execute it.
Eventually the Server will hit the same node, and that doesn't require a prediction key. Whatever that node is doing will then be replicated and the client will handle it as if they didn't predict it.

nova wasp
#

I have cheesed stuff with the prediction key in the past, but mostly for RNG stuff (not latent things as much as just choosing the same thing on both sides etc)

thin stratus
#

An example would be a GameplayCue that spawns an Effect.

#

If you break the Window, the effect will replicate down to the client and execute from replication.

#

If you keep the Window alive, it will be predicted and skipped when it's received later on.

#

Let's give a small example. Let's say you activate the Ability and play a Montage on the Character. The Montage is going to play on Server and Client.
After that PlayMontage node, you call WaitGameplayEvent. The GameplayEvent is triggered by some AnimNotify (I don't want to diverge, but this is actually a shit thing to do, cause AnimNotifies are super unreliable). Now after the Event is receceived, you want to play a Sound via a GameplayCue.

#

If you don't recreate the Window, the Sound will play "later" and not match the Montage timing, because the Client gets the predicted Cue denied and simply gets it later from replication.

#

So in that case, after the Event got received, you'd add a "WaitNetSync" with, iirc, "Only Server Wait" or whatever it is, and then call the Cue.

#

From the latent pin that is, no from the top one.

#

Reason why that fixes it is that WaitNetSync does two things:

  1. Let's the Server (in this case) wait on the Node for the Client to send an RPC in the background to tell the Server they are back on track.
  2. Create that FPredictionWindow once more before triggering the latent pin.
#

And due to 2. you have a valid Prediction Window/Key again.

#

If you want to understand this and try it, rebuild the setup I just explained and try it with and without the WaitNetSync and set up some really high latency. like 200+ ping in/out both sides.

frosty harbor
#

damn thats confusing not gonna lie, gonna have to try and replicate that to try and understand it better

nova wasp
#

the whole point is to have this atomic thing that says "undo this" if the server rejected the activation, right?

#

the whole point of GAS is to kinda hide this from designers making ability BPs and effects

#

or at least make it vastly easier than rolling your own (generic client prediction)

frosty harbor
thin stratus
#

TryActivateAbilityByTag should work just fine if it's predicted. But it depends a bit on what this whole previous flow is about.

#

There is a world where you can have a local ability, that never runs on the server, and that does some stuff that isn't needed to be authoritively(?) handled, which then calls TryActivate for a predicted Ability.

#

That TryActivate then causes a ServerRPC internally etc.

nova wasp
thin stratus
#

If you, however, already are inside a predicted Ability, then I'm relatively sure any "new" ability you trigger from it doesn't necessarily need to be set to predict, as it will be activated on both sides anyway. It might need a prediction window around it, otherwise it might decline the Client.

#

Which means, in your shared code, if that function is called from some latent code, like a timer, or some "later" callback, you don't have a prediction window anymore.

#

And that TryActivate call might only happen on the Server and the Ability will act as if the Server initiated it, and replicate the activation back, introducing latency.

#

Although the shared code looks like it's not even within an Ability.

#

So there you'd just have the ability be predicted and that code would only run on the client.

nova wasp
#

is this not an ability?

thin stratus
#

I mean the C++ one

nova wasp
#

ah sorry

thin stratus
#

Not sure about the whole Tap vs Hold part. That feels like an EnhancedInput "problem" more than anything else.

frosty harbor
#

yes that's not an ability just an input handler

#

the bp one is the base ability yea

nova wasp
#

HasMatchingGameplayTag would still resolve okay if the tag was predicted being added locally, right?

thin stratus
frosty harbor
#

It really is confusing not gonna lie, even when trying to ensure everything I'm doing is locally controlled to test & to ensure it for sure only runs on client the animation still starts delayed when I emulate network latency.

#

It does feel a bit better after some tweaks I did but could be placebo lol, it's still nowhere near as responsive as I'd like

dark parcel
#

if animation is predicted (executed locally), you shouldn't have any delay.

#

0 or 1000 ms

frosty harbor
#

Yep

#

I can't seem to figure out why even though I've added "islocallycontrolled" checks everywhere I can think of related to input handling

#

also on the ability side of things

dark parcel
#

How do you execute the montage / animation?

vocal current
#

That can lead to running the montage in a way that isn't locally predicted and you'll get a delay under poor net conditions

meager spade
#

speaking of local cues

#

i exposed a couple of things and some tracking

#

to add non replicated cues and execute non replicated cues

#
void UKaosAbilitySystemComponent::ClearAllNonReplicatedCueTags()
{
    for (const FGameplayTag& Tag : NonReplicatedCueTags)
    {
        UGameplayCueManager* GameplayCueManager = Cast<UKaosGameplayCueManager>(UAbilitySystemGlobals::Get().GetGameplayCueManager());
        GameplayCueManager->RemoveGameplayCue_NonReplicated(GetAvatarActor(), Tag, FGameplayCueParameters());;
    }
    NonReplicatedCueTags.Empty();
}

void UKaosAbilitySystemComponent::AddNonReplicatedCueTag(const FGameplayTag& CueTag)
{
    NonReplicatedCueTags.AddUnique(CueTag);
}

void UKaosAbilitySystemComponent::RemoveNonReplicatedCueTag(const FGameplayTag& CueTag)
{
    NonReplicatedCueTags.RemoveSingleSwap(CueTag);
}```
#

void UKaosGameplayCueManager::AddGameplayCue_NonReplicated(AActor* Target, const FGameplayTag GameplayCueTag, const FGameplayCueParameters& Parameters)
{
    if (UKaosAbilitySystemComponent* ASC = Cast<UKaosAbilitySystemComponent>(UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Target)))
    {
        ASC->AddLooseGameplayTag(GameplayCueTag);
        ASC->AddNonReplicatedCueTag(GameplayCueTag);
    }

    if (UGameplayCueManager* GCM = UAbilitySystemGlobals::Get().GetGameplayCueManager())
    {
        GCM->HandleGameplayCue(Target, GameplayCueTag, EGameplayCueEvent::OnActive, Parameters);
        GCM->HandleGameplayCue(Target, GameplayCueTag, EGameplayCueEvent::WhileActive, Parameters);
    }
}

void UKaosGameplayCueManager::RemoveGameplayCue_NonReplicated(AActor* Target, const FGameplayTag GameplayCueTag, const FGameplayCueParameters& Parameters)
{
    if (UKaosAbilitySystemComponent* ASC = Cast<UKaosAbilitySystemComponent>(UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(Target)))
    {
        ASC->RemoveLooseGameplayTag(GameplayCueTag);
        ASC->RemoveNonReplicatedCueTag(GameplayCueTag);
    }

    if (UGameplayCueManager* GCM = UAbilitySystemGlobals::Get().GetGameplayCueManager())
    {
        GCM->HandleGameplayCue(Target, GameplayCueTag, EGameplayCueEvent::Removed, Parameters);
    }
}

void UKaosGameplayCueManager::ExecuteGameplayCue_NonReplicated(AActor* Target, const FGameplayTag GameplayCueTag, const FGameplayCueParameters& Parameters)
{
    if (UGameplayCueManager* GCM = UAbilitySystemGlobals::Get().GetGameplayCueManager())
    {
        GCM->HandleGameplayCue(Target, GameplayCueTag, EGameplayCueEvent::Executed, Parameters);
    }
}
#

you can then expose them as statics

#

(as they are static)

#

then bp can execute/add/remove cues non replicated

lament flax
#

In this session recorded at Unreal Fest Stockholm, CCP Games presents a server-side system they’ve dubbed “Fog of War” that stops wall hacks at the source by ensuring clients only ever receive what their player should legitimately know. No line of sight? No data. No exploit.

CCP walks through the problem, shows how they solved it for EVE ...

▶ Play video
#

from EVE Vanguard (not released yet)

nova wasp
#

one of the confusing things about the way cues work imo is that there's no straightforward way to just grab active ones and reason about them

#

I guess epic never needed to

mystic estuary
#

Hello, I'm using Predictive Interpolation for physics replication, but I disable movement replication when the actor is carried or put in a pile as there's no physics going on.

However, when I try to move the actor using SetActorLocation with no movement replication, it's inconsistently trying to use prediction I'm not asking for. The last replicated pot position was on the table next to the pile, but it was taken and put in a pile. Then, when I try to take it from the pile, it's doing SetActorLocation towards a socket in front of the character, but usually it teleport the pot to last replicated position, and only sometimes it does what I expect it to do, which is interpolate it from the pile position. I have my own interpolation when it's supposed to get in front of my character.

So, when pot is not carried or not in the pile, it's simulating physics, has collision and replicates the movement. When it's carried or in the pile, it only has collision, so no physics and movement replication.

Does anyone know how to deal with it?

nova wasp
#

are you turning off transform replication locally?

mystic estuary
#

I just realised that there's some race that makes client enable Replicate Movement for a frame or something. Currently trying to debug it

nova wasp
#

breakpoint SetReplicateMovement

#

and OnRep_ReplicatedMovement

mystic estuary
#

Apparently it's related to my internal structure. I have a Capture Component that wraps up attaching logic between different things, and when I try to start carrying the pot, it tells me that the pot is no longer attached, so it starts simulating physics and replicate movement, but some frames after the component responsible for carrying gets the carrier replicated, which makes it disable physics and stop replicating the movement, but at that point the harm was done, and it has teleported it to what it previously knew

#

But sometimes the carrier gets replicated faster, making it behave correctly

nova wasp
#

given they are separate objects the order is entirely random

mystic estuary
#

Yeah, I get that

nova wasp
#

I do not undersatnd "it tells me that the pot is no longer attached"

#

so it locally does this?

mystic estuary
#

I have a component that tells me what I'm attached to along some other things. In the OnRep, I do Attach/Detach actor locally. I kinda forgot that they're already replicated in the AActor

nova wasp
#

the carrier thing overriding what picking it up does seems like an issue

mystic estuary
#

Shouldn't be, since it usually gets replicated after the detach + SetReplicateMovement to true

#

lemme grab some timings

nova wasp
#

hard to say what I would do without context if it's okay to predict this (if it misses would it be weird? I don't know)

#

I think you could probably cheese predicting the state of the picked up actor and have it not care about the carrier thing at all

#

also bReplicateMovement is a replicated variable

#

but

#

OnRep_ReplicatedMovement is virtual

#

this means you can basically tell unreal "actually I don't care lol" about incoming onreps to this and whatever you damn well please

mystic estuary
nova wasp
#

so if it's in this in-between state you can ignore the onrep until the pair are settled

mystic estuary
#

(the 139 on the left is the frame)

mystic estuary
#

I'll try that

nova wasp
#

OnRep_AttachmentReplication calls this onrep manually

#

notably ACharacter overrides this (ACharacter::OnRep_ReplicatedMovement) which it does something very similar to what I suggested: it just early outs if it is doing something where it wants to ignore the replicated value

mystic estuary
#

I see, but if it's set to false, it won't call it, no?

mystic estuary
#

oh, I see

mystic estuary
#

Will try to play around and see whether that's the case

#

Looks perfect so far

#

I guess I'll roll with that

nova wasp
#

my other dumb idea would be to basically manually change the offset of the static mesh to make it appear that it's in the right place but have that actually be mostly visual (similar to ACharacter interpolating the mesh but the root jitters a LOT in comparison)

#

at least temporarilly

mystic estuary
#

Sounds very annoying

nova wasp
#

yeah it would be a fair bit of math lol

mystic estuary
#

True

nova wasp
#

but it could be useful if changing the "true" position is undesirable on the client I guess..... faking this in-between state might not be okay if the idea is the pot actually hits stuff on the way there though so idk

mystic estuary
#

Yeah, that sounds nice, but I hate fighting unreal 😔

#

Also that seems to fix this

nova wasp
#

also it is possible to entirely replace the way movement onreps work with more overrides if you need truly atomic replication of the position + state

#

but that's a bit more involved

mystic estuary
#

Sounds like it

#

Alright, that seems to fix multiple issues without breaking anything, thank you very much 😄

nova wasp
#

I'm still not sure what was causing it to pop over from this but I assume it's re-applying the onrep somehow (from attachment replication?)

mystic estuary
#

I believe it adds it back to some physics replication prediction locally, and it uses whatever state it had replicated previously, even if it's very old, and forces that

nova wasp
#

interestingly OnRep_ReplicateMovement has a unique path for when it is predictive interpolation

#

it calls RemoveReplicatedTarget if it's not replicating anymore

mystic estuary
#

Yeah, I've seen that, but it only removes them

#

That shouldn't add for case when it's true

#

Most likely it adds it elsewhere ig

#

Seems like it does that in void AActor::SetFakeNetPhysicsState(bool bShouldSleep) and void AActor::PostNetReceivePhysicState()

nova wasp
#

yeah not sure how physics replication interacts here honestly, I could be unaware of it changing this in some other path I have no clue about

mystic estuary
#

Same

#

But as long as it works I'm good

nova wasp
#

does it have a delay to reaching your hand now?

#

it might be that's totally fine at 120ms or something

#

I think this is something that doesn't need to be instant if it's slower and not done a lot over and over

mystic estuary
nova wasp
#

I mean if it has a visual difference from network delay vs before

mystic estuary
#

Server-side it never tries to simulate physics or replicate movement when I'm taking it off a pile, it only was doing that client-side because of random replication order.

Right now it works the same way it does in standalone/single player, but obviously with that delay for the interaction to get approved by the server

frosty harbor
#

I'm having an issue with making my own locally predicted combo system. The way it works is that I have a data asset for each combo ability & their step + event required to trigger them then I have a combo ability which is basically like some sort of coordinator for when to begin the attack abilities themselves.

Basically:
-> Combo begins by activating combo ability which sends the first attack event IE: "Combat.Ability.Attack.A"
-> Attack montages have a anim notify in them called "Combo Window" which notifies the coordinator (combo ability) that the user is within the combo window, if the user clicks during the combo window being open the attack transitions to the 2nd step.
-> Cancels current montage -> Sends event for 2nd step "Combat.Ability.Attack.B"
-> Repeats the process until combo is over.

The issue I'm having is that if I spam clicks, sometimes the attack reverts back to a previous attack for some reason. IE: 2nd attack combo window opens, I click a bunch of times, 2nd attack cancels, 3rd attack animation begins, for some reason 3rd attack animation gets cancelled, 2nd attack animation begins again, 2nd attack finishes, moves to 4th attack in combo and skips 3rd.

Any clue what could potentially be causing this issue?

open wave
#

my ai seem to be very glitching in their rotation on multiplayer yet when in single player they are fine nice and smooth. I tried turning the network smoothing mode to linear but i have an aging system and it breaks the height part

chrome onyx
# frosty harbor I'm having an issue with making my own locally predicted combo system. The way i...

Print screen/log debugging might be helpful here. A few things I think you might be running into:

  1. anim notify start/end order can get a little weird when blending between montages - you might want to log when the notify start and ends are happening to see when you expect them to.
  2. not sure exactly how the system works, but you might want to ensure that the server isn't cancelling/queuing up its own changes or something like that
#

Anim notifies and montage boundaries are kind of sensitive, if you're doing any kind of montage listening, you'll want to double check what montage is blending out/etc

chrome onyx
#

The built in unreal "replicate movement" is kinda meh

#

Outside of character movement at least

frosty harbor
# chrome onyx Print screen/log debugging might be helpful here. A few things I think you might...

I would send you my combo file but its a little over 300 lines u prob dont wanna bother with that lmao. But I think it's related to #2 because if I start as server it does not happen at all, only when I'm the client. I'm guessing that since i'm locally predicting things client is significantly ahead of the server due to the latency simulation so by the time the client reaches attack #3 the server is still half way attack #2? Not sure

chrome onyx
#

yeah - like it really depends on the type of game, but if cheating isn't an issue (pve, etc) I'd recommend having the client exclusively drive the logic

frosty harbor
#

Well cheating will be an issue haha thats what makes things hard

chrome onyx
#

I tend to use a "networked montage component" that does prediction/replication for montages, driven by the owning client

#

hmm

#

okay well you probably still want to have one source drive the choices of what happens - maybe more of a "client lead/server validated" approach

#

ie server can decide if a client's request was bad or whatever and deny it, but otherwise just lets the client lead

#

I know that's vague, but it'll be tough if both client and server can drive behavior

ashen plume
#

with cmc, theres a problem with my default player acharacter not detecting short physics volumes, the character seems to need to be fully submerged before being detected anyone else have this issue?

frosty harbor
#

For something like sheathing weapons (play animation + turn weapon invisible basically) do I just run it locally and then call a server RPC after running it locally to validate the change or how would it work? The reason im asking is because right now I have a sheathing gameplay ability which is local predicted, it plays montage and calls server rpc from playercharacter to hide the weapon mesh & flip a couple variables. The issue with doing that with full server validation is that with high ping the animation plays but the weapon will still be in the hand then suddenly vanish when the server finally confirms.

#

Was thinking of running it locally then running it on server but i wonder if that'll cause more issues or is simply not the correct way to do things

latent heart
#

What we do is assume everything is fine until the server says otherwise. E.g. you can sheath the weapon and take it out of your hand locally, but if the server says "nope" then it resets that action.

frosty harbor
chrome onyx
#

Yeah usually I do:
(On local client)
Start action (play montage, etc)
Send request to server

(On server)
Validate
If success, start action (play montage, etc), send confirmation to client if required, multicast to other players
If fail, send fail to client

frosty harbor
#

unless theres a variable of some kind and Im just checking it non stop

latent heart
#

Have a response RPC

chrome onyx
#

Could send some kind of Id for the request so you know which one failed

frosty harbor
#

hmm will look into it thank you, still not super sure on how ill do the rejection update/correction but surely its not too hard and im just not getting it yet

latent heart
#

You don't necessarily need an Id. The server could just say "request failed, equip weapon X"

#

(Where X is the one you attempted to unequip)

chrome onyx
#

Yah just a client RPC that says "action failed" and some kind of identifier

#

I like an id cause it's very explicit - like if you have two actions queued up and the second failed, you wanna make sure it fails the right one

#

But that's more nuanced, at the core it's pretty simple

latent heart
#

Yeah. We use a synced server time to id messages / order them. If a message is rejected, the estimated server time used to send it is returned as the id.

#

(with some additional logic to prevent duplicates)

frosty harbor
#

And in the correction rpc that you send to the owning client, you basically just do the opposite of whatever it is that it did locally I guess?

IE:
-> Sheathes weapon -> Removes weapon gameplay abilities

Server rejects it:
-> Weapon becomes visible in players hand again(basically changing visibility setting back locally) -> Give gameplay abilities again

#

Isn't giving gameplay abilities always server authoritative tho

latent heart
#

Removing them is surely server authorative as well, then?

#

If the server doesn't remove them because it rejects the sheathe, it doesn't need to add them back again because it didn't remove them.

frosty harbor
#

good point I guess

#

Although will look weird ot have 200 ping and still be able to attack without a weapon in their hands for half a second or so

#

hahaha

latent heart
#

Generally you should predict visual changes. To make things appear like they're doing the thing, but leave major changes to the server to agree upon.

frosty harbor
#

gotcha makes sense

latent heart
#

You could make the displayed gameplay abilities based on the weapon you have in your hand, not the actual gameplay abilities you have equipped. But that's getting a bit further down the rabbithole.

frosty harbor
# latent heart You don't necessarily need an Id. The server could just say "request failed, equ...

Had to go have dinner but this is one of the function I run the sheathing through:

void APV_WeaponBase::SetIsSheathed(bool bNewSheathed)
{
    if (!HasAuthority())
    {
        return;
    }

    if (bIsSheathed != bNewSheathed)
    {
        bIsSheathed = bNewSheathed;
        OnRep_IsSheathed(); // update server’s own visuals as well
    }
}

void APV_WeaponBase::OnRep_IsSheathed()
{
    if (bIsSheathed)
    {
        CombatMesh->SetVisibility(false);
        SheathedMesh->SetVisibility(true);
    }
    else
    {
        CombatMesh->SetVisibility(true);
        SheathedMesh->SetVisibility(false);
    }
    
}

I'm only running this if bIsSheathed != bNewSheated, but if I change this variable locally then it'll also be changed for the server as well and it wont run when sercer gets to it (or vice versa) no? Which means I will probably also need other variables to flip / check when running this locally or am I thinking wrong?

latent heart
#

I would check that assumption before coding around the "issue".

frosty harbor
#

Oh it worked I guess

#

interesting

#

Thanks for the help guys!

fluid prawn
#

For AActor is TearOff property really used anymore? are there any side effects with calling this function?

#

or is it still good practice to call this for some ragdoll or heavy cosmetic stuff?

kindred widget
# fluid prawn or is it still good practice to call this for some ragdoll or heavy cosmetic stu...

I think for most cosmetic things, most people just spawn a new thing to handle it. It's messy having to shut down a replicated actor and keep it around technically in an inactive state vs just spawning a new actor with a same skeletal mesh, matching the pose and ragdolling it.

The only time I've seen people not really bother spawning a new thing is like... Arena shooter ragdolls where it cleans up on respawn of the reused character.

fluid prawn
frosty harbor
#

So I found an issue with the combo system I have. It's working well under high latency now, the combo is not being reversed to previous steps at all BUT, the replication of the attack seems messed up a little bit, since the first person combos are significantly faster than the 3rd person combo due to server latency (first person combos happen sooner), sometimes for example on the 4th attack of the combo, the first person / local combo is already on the 4th attack while the server is only beginning the animation for the 3rd attack so the server messes up either the animation by making it seem extremely fast or only showing a portion of the animation and then quickly switching to the 4th attack animation to try and "catch up" to the local combo, or at least thats what I think is happening, is there any way to fix this and if so can you suggest me a way to fix this or do you think it's something else that could be happening?

#

It also leads to issues where maybe at some point having high ping could be a benefit compared to having low ping

chrome bay
fluid prawn
chrome bay
#

Probably not because whether an actor replicates is also a replicated property, but IDK. Might be doable that way

#

But the client wouldn't have authority over it etc.

kindred widget
#

I've never used the tear off stuff but my general understanding is:

Dormancy is just "Please don't consider this thing for replication until I wake it up or flush it".

Tearing off is making it no longer server owned so clients can do whatever they like with it. So even if server destroys it, clients could still keep it around.

chrome bay
#

pretty much

frosty harbor
#

if ur doing locally predicted attacks should there be a trace scan both local and server based? Since for things like hit sounds to play accurately you need to know if you actually hit or not ig?

#

and you just use the local trace scan for the sounds

exotic wasp
#

Just doing a trace on the server with no rollback is likely to cause issues since the client will have been in a different position at that point in time, making the trace automatically different

frosty harbor
#

wont that also cause the issue where the player character (the replicated/latency one that other players see) can have hit air but the hit can count because it hit the other player locally?

keen slate
#

Hi, does anyone have experience implementing DetourCrowdAvoidance for a Pawn?
I'm using Mover, but I assume it's kinda the same that has to be done.
My Pawn class has implemented ICrowdAgentInterface, and I also have its AIController inherit ADetourCrowdAIController.

But I don't see any avoidance.

keen slate
#

I'm also calling GetPathFollowingComponent()->SetNavMovementInterface(NavMoverComp); from the AIController. In this case, the PathFollowingComponent is the UCrowdFollowingComponent.

keen slate
#

Also did this from the AIController:

auto CrowdFollowingComp = Cast<UCrowdFollowingComponent>(GetPathFollowingComponent());
if (IsValid(CrowdFollowingComp))
{
    CrowdFollowingComp->SetNavMovementInterface(NavMoverComp);
    CrowdFollowingComp->SetCrowdSeparation(true, true);
    CrowdFollowingComp->SetCrowdAvoidanceQuality(ECrowdAvoidanceQuality::High);

    CrowdFollowingComp->SetAvoidanceGroup(1, true);
    CrowdFollowingComp->SetGroupsToAvoid(1, true);
}

Still no avoidance. 🙁

I have never used avoidance before, nor Mover, nor anything path-finding related. So really, any help is helpful 🙂

#

I also see this code part:

bool UCrowdFollowingComponent::UpdateMovementComponent(bool bForce)
{
    bool bRet = Super::UpdateMovementComponent(bForce);

    AvoidanceInterface = TWeakInterfacePtr<IRVOAvoidanceInterface>(NavMovementInterface.GetObject());

    return bRet;
}

which confuses me, because I was convinced that RVO and DetourCrowd were mutually exclusive?
But would I actually need to modify the UNavMoverComponent and implement this interface myself?

limber gyro
#

Is there a callback or an OnRep for when the playerArray is updated?

gleaming raven
#

how can I disable weapon collision for the client?
the client is jittering but it's fien from the server side

limber gyro
#

jittering is corrections afaik

#

ur client weapon is not in sync with the server

#

if its cosmetic only you can just stop the replication and let the physics simulation run on the client

gleaming raven
#

@limber gyro so a better option is to have an empty class for cosmatic?

limber gyro
gleaming raven
#

like a fake class that only holds the skeletal mesh?

limber gyro
#

usualy weapons arent replicated at all, they ae just attached to the skeleton

#

you have to explain what you are doing exactly

fossil spoke
#

This could be generalized to BeginPlay in the PlayerStates themselves though.

meager spade
#

PlayerArray is local

#

its not even replicated

#

@limber gyro ``` /** Add PlayerState to the PlayerArray /
ENGINE_API virtual void AddPlayerState(APlayerState
PlayerState);

/** Remove PlayerState from the PlayerArray. */
ENGINE_API virtual void RemovePlayerState(APlayerState* PlayerState);
#

these are virtual

#

they only exist locally (PlayerArray is not replicated)

#

so you can override these in your gamestate to fire callbacks

limber gyro
#

i am a bit cofused then, if its not replicated how are all the player states reaching clients? the states themselves are replicated tho, does the array magicaly replicate if all the states are replicated?

gleaming raven
#

I have an Inventory and Equipment system and the items have physics enabled so I made them replicate because their position wouldn't match
also if they are not replicated the Inventory system wouldn't function for clients

gleaming raven
latent heart
limber gyro
#

never messed with that specificaly, theres a few settings you can mess with for corrections

latent heart
#

It does mean that the player array on each client/server is in a different order potentially.

limber gyro
limber gyro
#

the selected character is in the player state

gleaming raven
#

oh I done that before :3

#

hope in a call

limber gyro
gleaming raven
#

oh okie

limber gyro
#

i can show u the project tho if u want

gleaming raven
#

if you don't mind

crisp shard
#

is there anyway to detect when packet loss occurs?

halcyon ore
#

What if you lose the pack loss packet? 😛

fossil spoke
#

A hacky way might be to look at the percentage packet loss

#

And anything above 0 on either Incoming/Outgoing would indicate loss occurred.

#

But thats a rolling average, so its not going to be accurate nor would it give you any specific moment in time that packets are dropping.

crisp shard
#

ok cool, i always have 1 percent on when im testing just to see and i can see when it happens but was seeing if i could handle it somehow when it happens for certain things but i suppose it's also not something i can really design for or control, but was curiuos

fossil spoke
#

Assuming that your game is relatively network efficient, there is zero control you have over packet loss.

#

As in real world conditions, they typically happen at the hardware level across the transport mechanisms

#

Cut cables

#

Interference

#

Wifi dropouts

#

Etc etc

halcyon ore
crisp shard
#

nice, that adds some peace of mind, i just won't really worry about it

crisp shard
fossil spoke
#

@crisp shard Worry about making sure that packet loss doesnt result in desync or unstable gameplay AFTER you regain a normal connection.

#

Packetloss is intermittent.

#

You want it to come and go without affecting the long term running of the game session.

crisp shard
#

cool that makes sense. main thing that triggered the question was i noticed in very rare occasions, a timer based event causes issues, but i did just learn i could something like world time seconds and use that instead of timer or delay , for say a cooldown

halcyon ore
#

Kinda lost on the question.
Task Manager is a somewhat "known" shutdown, so UE can trigger a logout at the last second.
But, I know stuff like alt+F4 leave the client sit around for a bit.
(why they close processes differently, the world may never know.)

#

What did breaking on destroyed show.
No point in guessing, or reading the default logs.

#

Put a break point on destroyed
What calls it.
Remove whatever calls it.
Profit

#

So, just.
Override the PawnPendingDestroy
Now, it can no longer get destroyted.

#

Still seems hella weird, that alt+f4, and shit do just run completely different code paths. 😛

#

Looks like PawnPendingDestroy, and Reset can be overridden to prevent the destroy.
Looks like reset won't be an issue, cuz it looks like only the special resetlevel uses it.

#

I mean, you can see what its doing.
It doesn't modify much.
Changes to inactive state, and unpossess, then destroys.
Not like its doing magic.

fossil spoke
#

Pawn destruction on disconnect is normal behavior

#

If for example, you have possessable Vehicles that should persist so others can continue to use them when you leave.