#multiplayer
1 messages Β· Page 290 of 1
That'd be a welcome addition
Yeah, but it feels weird currently
I feel like Mover kind of eats that plugin's lunch so trying to make it more generic is a good idea
Nah
What Cyn is talking about is routing all of your networked stuff through GMC replication stuff
GMC has a community made GAS replacement plugin too so
So no more CMC fighting GAS for prediction and rollback and stuff
Which supports server applied but client "predicted" gameplay effects
yeah, that's what I mean by generic
so not just for movement but a psuedo-gas thing
Oh, you're talking GMC, not Mover being more generic
GAS prediction being separate from the CMC is a huge footgun people get burned by over and over
so it being 1 thing is a good idea (as a plugin)
Most annoying thing about GAS is how deep routed it is with ACharacter and the CMC
I just wished they did NPP and then just integrated it into GAS, CMC etc etc
It'd be nice. But the needs of Fortnite win.
And Fortnite works fine
Remember when Epic made games?
Fortnite is multiple games now I guess
Epic Mega Games
a lot of the chaos replication code is due to the needs of lego fortnite etc
With UEFN and how FN is going to be Roblox, I feel like they will need to make things more generic and play nicely together.
How do you test multiplayer sounds on a single pc? Such as footsteps
Spawn multiple clients?
You can isolate the sound in the settings to just the first client
So no matter which client you're controlling it'll always only return sound from that first client or something like that
Its in the settings
what's the recommended method, when using chaos for physics networking, to handle weapons that add impulses to other pawns?
modular vehicles :P
Pretty neat that you can make your own simulation components though, saving me a lot of time to just do that rather than redo the full vehicle sim that was going to be very similar anyway.
Having spent a lot of time with both GAS and NPP, IMO they are fundamentally incompatible. NPP is built around the idea that you can save and send the entire state of your system at high frequency. Also rollback/resim for ability logic when it can reach out to any part of your game is incredibly non-trivial.
Should I worry about race condition?
I do have Array and Iiterate it once per second. So its rare, but if some RPC comes and asks one actor to add some element to it.
Does it happen after global tick, before, is it async? π€
What racing with what?
Im just asking how unreal works, I don't have any async setup yet
Not sure whats that got to do with rpc
Servers iterates array, and some actor asks to be part of that array, or no longer wants to be there
so it breaks
async has multiple actual meanings
Why would inserting or removing element breaks the game?
async can refer to just doing something later, or doing it on another thread
in this case it is almost certainly the former
Realocation? Null pointer? list is long π
also yeah this question is not possible to understand
I do have Array and Iiterate it once per second. So its rare, but if some RPC comes and asks one actor to add some element to it.
Does it happen after global tick, before, is it async
what would race here?
@fallen fossil just a tip when it comes to networking.
I would say most of the tine like 90% of the time. Client always just request stuff.
Server always hold the truth and the correct data.
they are both on the same thread? why would one happening before the other matter?
the race would be the order of things not being what you expect, but I don't know why the order here matters at all
Well, I don;t know if they are on same thread
what are you doing from a task thread for this? you just said "every second" as if it's a regular timer?
unreal doesn't thread random things without you telling it to generally speaking aside from animation graphs
it it regular tick
I think if you can provide an actual use case / objective you can get clearer answer.
when would that execute on another thread without being marked to do so?
you really should just use insights at least once with stat named events on to see when each thing happens
it's really important to have a basic understanding of the engine tick flow to see when things happen on the game thread
No, but How unrela handles RPC requets or network channels :d,
this was my concern, is it on main thread, later or somehow using async maine worker threads
it's on the main thread
before anything ticks rpcs and replicated data are received
the order that this happens is of course not so simple but it's on the main thread
with networking the race condition issue is mostly in regards to things being split into DIFFERENT PACKETS that do not show up in the same game frame's network channel read
i did used them few times for performance, but never though I could check that
you really REALLY should use insights at least once, please just look at the frame graph
it is absurdly powerful to see what happens in the frame. you don't need to understand 100% of what is happening but having a basic understanding will help avoid doubts like this
and even if it did happen on another therad you could just add 1 critical section and call it a day lol
locking stuff about just 1 variable isn't that tough
also to be clear because of rpcs and replication being sent and received on the game thread this means that if your overall FPS is lower the rate of sent/received data will be more spread out as well
that last part about spread, why?
because there is more time between sending them
when something takes longer to do, the amount of time between doing it over and over increases
this generally matters more for data that is something that changes over time, like a player's transform etc
take note that literally everything you add from normal gameplay code is on the same thread
besides maybe some anim graph work etc
found my RPC, pretty neat tool
I guess you can try to find the 1 second timer as well but it might need to have a cpuprofiler trace macro or a named event (only visible in traces during stat named events)
but then, again, how would I know if its sending or receiving? π€ , I guess it is only tracing main window?
and it goes without saying the actual event must happen while tracing took place
how would I know anything about the network setup here?
is this single process PIE? multiple processes? which network mode?
, Im just asking if its tracing multiple windows π
read my message again
pie
is this single process PIE or multiple instances?
PIE can optionally create multiple processes to have each client be in a distinct program instead of just making multiple worlds tick under one uengine
you can also optionally have the different PIE instances tick at different rates to simulate the server hz being like 30 fps etc
okok
ok, I got one mroe question, more simple :D, how do I close this middle tab, which highlights my selected timer? π
that should be G I think for main graph... I forget lol
the options and keybindings are under the view options and tracks dropdowns
be careful because you can accidentally hit C and go into compact mode, just hit C again to undo it
I was there, but checked wrong tab
the button for it is here
If you see multiple game worlds under Tick_Engine it's running multiple instances in 1 process
if you are using multiple processes you will need to trace those processes separately afaik
thats add up
π πββοΈ
never test performance on single process for more players 
yeah it's kind of impossible to run well with 4 uworlds at once lol... the render time is just too much
you can crank down the resolution a lot but you can safely expect it to just be fairly slow
what about over 9000? 
r.screenprecentage will let you go above 100% so yes
The array would not be edited during iteration.
It's so good.
also hilarious that 10 iterations of a tire model costs less time than reading position and velocity or writing out forces.
I don't recall for sure but I think this was for like 512 or 1k tires
Wheel is smooth 
all that timing data comes from simple macros like linked here
https://github.com/AdrielKinnunen/SpectrelightPlugins/blob/main/Plugins/SLMechatronics/Source/SLMechatronics/Private/SLMSubsystem.cpp#L78
from chaos?
why not just run it inside of a chaos sim callback if it's going to be right there (some things will be much easier on the main thread that interact with main thread stuff though)
if you do a separate read lock for each physics particle of course it's going to be somewhat slow
depending on what other threads are doing it might even need to wait on those
Right now I'm just going through the component velocity and add force api, I'll investigate skipping that and going straight to the source later.
I guess you can look at modular vehicles as an example
not for how to make vehicles, but how to make them live right inside of chaos
I'll probably get it to run on chaos sim step but not right now
It's incredibly complicated and not necessarily related to chaos so that'll have to be an option
Chaos Mover might also be something that shows how to do this, btw.
Hell yeah, FFastArraySerializer is great. This is after spamming additions and removals of device models in a subsystem with bad network emulation. Order doesn't matter, just that the same IDs map to the same device models in the dense array at the end of the day.
ah shit nvm its getting out of sync somewhere
what does "out of sync" mean
also keep in mind "bad" emulation is beyond the pale
5% packet loss is insane
Final topology on server and client disagree. There's a device model on server that doesn't exist on clients, or vice versa, or mappings from ID to device data aren't aligned
what does that mean in fast array terms
is an entire element missing? not up to date after a second etc?
also make sure to not rely on fast array order
fast array order is not meaningful
you can use the fast array indexes of each element as a key if you need to
So here I'm using a fastarray of {ID, Data} and I build a sparse set on either end that maps ID to a packed array Data
I think the problem is when addition and removal end up in the same update as a modify
Yeah I haven't handled the case where fast additions and removals can result in a PostReplicatedChange as it all gets batched together, gotta handle that
I'm basically using a fastarray of {ID, T} to keep this in sync on both ends
template<typename T>
struct TSLMDeviceContainer
{
FSLMHandle Add(const T& Value)
{
const int32 Index = Dense.Add(Value);
int32 ID;
if (FreeList.Num() > 0)
{
ID = FreeList.Pop();
IDToIndex[ID] = Index;
}
else
{
ID = IDToIndex.Add(Index);
}
IndexToID.Add(ID);
return {ID};
}
void AddWithExplicitHandle(const T& Value, const FSLMHandle ExplicitHandle)
{
while (IDToIndex.Num() <= ExplicitHandle.ID)
{
IDToIndex.Add(INDEX_NONE);
}
if (IDToIndex[ExplicitHandle.ID] != INDEX_NONE)
{
Remove(ExplicitHandle);
}
FreeList.Remove(ExplicitHandle.ID);
const int32 Index = Dense.Add(Value);
IDToIndex[ExplicitHandle.ID] = Index;
IndexToID.Add(ExplicitHandle.ID);
}
bool Remove(const FSLMHandle Handle)
{
if (!IsValid(Handle))
{
return false;
}
const int32 ID = Handle.ID;
const int32 Index = IDToIndex[ID];
const int32 LastIndex = Dense.Num() - 1;
Dense[Index] = Dense[LastIndex];
const int32 MovedID = IndexToID[LastIndex];
IndexToID[Index] = MovedID;
IDToIndex[MovedID] = Index;
Dense.Pop();
IndexToID.Pop();
IDToIndex[ID] = INDEX_NONE;
FreeList.Add(ID);
return true;
}
bool IsValid(const FSLMHandle Handle) const
{
return IDToIndex.IsValidIndex(Handle.ID) && IDToIndex[Handle.ID] != INDEX_NONE;
}
T& Get(const FSLMHandle Handle)
{
check(IsValid(Handle));
return Dense[IDToIndex[Handle.ID]];
}
const T& Get(const FSLMHandle Handle) const
{
check(IsValid(Handle));
return Dense[IDToIndex[Handle.ID]];
}
int32 Num() const
{
return Dense.Num();
}
TArray<T>::RangedForIteratorType begin()
{
return Dense.begin();
}
TArray<T>::RangedForIteratorType end()
{
return Dense.end();
}
TArray<T>::RangedForConstIteratorType begin() const
{
return Dense.begin();
}
TArray<T>::RangedForConstIteratorType end() const
{
return Dense.end();
}
private:
TArray<T> Dense;
TArray<int32> IndexToID;
TArray<int32> IDToIndex;
TArray<int32> FreeList;
};
I don't have ID versions implemented rn but will add them later probably. Handle just wraps ID right now but will later wrap {ID, Version}
removal silently allowing an index none to stick around?
if it helps there is a built in struct called FInstanceIdIndexMap now that helps make doing this easier
(I don't know if it's fully exported though as it was made for isms)
I think the problem is if a remove and add get batched, you basically have the same size but different data. That's what I'm not handling, it'll get fixed tho
The FastArray is staying in sync, just not the thing I'm modifying on its callbacks
You can set the ReplicationID of the inner items of FastArray directly. I do that a lot when I want the ID to match something I already have, or if I want to control the ID's myself. Actually a very useful feature
FastArray will only modify it if it's the default value of INDEX_NONE - but if you set it before calling MarkItemDirty, it won't do anything to it
No need to maintain your own mappings then, it becomes native. Gives you a way to persistently ID things
(so long as you don't need an INDEX_NONE ID)
Server must spawn actors for them to be replicated to clients.
So my simple question is, spawning anything via RPC on client will have different Pointers and it won't replicate right? each copy will be local.
Replicated objects will resolve to the local object on the local machine
The object either needs to be net-addressable (resolvable by name, like objects in the map) or replicated down from the Server
wait a sec i gotta investigate this
oh shit yeah that's actually useful I think.
Do you know if there's a way to access the before value in PostReplicatedChange?
yep, the client spawning something will be local. You could for example create your own mapping of thing-> local object though
A really common thing to do is have replicated data on one object create other objects locally. This is good because you can keep the raw replicated data super simple but have a complex actor locally to mess with
For example equipping a gun could spawn the gun actor (only locally) while it's just from an onrep of a struct or a fast array being added/removed
so you keep the benefits of a nice visual actor but without the extra overhead and complexity of a new replicated object
Do you know if the inner items are guaranteed to be close packed?
I'm unsure wether to post this in #packaging or not.
Given I feel like it must be some tiny checkbox, or like config entry...
How do you setup your dedicated steam server, to not require the full steam client to be installed?
(If I install the steam client and login, my server works fine
(If I don't have it installed, or uninstall it, then the server throws some generic steam, subsystem errors, that says it has no appid)
Hello everyone, Iβve been thinking about this for the past 3 hours:
Should inventory slots and hotbar slots remain separate, or should the hotbar be derived directly from the inventory?
If I make the hotbar a separate slot system, Iβll need to create a separate table for it in MySQL. Iβm not sure whether thatβs a good or bad design choice.
If I donβt separate them, Iβll just use a single table instead of two.
Which approach do you think is better: a separate slot system or a unified one?
Logically I would think they are part of the same inventory system.
Thank you π₯°
Does it make sense that the hotbar IS an inventory or does it just refer to some set of inventory slots?
Is something in your backpack and on your hotbar, or is the hotbar like its own container?
Sadly no π It is kind of possible but you'd have to reimplement the fast array replication to get the base delta state before it serializes, you could mayyyyybe do that in NetDeltaSerialize but I've not tried tbh..
When you say the inner items, you mean the array? The array uses RemoveSwap during serialize so there won't be gaps in it when items are removed etc.
Yeah I mean the array at the guts of FFastArraySerializer
RIght now I have a fastarray that is used as the replicated state to keep a derived data struct in sync on either end
Yeah it won't have gaps or anything, item order isn't preserved though, could be different between server/clients etc.
the main thing is adds/removes/changes are bound to the ReplicationID - so if you remove an item with a replication ID, then add a new one with the same replication ID on Server, that's detected as a 'change' on the client not a distinct remove/add.
And generally you wanna be careful reusing ID's because the other properties 'ArrayReplicationKey' and 'ReplicationKey' may need to be incremented to ensure it replicates too
Basically I hand out handles to things, the core container looks like this:
template<typename T>
struct TSLMDeviceContainer
{
FSLMHandle Add(const T& Value)
{
const int32 Index = Dense.Add(Value);
int32 ID;
if (FreeList.Num() > 0)
{
ID = FreeList.Pop();
IDToIndex[ID] = Index;
}
else
{
ID = IDToIndex.Add(Index);
}
IndexToID.Add(ID);
return {ID};
}
void AddWithExplicitHandle(const T& Value, const FSLMHandle ExplicitHandle)
{
while (IDToIndex.Num() <= ExplicitHandle.ID)
{
IDToIndex.Add(INDEX_NONE);
}
if (IDToIndex[ExplicitHandle.ID] != INDEX_NONE)
{
Remove(ExplicitHandle);
}
FreeList.Remove(ExplicitHandle.ID);
const int32 Index = Dense.Add(Value);
IDToIndex[ExplicitHandle.ID] = Index;
IndexToID.Add(ExplicitHandle.ID);
}
bool Remove(const FSLMHandle Handle)
{
if (!IsValid(Handle))
{
return false;
}
const int32 ID = Handle.ID;
const int32 Index = IDToIndex[ID];
const int32 LastIndex = Dense.Num() - 1;
Dense[Index] = Dense[LastIndex];
const int32 MovedID = IndexToID[LastIndex];
IndexToID[Index] = MovedID;
IDToIndex[MovedID] = Index;
Dense.Pop();
IndexToID.Pop();
IDToIndex[ID] = INDEX_NONE;
FreeList.Add(ID);
return true;
}
bool IsValid(const FSLMHandle Handle) const
{
return IDToIndex.IsValidIndex(Handle.ID) && IDToIndex[Handle.ID] != INDEX_NONE;
}
T& Get(const FSLMHandle Handle)
{
check(IsValid(Handle));
return Dense[IDToIndex[Handle.ID]];
}
const T& Get(const FSLMHandle Handle) const
{
check(IsValid(Handle));
return Dense[IDToIndex[Handle.ID]];
}
int32 Num() const
{
return Dense.Num();
}
TArray<T>::RangedForIteratorType begin()
{
return Dense.begin();
}
TArray<T>::RangedForIteratorType end()
{
return Dense.end();
}
TArray<T>::RangedForConstIteratorType begin() const
{
return Dense.begin();
}
TArray<T>::RangedForConstIteratorType end() const
{
return Dense.end();
}
const TArray<T>& GetDense() const
{
return Dense;
}
const TArray<int32>& GetIndexToID() const
{
return IndexToID;
}
const TArray<int32>& GetIDToIndex() const
{
return IDToIndex;
}
const TArray<int32>& GetFreeList() const
{
return FreeList;
}
private:
TArray<T> Dense;
TArray<int32> IndexToID;
TArray<int32> IDToIndex;
TArray<int32> FreeList;
};
The Fastarray is just an array of {ID, Data} pairs.
I don't touch that replication ID, trying to figure out why I'd get any changes at all tbh
You have any UObject refs in there or anything? Could be getting changes flagged as UObject GUID's are resolved
Works the same way as OnReps in that regard
Basically i have a fastarray of {ID,Data} which is used to sync a sparse set on either end.
nah nothing is ever edited
I think it's a networking race condition that gets bundled up and called a change
Yeah, could be multiple packets combining or something. Would be strange though if you aren't changing ReplicationID yourself and just adding/removing elements
Normally ReplicationID is just an incrementing counter
Also you're not adding/removing items client side by accident or anything?
This is what it looks like when it happens. Red is serverside logging before adding/removing from fastarray
Ahh I see, so ordering issue
Nope all I'm doing is adding/removing from fastarray on server and recieving callbacks
ID xx is my id, replication ID is from fastarray
hmm yeah ID 6 getting a postrepchange is unexpected
Oh, unless fast array also flags items that moved in the array as changed.. but I don't think it does
It's rare and my removal test function just removes a random element, you'd think I'd see it all the time if that was the case
I'll check if I can just treat postrepchange as an add if not existing and call it a day.
what is the top level of the engine callstack that actually calls change
Played StepMania for a bit with add/remove commands and got the desync. Yeah it looks like client always misses something, it must be an add masquerading as a change.
huh, that is kinda freaky that it misses the add
I'm not sure if that is actually getting missed
or if you are expecting an intermediate value of a replicated property to arrive on a client or what
I still don't know why IsValid(Handle) just early outs on a dead entry that is index_none
that is your code
that should hard ensure
that is not a nice thing to happen
Change gets called all the time but a change with indices to work with is what we're talking about.
Handle is for consumers, a consumer can hold a handle that's invalid if they want
so they can just desync on their own? oh
I mean you can call AddDevice(returns handle struct), and later call RemoveDevice.
Just like timer, you can hold a timer handle beyond the lifespan of the timer it maps to
but that is not tied to replicating data
this is not the same thing
what happens if they just yeet a real entry from the server?
I'll later version handles, or I can just monotonically increment the IDs
having a way they can tearoff a handle might be useful to keep it around if that makes sense but imo it's easier to just have a separate local only container
The handle is how you get sim state, the sim lives in this opaque system. All you have publicly is basically a CRUD interface
Only other thing I can think of is if the client is the server/client sorting the array client-side or something, causing the internal ItemMap fast array keeps to be out of sync.
But doesn't sound like you're doing that
Be worth logging which ReplicationID's get added/removed server side too
could enable LogNetFastTArray to use log or verbose
that way it would log the reason for each changed indice
you can see there is a path that a new element is a changed indice
The other thing is that removes are always processed befored adds - so that second bit of client logging is two different updates
this kind of logging is easier if you add a framecounter imo
but the default log might have that already with a timestamp
for example BuildChangedAndDeletedBuffers
new elements are changed indices
at least in that path
this is indeed pretty annoying to follow but it's not impossible
yeah, probably need to log the hell out of it to figure it out. I mean personally at least I've not yet had a fast array that desync'd because of high frequency updates etc, but obviously updates do get "missed"
LogNetFastTArray
there are already logs
there is no need for new logs
you just need to turn them on with a console command
ye
it might be weird if there are other fast arrays active at the same time though
I'll admit I'm 50/50 on how I feel about the added elements marked as changed
I think skipping an added callback is nasty either way... that is super unexpected to me
I guess if all you have to do is just have a fallback in changed it's not that bad but still... I feel like that's kind of breaking the contract
I'm testing the lognetfasttarray rn
So here's a write with a numchanged
FastArrayDeltaSerialize_DeltaSerializeStruct for SLMFastArrayItemSimpleGearbox. SLMFastArrayItemSimpleGearbox. Writing
LogNetFastTArray: Current: 30 [12/0], [14/0], [15/0], [16/0], [17/0], [18/0],
LogNetFastTArray: Client: 29 [12/0], [14/0], [15/0], [16/0], [17/0],
LogNetFastTArray: NetSerializeItemDeltaFast: FastArray. DeleteCount: -1
LogNetFastTArray: Array[0] - ID 12. CL 0.
LogNetFastTArray: Stayed The Same - Skipping
LogNetFastTArray: Array[1] - ID 14. CL 0.
LogNetFastTArray: Stayed The Same - Skipping
LogNetFastTArray: Array[2] - ID 15. CL 0.
LogNetFastTArray: Stayed The Same - Skipping
LogNetFastTArray: Array[3] - ID 16. CL 0.
LogNetFastTArray: Stayed The Same - Skipping
LogNetFastTArray: Array[4] - ID 17. CL 0.
LogNetFastTArray: Stayed The Same - Skipping
LogNetFastTArray: Array[5] - ID 18. CL 0.
LogNetFastTArray: New! Element ID: 18.
LogNetFastTArray: Writing Bunch. NumChange: 1. NumDel: 0 [30/29]
might be an add tho, lemme find a read with a numchanged
so they just mark the changed elements and if they are added it just decides that later?
I guess why not if it's fast to check
OK i found this on the reading end, big chunk of changes, i'll try find the writing end
LogNetFastTArray: FastArrayDeltaSerialize_DeltaSerializeStruct for SLMFastArrayItemSimpleGearbox. SLMFastArrayItemSimpleGearbox. Reading
LogNetFastTArray: Received [65/57].
LogNetFastTArray: Read NumChanged: 5 NumDeletes: 1.
LogNetFastTArray: Adding ElementID: 15 for deletion
LogNetFastTArray: Changed. ID: 34 -> Idx: 9
LogNetFastTArray: Changed. ID: 35 -> Idx: 10
LogNetFastTArray: Changed. ID: 36 -> Idx: 11
LogNetFastTArray: Changed. ID: 37 -> Idx: 12
LogNetFastTArray: Changed. ID: 38 -> Idx: 13
LogNetFastTArray: Adding implicit delete for ElementID: 39. MostRecentArrayReplicationKey: 64. Current Payload: [65/57]
LogTemp: Warning: PreReplicatedRemove ID 4 at index 4 with replication ID 15
LogTemp: Warning: PreReplicatedRemove ID 13 at index 14 with replication ID 39
LogTemp: Warning: PostReplicatedChange ID 4 at index 9 with replication ID 34
LogTemp: Warning: PostReplicatedChange ID 9 at index 10 with replication ID 35
LogTemp: Warning: PostReplicatedChange ID 10 at index 11 with replication ID 36
LogTemp: Warning: PostReplicatedChange ID 11 at index 12 with replication ID 37
LogTemp: Warning: PostReplicatedChange ID 12 at index 13 with replication ID 38
LogNetFastTArray: Deleting: 14
LogNetFastTArray: Deleting: 4
LogNetFastTArray: FastArrayDeltaSerialize: Recreating Items map. Struct: SLMFastArrayItemSimpleGearbox, Items.Num: 13 Map.Num: 0
LogNetFastTArray: FastArrayDeltaSerialize_DeltaSerializeStruct for SLMFastArrayItemSimpleGearbox. SLMFastArrayItemSimpleGearbox. GatherGuidReferences
I wonder what 65/57 means here
ah it's ArrayReplicationKey vs BaseReplicationKey which I assume is the delta baseline
Anyway if anything about this approach seems baffling this might help.
I think I can get away with detecting when a "change" is really a funky add. As long as the derived high freq state lines up on either end it's fine.
those separate arrows are going to introduce some fun race conditions (not to say this is poorly thought out, I just think it's inevitable here... you would probably not get away with fitting the whole thing in 1 atomic thing either way)
you might need an incrementing change generation id
unless state showing up before the handle is okay and vice versa
State before handle is fine and handle before state just fails gracefully
"What's the RPM of the engine for this widget?"
"IDK the engine ain't here yet, so 0 I suppose?"
it might be kind of nasty to have a partial incomplete state in some cases but you can only really find out by triyng it I suppose
mostly when new stuff appears but it might be fine
It's the same thing as replicated actor vs a replicated pointer to it really
You got the thing, then references to it in some way which can be held by various consumers
Hello, create widget is returning unkown on client, I'm doing this on BeginPlay on a "Character" based blueprint, any one knows why?
Is that function authority only?
Nope, its Event Begin Play
I meant the spawn widget function
Because if this actor is replicated, a client won't have authority
And it seems like you're missing the owning player input
already tried that and didn't work
My guess would be it's showing up like that because you're inspecting it in a macro.
What is the actual problem you are having?
Begin play is too early, most likely it will always just spawn on server since the character isn't owned yet by the client at Begin Play.
@verbal field Begin play would not be the right place to setup U.I most of the time. Also if you are planning to have one radar per player, you should use IsLocallyControlled,
otherwise you get duplicates.
I'm assigning the widget to a variable, but the client player will have the variable as null half of the times that is called, the variable doesn't get changed anywhere else
Widgets aren't replicated.
Creating a widget on Begin Play of a Character blueprint means that every single instance of the game will end up creating their own copy of that widget for every single Character.
So if you and I are in a game, Begin Play will fire on my end for my character and for your character. On your end, it'll fire for your character and my character. That's 4 instances of a character and each has their own widget being created.
Your problem may be that it's coming up invalid because you're attempting to access it on the server (if you're running as dedicated server)
Setting the variable
Widgets don't replicate, so setting w/Notify does nothing.
when a client validates it on the same Caharcter it shows null half of the times
it's utterly pointless, widget don't replicate.
a machine need to create it's own widget on it's own.
Replication in object means that when a server create the object, clients will also get a copy.
when it comes to widget, widget does not replicate.
I know Mover has better replication and network prediction out of the box compared to cmc, can I for example have a pawn with two separate collision capsule components properly replicated and network predicted without having to modify any of the components through cpp?
Ok, but turning off replication still shows the variable as null
Sure, that's not gonna magically make your widget replicate.
and afterall it doesn't replicate, so it's irrelevant.
You need to ensure that the create widget node is executed in target machines.
and I repeat, BEGIN PLAY is the WRONG place if you required to have the U.I in client.
Thanks
perhaps you can show us the visual of your widget. Hard to give pointer without knowing the objective.
The widget is irrelevant, I have multiple widgets with the same problem, all I need is to save each players individual widgets into variables to call them in gameplay
the problem is you may unintentionally get duplicates if you don't know how to filter net code.
for example if you spawn at begin play of character without filter. If there are 4 players, your Player 2 will end up with 4 radars when the intention was just to spawn one.
caching them isn't even the issue if the create widget node is not run on the problematic machine.
I don't know what event you can hook into in blueprint though... I use AcknowledgePossession to setup my U.I on client.
may able to do reliable client RPC after server Possess but not sure if that's 100% reliable.
can maybe do on the OnRep_PlayerState but it sound nasty.
OnRep_PlayerState would be helpful if they need to be aware of the playerstate set locally
which is often the case, so that's not a bad idea at all
if it needs to read and bind to properties from the playerstate etc
In this case it might be useful to use something like ReceivePossess on the controller or pawn
that way you can see when it's a local player controller and keep the logic relevant to the pawn
ah wait, that's server only
I've been away from stuff like this too long... I think the playerstate's OnPawnSet would work okay
Server get loaded Character from Cleint(Super), but Client not get loaded Character form Server, i try everything but no success i am near it must be a small fix for this?
Are you the person that ask about "loading" save file in multiplayer game?
Yes Coldsummer
As client, you load the save data then you send the data to server.
Server then set the replicated variable and replicate it to all client. Its as simple as that.
For example you have a save file in the client machine to dictate hair color.
As client, load the save data then send that FColor data to server via server RPC.
Server then set the hair color (replicated). Client will get the update via OnRep -> set hair color.
need to see more code
Sorry maybe i make things to complex, thank you for yor time looking on that
Because it is MP and i can only see the Result if it is working when i package to Steam and test on 2 Machiene this make things more Time Consuming and complicated( like Matt Botswain says here: MP is not a walk in a Park π for sure)
replication is walk in a park once you understand it. But yes MP is a can of worm, I don't even know if I can make a working MP game. Things get hard if the game is real time.
For turn based game or where latency doesn't really matter, then basic understanding of replication will suffice.
@willow adder You can test by making dummy data too instead of loading from save file.
the point here is that as client, you need to send data for the server to acknowledge and replicate.
Where the data is pulled from, e.g from code or save file. It doesn't really matter in the context of testing.
having to package everytime you want to test functionality is a pain.
I try it with a Dummy data and it looks good but when i switch to Steam and it do not work and load all from the Server Save file
so the save file, where does it exist?
wdym by Server Save File
I thought the client store their own .sav in your project
when i start Steam as you know Matchmaking Listener Server 1 gets the Server and 1 the Client both have its own Local Save
Even if i Switch from my Alt Pc and Back the same Result
for every Pc also client itself
yea, so local to each machine, gotcha.
what event is called prior to this branch
lol
that's not ideal, if your player have high latency the game will break.
I haven't seen your loading code yet, did you send the data to the server as client?
what you prefer instead?
try to do this in
OnRep_PlayerState->IsLocallyControlled->Switch Has Authority -> Load SaveGameFile -> Set things
-> Client -> Load SaveGame File -> Server RPC (Data) -> Set replicated things.
Did i must Cast to MainChar or to that Component
when the Playerstate is replicated. You need to know these objects, they are crucial in MP.
Game Mode, Game State, Player Controller, and Player State.
Hi! I ran into a problem that makes me wanna pull out my hair and thought maybe I'm missing something very obvious that someone can point out.
The following code is being called on some players from the game mode, the problem happens only on the joined clients and not on the hosting player:
In example 1: I print the value of pos (1000, 0, 40), the client moves nowhere.
In example 2: I hardcode the exact same value as in the other example and the client moves to that spot.
Why does it behave differently by passing in a vector even though the value is exactly the same?? π₯²
is your CurrentMinigameStartPositionLocation array empty? because my guess is that it's empty
It's not, logging the length says 4 and I get an expected vector value
Who's calling the code, the server or the clients?
so if you print the value of the vector it's printing a correct value on both client & server or whereever you need it ?
The server
it sounds like the value might not be replicated to all clients ?
since you said its only an issue for connecting clients
print everything
It's printing on the server only and setting actor location on the server should automatically replicate
where are you calling the code?
Is this in your character class?
The event is in the character but I'm calling it from the game mode
Can you show the code that's calling this event
The vector array is set to replicate and is set on the server through a server RPC
and can you also show how you are setting the array
where are you setting the replicated array
the BP_OnMinigameLoadDone is called on the delegate OnLevelShown when loading a level instance, which I assume is always on the client
All of this seems right, are you making sure the variable is being set before calling the MoveToMinigameArea event?
it's a really interesting way of doing it but the code doesn't raise any flags, I'm guessing it's a race condition
make sure you're only calling MoveToMinigameArea event after the vector array has been set
to test if this is the problem you can add a 1 or 2 second delay before calling MoveToMinigameArea
yea I'm sure it's being set before.
hehe yea I'm gonna clean up a bit later, just wanted to get the moving to area bit working as fast as I could but maybe I'll just rework it now since it's not really working π
yea I'll do some more tests before I try something else
The thing is it looks like clients are calling an RPC to the server to set the vector location array, that can cause a race condition
It explains why it works fine on the server but not the others. I bet SetActorLocation isn't being reached
if you remove the branch in the first image all your clients will spawn teleport to 0,0,0 on the map confirming this is a race condition or that you are setting the array vector incorrectly
I created a custom phy function that generally replicates phys walking and pushes the character at a certain speed and than i play a montage ontop of. This has been working really well and will replace this instead of using root motion to fix all the corrections for networking. I have created animation cancel notifiers for each montage to cancel into other montages. Now the issue i am facing is as sim proxies the distance and speed traveled is fine but at higher ping the animations don't match up and if you were to spam dodge roll animations for example it will cut the animations due to high ping. I am wondering what would be the best solution to resolve this? This is due to server rpc delay issues and wondering what can I do to have it where for sim proxies their animations play in order and don't look like they are cutting off completely.
is a server rpc what makes the sim proxies animate?
sim proxy characters are almost entirely just some onreps and local interpolation/extrapolation + some local sim
Just a net multi cast
Sorry if i confused you but basically I play a montage locally and than right after a server rpc call with a multi cast
in that case it's entirely random when it will show up more or less
relative to other properties
is it reliable or unreliable?
Reliable
for this kind of thing it's really context specific and to make it "perfect" might involve buffering things or sending timestamps etc
I can't tell what is actually being sent or received or skipped
that's not descriptive of what is happening here
the montage is a "roll anymation"
is it playing with root motion? does it just follow the player moving?
oh okay no root motion
also FWIW network emulation will make for some bad situations that are rarely going to happen in a real game... if you are testing with 1 second of ping and 5% packet loss of course it will be nasty pretty much no matter what
Yeah i have a custom phy function that drives the chatacter. Im just playing an animation ontop. My issue isnt with corrections or moving the chatacter that all works really well. Just that the animations themselves are not playing as clean in higher ping.
Is this as the host looking at a client?
Yeah i know I tested with friends and had one friend with bad internet hovering around 200 ping. It played fine but I want the animations to play cleaner
in order to make it perfect 1:1 with the OTHER replicated properties IMO the only thing you can really do is have the onrep that triggers sim proxy movement include the information about the roll... this requires C++ but I imagine you could probably cheese this in bp somehow
you don't need to do this but otherwise properties/rpcs will always have a chance of showing up on different frames from the normal transform replication
and yeah is this listen server etc?
Host and other clients
listen servers only update their cmc's animations when an rpc is received with a new saved move (to support root motion) and disabling this behaviour might involve some C++ or just having a second mesh on top of the normal one
So are you saying the clients see the animation jaggy too?
because those artifact normally visually visible on listen server only for the reason Megafunk said above.
GetMesh()->bOnlyAllowAutonomousTickPose = true;
this one?
Looks familiar.
hmm actually he said the montage is clunky, not the normal anim?
yeah fwiw this person seems to be seeing this on clients as well
but that listen server thing is still worth pointing out
yeah that may not be the case then.
My montage playing pretty bad when I use GAS to do it under high ping.
haven't test in packaged yet but that's the behavior on editor.
GAS montage replication is just an onrep that sends timing and section info with some error margin
Yeah, it kinda skips some of the time.
Oh no that is something else i already did that. Im not talking about if host sees it like skipping. Im talking about animations at higher ping cutting off.
More of i want the animation to be more in sync with the movement.
Sorry when I come home I can give more details had to head out somewhere. I can show video examples of what I am talking about.
in order to get perfect timing for a series of montages that aren't locally following you might need to simulate the work locally but this is probably just 1 montage for rolling
"cutting off" is not enough info
is it starting too late and getting overwritten? is it starting too soon and getting stopped?
oh okay yeah videos would help
all good
Yeah I'll show what I mean to get a better understanding its really hard without context. Thank you guys though!
but yeah either way I think my personal favorite way would be with a custom onrep for your cmc that replaces onrep replicated transform... this will involve some c++ but it is pretty much the most complete way to remove this problem
if 1-frame offsets cause jitter from separate properties/rpcs arriving at random times it can help
Going with this, how would i work with a root motion animation for a dodge? Using RPC I have gotten it to look perfect on other clients but the owning client has huge jitter
Same goes for a quick and dirty running code i made in blueprints, which will be easy enough to add to the CMC, but i think they seem from the same issue
I can also make it relatively smooth by playing the animation on the client and the server, but then the other clients fail to see it
are you using montage? If you do, you shouldn't get jitter.
Sorry about the delay I was with family but here is the video @nova wasp
i am testing around 400 ping with like 5 percent packet loss.
so the window on the right side is the client i am controlling. On that side everything is playing fine and no corrections. My issue is what it looks like to others. Becuase of the rpc delay time if i keep spaming attacks it gets cut off. I know these conditions are not realistic and wont happen but I only did this to stress test and show clearly the issue i am having. I asked claude on solutions and it talked about some sort of queuing while multi casting and stuff and dont know if that is the best possible solution and was hoping if there is a better way to handle this.
Just in general I would not test with package loss, especially not that high values of it. You can check if package loss leads to your players getting soft-locked and resolve those cases, however, despite that you can expect the game to run and look really bad if packages get lost. Try to see how it all runs and looks with only the ping being high and maybe keep it to values like 250.
it plays and looks fine at around that ping with some occasional animation getting cut off like in the video. I know that those values arent realistic but i set those values to show more of what I am talking about. I am handling rotation and speed using custom cmc code with safe and saved and compressed bools. Issue is i am playing montages with an rpc ontop of those movements. so movement is being handled perfectly fine just animations lag behind.
it kind of depends on which part you can "skip over" safely I guess
you might need to get into predicting them continuing to attack if you really really can't accept missing one animation
I feel like the 5% packet loss case even for demonstration here is too extreme
So packet loss here is the reason why the animations get cut off here. Generally what is the best values to use to test emulation?
you already said it
the actual real life ping values
one friend with bad internet hovering around 200 ping
I am going to venture a guess that their loss did not exceed 1%
even 1% is absurdly high imo
oh really??!?! why the hell am i testing with 10 percent and stuff loool
the "bad" settings are to see if the game even works under the worst case scenario
not to compare with just "bad internet"
Oh I guess i spent alot of time on this when it wasnt as bad as i thought lol.
it's worth trying out just to see if something outright breaks with it on I suppose
for example someone could have their internet cut out for like a split second or something... shit happens
on the bright side I did improve my netcode alot and testing with my friend really proved how solid it is so it wasnt a waste.
yeah. Thats the thing im still learning networking and so far making some good progress. Thank you though you helped relieve alot of weight on my shoulders!
Yes! I am. I am testing with network lag though
show your code
anything related to playing the montage and the network emulation settings.
coming
I don't think you can expect to have something look allright with packet lost
5% is extremly bad too.
even 2% is too much already.
yeah I am starting to think they need a really big caveat there
5% packet loss is ABSURD
that preset is not just a "bad" connection... it is the worst case
1% packet lost in dota and i just stop playing.
this works almost flawlessly on the client but other clients don't see the anim
this works almost flawlessly on other clients but there is jitter on the character
what does "there is jitter on the character" mean
what actual data is representing the jitter?
this clip is using this
that looks like a movement correction
yup, looks like movement correction.
This is using the other one
what's the command again to visualize correction?
well that's because you play the anim on the machine that is calling the code AND on the server.
but you never play it on the other clients.
this one is also cooked because you are not locally predicting the animation. Input delay is nasty on movement / attack for the player that is possessing the character.
I don't really feel any input delay, and this is more of a chill game so I wouldn't need such a precise input anyways. if i could only make it so the animation appears on the rest of the clients i would be set
nvm actually
with this picture, 100% input delay.
also if this is a co-op game as always I would say consider turning off network corrections entirely... you do not need to suffer the madness of extending the cmc correctly that way
the first one you are predicting but you are only playing on the calling machine + the server.
How??
you never tell other client to play the anim.
can i do that "easily"?
that's the part I am lost at
you literally do so in the second picture?
try this. But I don't know if this cover all edge cases.
Personally I use GAS play Montage and Wait.
but then there is huge input lag, and not only that but the animation plays twice on the client
you don't want to play the montage again on the client that is initiating it.
exactly! How do i prevent that?
MC_Roll -> If Is NOT locally Controlled -> Play Montage
THANK YOU let me try that β€οΈ
you could also consider sending it is an onrep of a value but that would involve dealing with some math to prevent timing issues and incrementing it etc
@nova wasp So corrections are driving me crazy too. It's been constant ongoing battle.
like just bumping into another player already cause unwanted correction.
I can just turn it off, but would there be a lot of margin of error as the time goes by?
well, bumping into another player sucks for corrections because the cmc only thinks about itself for the most part
like off by 200 units for example.
This is what I needed! I think it's a bandaid solution BUT it doesn't bother me much
the margin of error would only exist if the server never ever accepted the state but only the input (in a way that diverges)
the server does accept the state though afaik
ye, I would maybe use GamePlay Ability System PlayMontage and see how they do it.
I'll try this as well
GAS PlayMontage is 100% just an onrep of the montage and some timing
it is really really simple and they kind of make it look fancier than it really is
it's not some magic external thing either, the onrep exists right on the GAS component
the task exists mainly to hold callbacks and keep the replicated property updating until the montage is over
that said yes it is quite effective at what it does
it's not good enough for things sensitive to frame-by-frame timings but it's great for most things
I guess the montage slot timing and the serialization is somewhat fancier than just a basic onrep but I guess it's just... not doing much beyond sending a montage and a time
the best thing about it is that it's stateful in a way that late-joiners will resolve state and relevancy pop-ins will fix themselves
but 90% of game anims like montages are so short it's not that important
(also I just wanted to say that game environment looks neat... I like the style)
sorry for late reply! I hadn't payed attention to the fact that the client was being moved correctly on the server so this was fixed by just multicasting the setting of the new location. I just strongly believed I shouldn't have to multicast since player movement should automatically be replicated, I'll look into that more, but thanks for your replies! π
Makes my heart warm β€οΈ
Ah you dont have the replicates movement boolean set to true
it involves a variety of cvar settings including AGameNetworkManager::ClientAuthorativePosition
;defaultgame ini:
[/Script/Engine.GameNetworkManager]
ClientAuthorativePosition=true
This may very well be a good solution too since I don't expect/care for cheating
If you start flying all over the place? Sure, yer a wizard now
https://notes.hzfishy.fr/Unreal-Engine/Networking/Types/Character-Movement-Component#client-auth I could not find a more official source but fishy's notes include this as well... It's been a few years since I tracked down the 2 or 3 settings
you can also get away with accepting client positions temporarily which can be helpful if you just have certain situations that are difficult for the server/client to agree on
When I tried to do that, the moment I toggle the bool back, the character get corrected π’ .
that was the advise given though when doing something "fast". π€
yes I do, so setting it only on the server has worked in a bunch of different places but not now for some reason, I'll look into it more!
hmmm i got the strangest issue after switching to Iris... after a good amount of actors have been spawned/destroyed, a random actor being spawned will just not replicate anything (other than its initial data, so no replicated vars or RPC's) and the ONLY hint i get in the logs is:
LogActor: Warning: AActor::PostNetInit InteriorShape_0 Remoterole: 0
this is gonna be fun to track down π although while writing this i notice the name of the actor is _0 and its definitely NOT the first InteriorShape actor that has been spawned
Hi everyone. For seamless travel I believe the process will destroy all actors like game mode, game state, player state etc, create new ones and allow you to copy over some properties from the old to the new.
Is the sequence in which these actors are replaced guaranteed? For example, can I guarantee that when the player state's CopyProperties or BeginPlay functions are called, the new game mode is already active, or is it uncertain?
Hi everyone, hope youβre all doing well.
Iβm running into a replication issue with head movement and would really appreciate some advice.
Iβm trying to replicate head rotation (offset) so players can see each otherβs head movement in multiplayer.
Current issue;
The Main PC (Listen Server) can see the Clientβs head movement.
But the Client cannot see the Main PCβs head movement.
Important details:
The head movement logic is inside the Animation Blueprint.
Iβm using control rotation to drive a spine/head offset.
Jumping and other movement replicate correctly.
The rotation is being calculated locally in the AnimBP.
Has anyone run into this before
@dark lance where is this?
anim blueprint doesn't replicate.
so no point making a replicated variable in your anim bp.
Okay that makes Sens , Can I ask where should I put that logic , I'm still new with Replication
You wouldn't replicate any of that as you can compute its value based on other values that are already replicated.
However, instead of using GetControlRotation, you would need to use GetAimRotation, which is replicated
If the head points where the player is looking at, then just use GetBaseAimRotation.
or is it GetAimRotation 0o?
void AAGPlayerCharacter::AimOffset(float DeltaTime)
{
if (IsLocallyControlled())
AO_Pitch = GetBaseAimRotation().Pitch;
/** Gets proxies characters in server that server don't control. */
if (GetBaseAimRotation().Pitch > 90.f && !IsLocallyControlled())
{
/** map pitch from [270, 360] to [-90, 0] because of compression */
const FVector2D InRange(270.f, 360.f);
const FVector2d OutRange(-90.f, 0.f);
float L_AO_Pitch = FMath::GetMappedRangeValueClamped(InRange, OutRange, GetBaseAimRotation().Pitch);
AO_Pitch = FMath::FInterpTo(AO_Pitch, L_AO_Pitch, DeltaTime, 15.0f);
}
else
{
AO_Pitch = FMath::FInterpTo(AO_Pitch, GetBaseAimRotation().Pitch, DeltaTime, 15.0f);
}
}
remapping bonus because iirc, the pitch value is optimized.
wow okay thank you @mystic estuary @dark parcel I will try this and let you know thank you for the help appreciate it
Iβve got the pitch (up/down) working on both client and server. However, when the server (main PC) looks left/right (yaw), the client doesnβt see that yaw movement. Any ideas why yaw isnβt showing on the client side
I did use Get base aim rotation and it worked
Is there a "best practice" way to delete default subobjects only on the server?
Looking at your footage it appears that your character capsule isn't actually rotating when you're looking left/right slightly. GetAimRotation predicts the yaw based on capsule rotation replicated by CMC.
In this case you would need to replicate yaw manually. Simply create a replicated variable that you update on the server using server RPC on tick, and use that to replace base aim rotation yaw
Nah use GetBaseAimRotation instead
There's never any need to replicate anything extra for aim offsets
@dark lance on simulated proxy you'll want to add interpolation to your aim offset because it's byte compressed, it'll look jerky without it
hey, did anyone encounter this issue where the charactermovementcomponent's smoothing doesn't work in the listen server compared to the dedicated server?
i did this test side by side with network emulation
in the listen server i get the correction debugs and the experience is bad, like if there is no smoothing
while in the dedicated server, i also get the correction debugs, but it's much smoother like the system is actually working
There is no extrapolation on listen server, epic confirmed via udn, and suggested attempting to implement it manually the same way they do for sim proxy. Never tried it myself nor was any outcome posted
Epic don't care about listen server and haven't since 2014
Fortnite doesn't need it
what is extrapolation?
it also only ticks their skm animations by default when a new rpc is received (mostly to try to resimulate root motion afaik)
Maintaining networked objects in sync is just one part of the problem when we consider multiplayer games.
One of the prominent issues that arise is th
In case it's not clear, it's used for mesh smoothing
has anyone used filtering classes for Iris? is there any way to get the internal index that the filter class uses from a FNetHandle? from what I can see from source the main way is through FNetRefHandleManager but that is completely private...
oh the UNetObjectFilter class has a GetObjectIndex() function
When you find out the game state isn't always replicated/ ready for use
I know it has to be networked, but I assumed given its a core actor, it would be forced to be first or something
Thank you Coldsummer and Datura both way working, the solution was on the End just 1 Variable as RepNotify the Rest Replicated than on these RepFunction Call Server RPC and it works like a charm on Steam, too.
yeah you cant rely on actor order, even the player controller actor isnt guaranteed to spawn first
It's guaranteed to be there in BeginPlay however
If that helps
Simply because the game state is the one that routes begin play.
Anyone got any tips for reducing RAM usage in editor, so that it's easier to launch multiple editor instances?
dont have any levels open / open an empty level is the only thing you can probably do
AddGroupFilter doesn't exist anywhere... did AI write these docs? π€
They change the API a lot
anyone knows what would cause this on iris?
How the heck does that work?
Isnβt the PC essentially the clients connection?
no
For RPCs it's the owning connection yes but the PC doesn't handle the low level networking stuff
Iβll need to double check my code then, maybe something is messed up.
Cuz I think at least my testing wise it shouldβve all been begin play based.
But I know in actual gameplay thereβs be on reps and stuff.
the game state routes begin play so you quite literally cannot have a begin play call without it being available
Oh, interesting.
I always thought it essentially was.
First thing created on join, and first thing destroyed on leave/ quit.
However rep notifies can call before begin play, that might be your problem
Yeah.
But at least for this test on rep shouldnβt be an issue.
Has me curious if I did something weird without realizing.
ah yeah its AddExclusionFilterGroup()/AddInclusionFilterGroup() now
anyone? π
cant say i've ever seen that before... looks like LogIris throws out some logs when protocol verification fails though.. i'd try searching for "FReplicationProtocolManager::ValidateReplicationProtocol" with LogIris turned on and see if anything pops up in either server/client logs
its suggesting to compare the CDO state for client and server to find the mismatch ?
could be different build version on client and server i guess
Anyone know if there is a delegate for when a playercontroller disconnects? I'm struggling to find something but I need to bind to this so I can do some cleanup in some of my container logic
cheers I'll take a look
Oh, lol.
I forgot half of my system is built on ReadyForReplication() of my component.
Hence why I run into issues of no game state
Perhaps I should change that to begin play. π
it cant be, not possible
unrelated but were you able to fix your gc crash issue?
If so what was the fix?
Thank you Vaei , I will add this and implement it ,
Hi, I have a fast array that contains a replicated uobject ptr.
For some reason, when I add an entry to the fast array, assign its uobject ptr to a new replicated uobject (which I also added to the replicated subobject list) and mark it as dirty, the fast array first calls PostReplicatedAdd with an invalid uobject ptr and then PostReplicatedChange with a valid one.
But in both calls the replication ID is identical.
Does anyone know what could cause that?
what crash?
this is correct
cause the uobject is replicating slower that the fast array did, PostAdd has no replicated uobject on the client
when it does resolve, postchange gets called
this is a typical race condition
and if your making the object the same time you update the array, something has to arrive first.
Is that internal to fastarray? Like it checks that the pointer resolves and enques for PostChange if it doesn't?
yeah
might be anything tbh
never really took notice if it happens on say a replkciated TArray of objects
I've only used fastarray on POD structs but I've noticed some changes that seem to be packet ordering based. I basically route Add and Change to the same code
I see, thanks !
Hi guys, I'm making a Local coop couch party game and I've run into some problems, I am running ue5.6 using blueprints . I either need a way to toggle the project setting that sets the a gamepad to controller 1 instead of 0. Or I need a way to add more than 4 local players. Preferably I would like to add up to 8 but tbh I'm ok with whichever is available to do with blueprint or a plugin.
the shipping build Only gc crash which u were getting a few days ago
It does yeah, quite often you get OnRep's where the elements have changed but some are still nullptr, when the objects get resolves the OnRep will fire again
yeah figured it has some kinda property resolver
to refire the onreps
hey guys, i am trying to do a server travel in blueprint and it does not work on the package project when tested.
I am doing OnPostLogin in game mode, and also set "Use seamless travel travel to true" but still no result. have tested the server travel in editor it worked but when i package it does not. please any one with experience in this ?
Did you include the map in packaging?
yes
So I'm a bit confused by knockback with GAS. I'm trying to, inside my ability after I detect a hit, to apply knockback via impulse or launch character (tried both). On listen server knockback is executed properly, but when I swap over and play as client I don't see any KB. This is after a few authority checks. IF I remove my authority checks I do see knockback but then there is some desync where I'm running into an invisible character.
How are we supposed to implement KB inside of GAS as I feel like I'm missing something here. My flow is basically : Execute Ability -> Play Montage -> Start trace via gameplay event inisde the ability -> Apply knockback and damage if we hit something
hey @kindred widget i think it was the problem actually, I did include all the levels in project settings before package. I thought by default the packaging will include all the levels
Names for identifiers. Strings are text values. Text are user-facing text values.
Send whichever is appropriate.
FText is the input you get from text entries, so probably FText.
It probably makes very little difference. You may lose some encoding data if you convert to fstring.
May
I believe the limit is over a thousand per packet, so you can send pretty hefty strings.
100 would be fine.
I'm not sure honestly, I haven't looked into the internals of ftext.
No. Definitely not for user chat messages.
You should try to stick to fnames, but only where they are appropriate. Is it an identifier for something? Use an FName.
For user chat messages I'd go FString
Since they're arbitrary strings
Not localized and not identifiers
Still remember the day someone said, "you should use FName instead of FString because sizeof(FName) < sizeof(FString)".
That's just their RAM, it's able to store strings of any length without using more space
pocket dimension ram
It was probably Mistty. We all know they're PC is a magic black box.
we're just all living in the past
idk when I run out of RAM I just download a bit more from some totally legit website
can anyone please help with dedicated server stuff. im having an issue where it wont launch right
Even if you pick FName under the wood it will be serialized as an FString
I'd still go FString just for what it represents
well the thing that stands out to me is that the client is calling a client rpc
Well the function name kinda weird too. Client spawn character on client.
So i guess he doesnt want to spawn a replicated character??
nevermind i solved it
Its common etiquete to explain briefly how you solve it so people with simmiliar problem can find resolution.
Also its mp we r talking about. You may miss a thing or two and that may be picked up if you share your solution.
Ah your right, well the problem was not this code, it originated from the game mode that rann the spawn character to soon really
so the code shown worked as intended
I am kinda worried about the client rpc call inside the controller.
Very much doubt that is the actual intention.
If you are aiming to spawn a replicated actor then it has to be done by the server.
A client running client rpc will only run the function locally at best.
So what ever you spawn will never be in sync and only exist in the client machine that execute the code.
Hmm i dont remeber, but if im playing as listen server then playing a montage with RPC will make it play twice once on client and once on server, i dont rember how to set it up x)
iΒ΄ve set this up before and it worked like a charm
isnt that what you want? for it to play on server and client ?
well since im playing as listen then the host playes the montages twice
wich runs the code twice basicly
so it plays twice on server?
so you never want it to play on the server?
or what do you mean with client side of the server
or is there no dedicated server and is it one of your players that is hosting
maybe the server has a local and remote controller and is calling it twice
have you tried logging all the calls to the function and what object is calling it
if you add a print node just before playing the montage, and you launch the game as listen server with no clients, does it print twice?
yeah
or on the client side its printing for the client and server .. hm
Should clients ever be manually adjusting their Role? I came across code that's manually adjusting the Role of Pawns on clients in order to mimic Possession so that both a mounted unit and the player are both still AutonomousProxy. This doesn't seem like the expected path and that maybe it'd be better to just set the mounted unit as the Owner of the player Pawn when they're on it, or let the Controller own the player Pawn. EIther way it seems like the server should be in control of determining roles. Thoughts?
having problem with online subsystem steam
it doesnt pop up
enabled online subsystem in plugins
I'm fairly certain clients can't adjust their role. The server is the authority as to what has what role and that won't change if the client changes it locally. They may be able to set things locally, but that doesn't mean the server will respect it.
this is the listen server player if fires the code twice...
The Multicast would trigger once on all clients and once on the server. If the problem you're having has to deal with the amount of damage being dealt, it could be because you're doing that down the line in your code.
Also, it's probably not a good idea to allow a client to tell the server what animation montage to play and then let that multicast out to everyone, as that could allow clients to play animations they shouldn't be allowed to play.
how would i play a montage without RPCΒ΄ing it then :/ ?
You let the server decide what montage should be playing. don't have the client send an RPC to the server with the montage and blindly multicast it out to everyone else.
hm,
yeah but for the clients it only damages once, but for the listen client twice, with same code
and i get "why" it dose that
im not sure how to sole it tho
You should only be doing the damage on the server π
You're probably doing damage on both the server and the client.
https://blueprintue.com/blueprint/y1dvbrak/
Hey im trying to show Health Bar (widget) for only the client or the player doing the damage
but it always shows for the listen server host also..
Stop using the getter with index
aye ignore that part already removed it <)
Info are missing so cant help without knowing more.
Like what actually calls the event. Whos executing the code.
ok i have a widget componenet (healthbar) when a unit takes damage i want it to "show" the hp bar for that client
So how is the client informed when server deal damage?
Nothing that you show tells me client gets any feedback.
well the player pawn is casting to the damaged npc telling it to show the widget
so basicly its like singelplayer but i though since i only want it to be played locally it would work the same way basicly
oh..
Wdym by locally? One pc?
your right again as always
Then why do you have rpc again at all.
im dealing the damage via rpc
and applying damage via server
so the server gets the info also
The server need the info unless you take 0 info from the client.
But normally to compensatw for latency server trust client to certain degree.
Like if client says i hit this person. Server can check if the hitbox is close enough.
But at the end, server the one that deal the damage.
Client just say i hit this thing, go verify.
yeah
but based on this if i have the triggering Actor how owuld i tell it to show it to that client
By knowing how coms are done in multiplayer.
I have a feeling you dont fully grasp rpcs yet.
Server rpc = hey server run this function.
Client rpc = hey client go run this function.
Normal workflow is when server deal damage it will inform client that the damage is done.
Client can then display txt damage etc. Based on that info.
i took a breake with mp for like 2 years so yeah forgot almost everything ...>.<
ApplyDamage(server side) -> set attribute.
Client OnRep->Attribute -> get delta between old and new value -> show damage text
Damage is also done on the server. Server have context (which player deal the damage, etc.)
So server can just send info to the client that deal the damage if neccesary.
i got the actor (owner) i tell all clients "are you this owner" if owner play for him only ?
But you said you only want to show the text to the player that deal damage. So why multicast?
Can just do a client rpc
Either that or OnRep when the attribute gets replicated
And check if the text should be shown.
What does a client rpc do?
client rpc= talks with all clients ?
or client rpc do you mean just tell the server ?
No
No
Client rpc when executed by the server (as it should) tells the owning client of the actor to execute the function.
oh okey, so how do i do a client rpc 
So you can just get the damage causer-> client rpc -> show damage text.
You can set it in the event. Read the bible again, going forward without concrete understanding will lead to more bugs.
are you talking about run on owning client ??
That is indeed client rpc
oh... yeah now i get it just confusing with the labeling yeah i know that
but doing it with a client rpc im still getting the server getting the code
I need to see code
This should be done when applying damage
I dont know what calls that event prior
Or whos even executing it.
-
When server deal damage
-
Server tell the player (damage causer) to execute a function that show the health bar.
Its as simple as that
A neater way to deal with this is to use GAS and the gameplay effect.
or the health bar just shows the player HP and that is a replicated variable ?
Same thing but can just add more stuff like sfx, vfx, etc.
you probably still need a RPC call to trigger the damage effect vfx tho
Yeah but thats done under the hood with gameplay effect.
does using gameplay effects require gas
Yea its part of GAS
finally a reason to use it π
you know what i think i know why its not working
im jsut not sure how to workaround it
the damage is dealt with a RPC since its playing a montage then tracing for hits if hit only server deals damage so it only happens once,
but the damage it run from that code so therefor its running on all clients...
So make a system for it. How its done depend on how you want to design the game.
yeah..
Easiest way is just to let server be the only one checking.
But since movement is predicted this can cause a scenario where player hit something on their screen but the damage is not valid as in server the hit is missed.
But if you gonna go with this then just make sure only server runs the damage thingy in the montage
Anim notify -> get owner -> has authority -> deal the damage
-> get damage causer -> ClientRPC_showDamage
well since the tracing is related to the montage...
oh wait!
if i do this authority check in the montage thats being RPCΒ΄d
will that work ? will it run once on the server
or X client times on the server ... hmm
You can make sure that client doesnt do the tracing logic at all
Just filter with has authority
Doesnt look wrong but never know when i can only take a glimpse.
Also regardless of the trace, unless the client send a server rpc to inform about the damage then this is unrelated.
You gotta make a choice on the degree of trusting the client or no trust at all.
hmm
Something is hit -> has authority (is the server executing the code?) -> apply damage -> damage causer -> client rpc show damage text.
In plain english.
Something is hit. If we are the server, apply damage then tell the owner of the damage causer to show text.
I dont understsnd what this is doing. Ive been telling you about showing text upon server apply damage.
That server rpc you showed makes absolute no sense to me.
Cant c on my phone other than the text that says trace multicast which sound super wrong.
I dont see why you need to tell every player to trace.
Also multicast means server telling every client to run X function.
well since its tracing from a montage wich has to be RpcΒ΄d form what im told thats the only way i could do it
You can rpc the montage but why the trace?
Anywayy i cant debug this further for you.
My advise would be to ensure that apply damage is run on server only.
Then all you gotta do from that apply damsge function is to run a client rpc of the damage causer to show text
There shouldnt be server rpc or w.e u trying to do.
All you gotta do when applying damage (server) is to tell the client (in this case the player of the damsge causer) to run a function to show the text.
Apply damage -> get damage causer -> client rpc ShowDamageText
hm should the widget be replicated :/ ?
just to clarify its no text thats shown its a widget component on the actor itsefl that i set visiblity on/off
Widget dont replicate
It will be printed on the owner of the actor
If the owner is the server then it will be printed on thr server.
Example, a listen server gets a pawn. The listen server is also a player.
yeah i know that
Not possible.
The only way for client to communicate with server is thru server rpc.
A client calling a client rpc will just execute the function locally at best.
Yeah w.e you show doesnt change the facts about rpc.
havn't we been talking about this simple fact for like 4 days straight
hmm
Show the event that call ShowHideHPBar
On phone, screen shoot only pls.
so 2nd picture is the montage thats being played on RPC but since the trace checks for authority the event on hit actor is played on server and from that i deal damage first the after calling that function
this trace is acctualy a pluggin so i guess it might be something with that causing it
you absolutely do not need a plugin to trace between 2 socket locations
true i did it myself before* but i saw this free pluggin and wanted to try a more "advance one" and test it
or do you mean from what class, its the player character BP
this is the root from where the montage starts*
So this is the character bp?
yeah
or its a parentclass of caracter BP
or its the char bp* i jsut have 5 different child classes from it so yes
If the unit base bp is owned by a client then it will print on client.
The only time it will print Server is when the owner is the listen server.
i agree this is news for me to
you know what
im dumb
or
This code ir run on the NPC wich hold the HP bar so the printing comes from a NPC = Server
even if its Client RPC then its still the Npc thats printing it
so i need to run the code from my player bp to tell it to showβ¦
Isnt the damage dealer the player?
The show damage text needs to be in player owned actor. In this case the character the player possess.
It doesnt matter where you call it. You are the server.
(Server)where ever -> the player character that deal the damage -> show damage text.
Hey guys, did anyone know how fix this:
in my dash ability, even I only commit ability on server, but when my client dash, the remaining cooldown time might be strange (I have a GE_Dash_CD, used as the cd class in my GA_Dash, it's only 2 secs, but sometimes the widget says it's 5 secs for example(i literally watch the float value from my ability object!!))
can anyone fix it, private chat if u r willing to help
please +
using UE5.6
u can see
I'm sorry that this video looks strange, IDK why, but, please, I need your help
Looks like your UI may be the issue, not the GE. The UI only displays for a couple of seconds, not the full 5 seconds.
yeh, cause when it receive the CD tag is removed, it'll force the UI to display as ready-to-use
Also, I use breakpoint to check, its' literally 5 secs or sth more
Whats your code that the UI uses to display the starting value of the GE cooldown?
private chatβΊοΈ
Hi, Advice
if im to spawn Npc or stuff on the level ingame whats the most common way to spawn them, from game mode or just call it from a parent or ?
Completely depends on what you're trying to do. GameMode is mostly for handling spawning rules of players. If you're wanting to have continuous spawns of actors at a certain location, then you'd probably create an actor and place it in the world that would handle the spawning of those actors.
If it's just an actor you'd place and they're static in the world... Probably just place them in the level.
huanson
onrep has issues with previous state of a TArray?
I want to read the PreviousContainers
void OnRep_InventoryContainers(TArray<FInventoryContainers> PreviousContainers);
this works for simple properties perfectly but not with container property
Issues how? Compile issues?
I'd start by turning that into a const ref.
no, I can't read the previous state correctly, it seems like its random and sometime it returns garbage
I changed it now to single property
Why arent you using a Fast Array?
As soon you need previous state of a replicated TArray, your first thought should be considering moving it over to a Fast Array.
Does FastArray have access to previous state? I only saw PostReplicatedChange
You can simluate it by having a shadow array in the FA container.
I oftenly use non fast array, its now a habbit π
You update the shadow array when PostReplicatedChange gets called
Which gives you the opportunity to extract the previous state.
How do you keep the orders synced? I thought the array ordering was only valid during that call.
I suppose you could just have shadow unreplicated fields in the array entry too
Generally I find it good practice to always generate a UID for each element.
When using FAs
So to avoid ordering issues
Is there any kind of rollback netcode solution on the market or elsewhere? UE5 doesn't have one by default.
Depends a bit on what you want to do.
Most peeps are fine with what the CMC offers. Other tried their luck with the Network Prediction Plugin (either on Independent mode, or on Fixed Tick). Epic itself is more leaning into Chaos Replication by now, I think.
If you need anything more complex or specific, I wouldn't know what's on the market. If searching for it online hasn't brought up anything, then I would guess that most of those solutions remain hidden in studios that needed them.
we just had client auth physics & hit detection and snapped things into place if they diverged too much
so it really depends on what you wanne achieve
Rollback is usually asked for when wanting to make a fighting game and that is usually not support out of the box I would say.
There are probably several convention (e.g. GDC) talks that brush over the topic, but if there is none available you'd be stuck coding your own.
Or at least adding a third party one
Guys, Iβm currently using data coming from the real server, but Iβm experiencing a problem.
When I jump while running, the character gets pulled back (rubberbanding).
If I jump normally, there is no problem.
Walking or running also works fine.
However, when I run and jump at the same time, the character gets pulled back.
My ping is good, so Iβm not sure what could be causing this.
I usually replicate an array of structs that hold an index and data
Then I just make a sorted array when needed. It's trivial to sort by index because it's a 1:1 mapping
Guys, Iβm currently using data coming
How do you implement your sprint?
I took this system directly from the GASP project because it already has replication.
So I didnβt modify the character at all, Iβm using it exactly as it is.
Well that doesnt say much.
If the system uses character movement component. The data has to be packed and send using the movement struct.
Cpp only btw since you said your project is bp only.
At least for server auth movement.
has anyone managed to get gamepads to spawn local players correctly with "Skip assigning gamepad to player 0" without a player controller and directly geting the gamepad that pressed the button to control the local player that is spawned? I can get it to work with "Skip assigning gamepad to player 0" off but it's only when it's enabled I can't get it to work? any ideas?
The issue is that with "Skip Assigning Gamepad to Player 0" enabled, gamepad indices shift by 1 (gamepad 0 maps to controller ID 1). When you call CreatePlayer, the new PlayerController gets a sequential ID that doesn't match the gamepad.
Solution: After CreatePlayer returns the new PlayerController, manually call SetControllerId on it with the actual gamepad index that triggered the join. You'll need to track which gamepad pressed the button (via Enhanced Input's GetLastInputDevice or listening to InputDeviceConnectionChange), then force-assign that ID to the spawned controller.
You can't fully avoid PlayerControllers for local players β UE requires them. But you can keep them minimal and route all gameplay logic through your Pawn/Character directly.
will help her understand
do you even understand it yourself?
yes if want can do
Do you have a link to more info on Chaos replication?
Scratch the previous questions. Stranger and more detailed new one. What you see here is the output of ShowDebug INPUT, and printing out the name of the controller returned by "Get Local Viewing Player Controller." It looks to me like ShowDebug INPUT says that Player 1 DOES have a controller attached to them. This is backed up by the fact that they can recieve inputs. And, if I were to use the player index to access the player controller instead, it would find Player 1's controller. I'm very confused over this behavior. Any explanation would be appreciated.
Any idea why I am getting this line of warning on tick in the logs?
OldMap size (0) does not match item count (4) for struct (VehicleSeatItem), missing a MarkArrayDirty on element add/remove?
A4WBase::A4WBase() : AVehicleBase()
{
if (SeatComponent)
{
SeatComponent->AddSeat(0, ESeatRole::Driver, "Seat_Driver");
SeatComponent->AddSeat(1, ESeatRole::Passenger, "Seat_FR");
SeatComponent->AddSeat(2, ESeatRole::Passenger, "Seat_RR");
SeatComponent->AddSeat(3, ESeatRole::Passenger, "Seat_RL");
}
VehicleType = EVehicleType::Car;
}
USTRUCT()
struct FVehicleSeatItem : public FFastArraySerializerItem
{
GENERATED_BODY()
UPROPERTY()
uint8 SeatIndex = 0;
UPROPERTY()
ESeatRole SeatRole = ESeatRole::Passenger;
UPROPERTY()
FName SeatSocket;
UPROPERTY()
TObjectPtr<APlayerState> OccupantPlayerState = nullptr;
UPROPERTY(NotReplicated)
TWeakObjectPtr<ACharacter> CachedCharacter;
};
USTRUCT()
struct FVehicleSeatArray : public FFastArraySerializer
{
GENERATED_BODY()
UPROPERTY()
TArray<FVehicleSeatItem> Items;
UPROPERTY(NotReplicated)
class UVehicleSeatComponent* OwnerComponent;
bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms)
{
return FFastArraySerializer::FastArrayDeltaSerialize<FVehicleSeatItem, FVehicleSeatArray>(Items, DeltaParms, *this);
}
void PostReplicatedAdd(const TArrayView<int32> AddedIndices, int32 FinalSize);
void PostReplicatedChange(const TArrayView<int32> ChangedIndices, int32 FinalSize);
private:
void HandleSeatChanged(FVehicleSeatItem& Seat);
};
void UVehicleSeatComponent::AddSeat(uint8 SeatIndex, ESeatRole Role, const FName& Socket)
{
if (!GetOwner()->HasAuthority())
return;
FVehicleSeatItem Seat;
Seat.SeatIndex = SeatIndex;
Seat.SeatRole = Role;
Seat.SeatSocket = Socket;
SeatArray.Items.Add(Seat);
}
Server 0 , 3 Client ?
Local multiplayer.
No server.
It is possible this is a 5.6 local multiplayer bug. I've already found one. But I don't know nearly enough about multiplayer systems to figure that out alone.
What do you mean by "starting with"? I didn't understand the question. Are there 4 clients or just one Pie client?
Warning says if you forgot to mark the array dirty.
Have you actually do that?
yeah SeatArray.MarkItemDirty(SeatArray.Items.Last());
I cant find that in the code but try marking it dirty after you add element to the array?
After SeatArray.Items.Add
yeah its fixed, was needed to make it dirty
SeatArray.MarkArrayDirty();
Not really, also LLM hallucinate a lot. At the very least you can mention that your answer was from LLM.
Presenting it as a solution as if you know if its right will end up shooting others in the foot more.
There are no clients at all unless Unreal sets up a default one (sorry if that's an ignorant statement but I've yet to work with Unreal's online multiplayer). There's no networking in this game.
I have a multiplayer project in Unreal Engine 5. The character movement itself is perfectly smooth, but the camera appears to stutter or jitter while moving. This issue only happens on the client side; the server view is smooth.
The camera is attached directly to the characterβs head (to the mesh/head bone), not to a spring arm. There is no camera lag enabled. Settings like βAlways Tick Pose and Refresh Bonesβ are already enabled on the mesh, and the character rotation settings (Use Controller Rotation Yaw / Orient Rotation to Movement) are configured correctly.
Despite this, the camera still moves in a slightly jittery or choppy way while the character walks, but only on the client in multiplayer. I'm trying to understand what could cause camera stutter when the camera is attached to the head bone in a networked character.
How are you moving your character?
I didn't understand what you meant
the warning happens again, seems like constructor is a bad place to add elements to fast array
LogNetFastTArray: Warning: OldMap size (0) does not match item count (4) for struct (VehicleSeatItem), missing a MarkArrayDirty on element add/remove?
What does your code look like for moving your character?
There's no problem with the editor, but when I package it and play with my friends, there's an issue.
As you're saying that you're seeing this only happen on clients, have you verified that it's not happening due to network corrections?
How can I control it?
Test in editor with network quality emulation, see if it shows up.
That would differentiate if it's the editor build or just the fact that you have zero latency
Dont think you should initialize replicated stuff on constructor but hey what do i know.
You probably did not test with network emulation in the editor.
0 ping is fake multiplayer, always test with ping.
@nocturne quail why fast array for seats? Iirc you get more overhead than regular array for something with small length.
I tested it and I think that's the cause. But why does this problem occur when I walk? It doesn't happen when I just turn around. and How can I fix this?
looking for help with setting up a dedicated lobby server setup
most importantly I am accessing the previous state of the containers
Its not only seats, it has more responsibilities, enter/exit vehicle, Assigning seats, have reference to current attached characters, supports late join clients
The problem isn't as noticeable on a different computer in the same house, but it appears like this on a computer on a different network. The camera only malfunctions when walking
did you mean it only functions when not moving?
cuz that's the only part that wasn't a stuttering mess
Show how your inputs get to the CMC.
It spins smoothly while staying stationary.
yeah cuz you're not moving, the problem isn't orientation. Show the path from your input events to the AddMovementInput call on CMC.
Are you doing anything funky with setting max speed or anything like that?
I change my maximum speed while walking or running.
show how
are you doing any of that in these clips?
that won't work btw, not butter smooth anyway
He is running and walking in the video, but even if he just walks straight, there is jitter
So your current speed modification system will 100% introduce corrections. Disconnect it for now
If sprinting isn't a thing, is the only code that touches the CMC the AddMovementInput?
Yes, I didn't add anything else.
test with cam attached to capsule instead, see if it still jitters.
Could be mesh interpolation shenanigans
The reason I put on the mesh was to attach it to head and use the aimoffset.
I removed the other variables from the CMC and am packaging them.
I disconnected the things you mentioned related to CMC, but the problem persists. Is there no way to fix it while the camera is connected to mesh?
When I asked AI, it said this was related to the network smoothing mode. My current settings are as follows:
don't ever directly modify the max speed, it will be desynced and you get jitters
I removed the motion speed modifiers from the image you quoted. Only the changes I made here remain.
read this to see how to correctly sprint
https://github.com/tomlooman/EpicSurvivalGame/blob/23159c1c856054278119c6694093930abf9ebdfc/SurvivalGame/Source/SurvivalGame/Private/Components/SCharacterMovementComponent.cpp#L23
you should modify max speed before it returns in the same tick frame
I moved the camera from the mesh to the capsule, but there's still jitter.
You sure there's no collision shenanigans?
Add a new default character and compare the settings
Without skip assigning "gamepad to player 0" I have already skipped the player controller part which works when any one of my controllers press face button down. So It is possible to detect gamepad id and which gamepad pressed it. It only gets weird when skipped is enabled. I can spawn all the players when I have it true but they wont be assigned to the gamepad that pressed it. Which is weird behavior
It's done in c++ btw. Bps don't expose the data
I tried making proxi PCs that detect gp input but that wigs out my online multiplayer part. The goal here is to have a dynamic load in for local + online players to play together eg, computer one joins and then creates 3 local players and server also has 3 local players so it'd be a 6 player game with two computers, one client, one host. Which I have working. It's just a little funky is all. It's just skip assigning gp to p0 that screws it up
I have four things that might help you; I can send them to you if you want, but I'm not sure if they'll be helpful.
No LLM stuff pls
I already mentioned that I would send it privately, and the issue is not related to you. He can also write himself. Anyone reading the messages can already see that the first message describes the problem and the second one suggests a possible solution. The person himself is also aware of the situation. Iβm just trying to help. Since nobody knows the details of the project, no one can give a direct or definitive solution.
Wether you send privately or not you are already advised to not copy paste llm amswer as a solution.
You havent seems to acknowledge why you shouldnt do that.
Any idea why character can still rotate inside vehicle? π
this details was missing, which is a solution
bUseControllerRotationYaw = false;
I thougt disabling movement component will disable it automatically, but its not
so have to add it
Hi, This might be a dumb player but creating widgets for each palyer/client should be done with Client RPC on controller or such right ?
there is no reason to RPC the creation of the widget right ?
it cant detect the player hud from the player pawn
Hey guys my NetDeltaSerialize seems to be called every tick, is this intentional? cpp bool FInventory::NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms) { UE_LOG(LogTemp, Warning, TEXT("FastArray NetDeltaSerialize called")); return FFastArraySerializer::FastArrayDeltaSerialize<FInventorySlot, FInventory>(Slots, DeltaParms, *this); }
Shouldn't involve networking at all
WHEN do you want this widget created?
its created at start
NetUpdateFrequency can adjust it, depending on how often you need to rep state change