#multiplayer
1 messages ยท Page 74 of 1
ok, thanks
If role matters, its set before that point
It means whatever you are using as a floor is not net addressable
Which CAC actors usually arent
CAC is pretty bad in best conditions
Its terrible for multiplayer, i suggest you rethink your approach there
CMC keeps a reference to Base
Its a component youre currently walking on
All movement is relative to it
CAC spawns an Actor locally on each machine
They cant be really replicated, and pointers to them dont work over network
hi!
dedicated server crashed with FMemory::Free somewere https://i.imgur.com/OvVCv5v.png
next GC tick if client just open lobby map right from the mp match
is ENetRole "none" when not connected to a server? Or is it authority?
It is authority, and remoterole is simproxy
Figure out which actor channel
Best guess, you manually destroyed replucated actor or one of its subobjects on client
So it means that a character can't walk on another actors that have multiple static mesh components that serve as walkable surfaces?
It can, as long as they are net addressable
wym by net addressable
So the floor component must be set to replicated ?
It's spawned at runtime
Any actor spawned at runtime that has exact same nsme on all machines and is set as net addressabls manuallt as well
Make s mistake here and your clients get disconnected tho
Pretty much - if you can guarantee that the actor/component have the exact same name on all machines, you can mark them as net addressable. With that, you can do some fancy stuff that wizards like Zlo can abuse ๐
My clients don't get disconnected at all nor they really get a position correction (or very small one which is not noticeable)
CAC Actors = worst possible choice to serve as floor
I see
updated. alt + F4 also crashed it. silly me forget to tweak GC tick time
@fathom aspen Time is ticking ๐ฆ
do u mean during pawn/pc/ps etc staff related?
I have no idea
Find a way to attach s debugger to your DS
Crash it
Then jupm to that UActorChannel line in callstack and see what actor it belongs to
I do. I have no idea whats wrong.
got it
thanks
I just find it weird the fact that the log spam doesn't always occur even when walking on the same surfaces multiple times, but I'll replace my CAC as much as I can
You can do almost the same thing without cac
With normal attaching of actors
You can even expand it into full modular data driven spaceship system
Not so easy with CAC
thanks. found . pawn.
Basically, instead of CAC you put named sockets on the CAC atrach points
Then you create a data asset that defines a spaceship
You have a class for spaceship core actor
Array of structs for modules, which contain a class, atrach point name and whatever else you need to slsp it in place
Then spawning a spaceship is spawn core, spswn all modules and attach them to correct place
With CAC you dont have this flexibility, but without cac your spaceship actor wont look whole in blueprint editir viewport
Yes Yes, No doubt I could use data driven system, I'm working on a project which I do not own that's the way the ship has been built, event tho I had already told them that CAC were bad, now I have to announce them that they need to redo everything xD
I think the big advantage for a CAC is in fact being able to look at it in the BP editor viewport
Will do on the new version !
Just need to take into account the logic that some CAC had
I wish they actually cared about the CAC ๐ญ
remind me this - are "core" actors (game state, player controller, pawn) are guaranteed to be replicated to just connected client before any "regular" gameplay actors?
No
eh
PlayerState wull generally arrive later too
what is CAC?
Engine will try to replicate them in order of net priority
Child Actor Component
so if some of my replicated actors initialization are dependent on PC I should notify them from PC's autonomous proxy on begin play like "hey, PC has arrived"?
aaahhh oki thanks
I think GameState is like the only one guaranteed to arrive first, because it's what kicks off BeginPlay
onreps can help
(I know, it just tells the world settings to dispatch begin play)
right, thanks
As they will fire when netguid is resolved (both actors replicated)
But only guarantee you really have is that gamestate will replicate before any actor on client calls beginplay
Its still not guaranteed to arrive first or in any particular order
My advice is construct entire object graph from handlestsrtingnewplayer on server
And set onrep references you need there
If ant dependent actors are level actors, they will be there before PC
If they are client auth, just spawn them from PC client side
hmm I don't really get it what you are suggesting. not sure what do you mean neither by construct object graph nor handlestsrtingnewplayer. Is there any article to read on those?
Your A is depending on PC
HandleStartingNewPlayer is GameMode function that by default spawns Pawna by calling RestartPlayer
After Super, you spawn A immediately
Then either set onrep A on PC or onrrp PC on A
Then ypu dont reallt care which order they arrive in
All objects depending on your PC with their references to each other
Are object graph
Thiz doesnt solve 3 way dependencies (A needs both B snd PC to init)
But it does solve 2 way nicely
sounds good, I was thinking about the topic since I had a related problem with replicated actor initialization on game start
How can I buy an item on the server from a shop widget without RPCs ?
you cant
the widget can call an rpc on a class that can actually send them, like playercontroller
Unless you're a listen-server o_O
All I want for christmas is for OnRep to happen after BeginPlay.
I mean it makes much more sense for it happen before, but if you want so, you can defer call it with some hack
Screw that - give me UHT namespace support
CopyProperties is only called on the server right?
Yeah
Why does it make sense? If I knew the reason I'd probably have a much easier time remembering and reasoning about solutions.
Because you want the replication callbacks which are meant to initialize/set stuff to have happened by the time BeginPlay was called
Also BeginPlay is the function that gets called when an actor/object spawns
If OnReps were not called, it means that data didn't replicate by the time it was spawned and that's not fun
I don't have my blueprint childclass member variable values before BeginPlay though. :(
Or, I want to broadcast OnRep calls, but none of the BP listening have been created yet.
Well not all values are there before BeginPlay
Only those who can potentially make it
With those being POD types as they used to be called in cpp anciently
It just means I can't have my replicated values get sent to listeners by the replicating object, for initialization.
and special cases make me sad.
I don't see this as a flaw with UE, more like a flaw with your design.
Is there a different pattern you recommend?
This is data that changes regularly in the server and there are umg elements that need to be updated to reflect that on the client.
I mean yeah, bind to these UMG widgets where it makes sense to you. Usually BeginPlay is good. And I would at least expect that you initialize your widgets with values (so those OnReps that made it before BeginPlay will be handled by this form of initialization)
There is no specific pattern, you have to adapt your code to how things work
I'm not using UMG bindings as they don't change that often. Well, I guess I am for one.
The ones I'm talking about here are cards that change when you play them and draw a new one. I have a delegate on the ActorComponent that's replicating the values, sitting on the player controller, which registers bindings for the delegate and passes them to the widget. Which works great. Except for init. The widget is created last and so I have it request initial values from the player controller in its BeginPlay.
I fail to see the issue - if the OnReps are firing before BeginPlay then the initial data replicated from the server is being set before BeginPlay.
Therefore if your widgets pull an initial value during BeginPlay then they'll receive that initial data even though they missed the OnReps.
@thin stratus was your compendium modeled after anything? Wondering if there's anything similar I can read in unity, the knowledge does carry over but I'd like to see some actual implementation, the docs don't really do that from what I am looking at
No, I mainly gathered info from all the docs and scattered resources and wrote that into one doc
so afayk nothing similar like that in unity?
I also gave up on Unity multiplayer cause their native gameobject stuff is half baked atm and I can't be arsed to pay for photon
they did an update recently (today), idk what it added though
They have a road map for the networking stuff
There are still some fundamentals missing
I noticed how using velocity on RigidBodys can cause client lag but that's how far I've gotten so just trying to see more examples
isn't there like a free version of photon btw? why dont you use that
Pretty sure in unity you gotta code the Movement Component from scratch or buy one from the store
I heard it's pretty good for a free version iirc
Proton is CCU based
what's that mean?
The free version doesn't get you far if you want to release
any major examples? I've asked this question before and got some different responses compared to this
Well CCU means Concurrent User
So the more users you have the more you pay
Free doesn't cover anything
(kinda cringe example) but what about that Dani youtuber? Did they pay for multiplayer support? How could they make a game like crabgame since every lobby can have so many people?
The shooter?
Crab Game is a First-Person Multiplayer game where you fight for the ultimate cash price in different minigames based on children's games, until only one player is left to claim it all. Definitely not based on any online streaming pop culture korean tv shows, as that would get me in legal trouble, so we're certainly not doing that.Features Up to...
I'm overriding APlayerState::CopyProperties(). I turned on seamless travel on the game mode. I'm calling UWorld::ServerTravel to initiate the travel, but it's not getting called. What am I missing?
Ah I had something else in mind
No idea
it has 35 player lobbies and this was made before Netcode pretty sure
Maybe they simply coded it themselves
Games like Hero Siege which is done in Game Maker also coded the multiplayer themselves iirc
Aka handling the packages and all the underlying stuff yourself
coding multiplayer in gamemaker...
that sounds horrible
well that sucks then kind of puts a dent in my plans
Servers are probably not in gamemaker hehe
I literally went back to UE due to the lack of multiplayer support in other engines
ever try godots multiplayer? Only tried it for a second but it looks like it doesn't have much support either
You might want to breakpoint the code where it's called
Which is in the GameMode
Not GameModeBase*
Yes, they basically use ENet as their base and expose low and high level
What makes Godot tricky is that multiplayer seemed to have been an afterthought. There are also barely any guides of how to properly utilize it
They have rpcs etc and the simple stuff also all works
But more complex things seem to be a lot tricker
which call? ServerTravel?
Copy properties
I don't see that.
Go to the PlayerState and look for usages in the solution of the function
Shouldn't be used a lot
I followed it back to a number of calls that are doing server travel stuff, but none of them are hit. I got lost trying to connect the two functions.
yeah I noticed there like only 1 video on the new mutliplayer tools that have been added to 4 so far and it's pretty rushed.
alright thanks for your help I appreciate it
so there's not some obvious step I missed?
that's mostly what I wanted to know, or if I should keep digging
From what I know if you seamless server travel you should get that call
Not sure atm about any small things that could cause it to not call
Well we are talking about actually traveling as the server right?
And taking connected clients with it
oh what, my new game mode is based off GameModeBase and not my game mode. oops
Rip
Make sure to reparent the GameState too
They can't be mixed
Either both Base or not
when should you use AGameState vs AGameStateBase and AGameMode vs AGameModeBase?
Base when you probably aren't doing a multiplayer game. But honestly I would always use non Base
They split that 4.14 or so to give people a Gamemode that is not overloaded
But I think that's kinda pointless
I checked SeamlessTravel in the BP, but it's false in CanServerTravel().
oh, this is a PIESeamlessTravel
interesting, it's an experimental feature
You can't seamless travel in the editor@sterile plaza
The experimental feature at least for me still crashes the editor
Best is to test in standalone
yeah... it's failing to get member variables defined in BP, in the BeginPlay of the component
That sounds like a generic programming problem
it doesn't happen when I don't turn on seamless travel
and why would it not be available in the beginplay?
just starting to make my enemies. Am i able to use root motion in multiplayer? or does it require a certain setup or anything?
Not sure I can 100% answer this, but from what I learned and saw:
- RootMotion on AnimMontages work fine (if used on a Character)
- RootMotion in AnimBPs might not
I know that Paragon (Epic's cancelled Moba) did the sort of RootMotion stuff by hand. So they basically ended up calculating where a character would stop and blended into stop anims etc. I haven't really encountered a project yet that uses RootMotion in Multiplayer in AnimBPs.
Depends on what Blueprint and when
Rogey, was planning on just using them for my attack anim montages, the rest of the animbp will lock in place
That should be fine, yeah
i think i just got it working, its not too bad, little bit janky xD
It's important that you play them locally too
The CMC syncs it iirc
But it might be overall a bit janky. Might need to flush server moves before executing the Montage (c++ only function, would need to be exposed to BPs). That's at least a requirement for RootMotionSources.
ah right, ill dig into it more once ive learnt a bit more. Its acceptable for now, will just need polishing later. Im on my first project so trying not to get too hung up on things and will come back once ive learnt better practices
Alrighty
yeah i havent even touched C++ yet and dont plan to for a while ๐
also, will root motion try to go through a player if it say jumps forward? or will collision stop it?
Iirc collisions in root motion can be unpredictable
Do a capsule sweep to check for room
I released the updated version of the already 7 year old "Multiplayer Network Compendium":
https://cedric-neukirchen.net/docs/category/multiplayer-network-compendium
It's now a Docusaurs (React + MDX) page, with proper Table of Contents, Sidebar, Light and Dark Themes, BlueprintUE support for Blueprint Examples and more.
I ultimately want to provide access to the mdx files via a GitHub Repo, so other users can contribute to it.
There is also a new "Additional Resources" section with links I took from the pinned section here.
The C++ Session Tutorial is also part of the tutorials now and with the new website I will hopefully have an easier time writing new things.
The old pdf and website links should redirect properly, but you may need to refresh your cached websites.
sick!
Hi, I need player specific data to exist only on the client, where should I put it, PlayerController
local player subsystem
hello, if i do an open ip address console command, how can i handle the server not responding?
In BP or C++?
BP GameInstance should have Travel Error and Network Error events you can add and use
C++ has them too, but they have to be bound via CoreDelegates iirc
// register the engine with the travel and network failure broadcasts
// games can override these to provide proper behavior in each error case
OnTravelFailure().AddUObject(this, &UEngine::HandleTravelFailure);
OnNetworkFailure().AddUObject(this, &UEngine::HandleNetworkFailure);
That's part of UEngine
So basically GEngine->OnNetworkFailure()
The BP ones are weirdly routed through the bindings above
Where it tells the GameInstance about it
But you can just listen to the callbacks yourself
Oh lordy - it is here!
thanks i'll take a look at it ๐
Yeah it's probably full of errors cause it was way too much work and I need a break from it for a few weeks now xD
Anything in particular you were curious to know?
It's networking stuff is quite barebones in comparison to Unreal. And pretty much - you have to handle everything by hand.
I've even been seeing bugs with some of the new nodes that are supposed to make things easier - as in, sometimes, they just flat out aren't working.
We can talk about that in #programmer-hangout at some point. I'm gonna step away from the PC for a bit. :D need a break after all the Compendium stuff
Ohh - this site is fancy
the site doesnt support my preferred dark mode out of the box.. literally unusable
i have to manually select dark mode
Oh okay but why PlayerController usually ? Why not in the PlayerCharacter/PlayerState or the gamestate ? I'm currently using PlayerController without knowing exactly why ๐น
Anyone about?
you can use player state or player pawn
but not gamestate\
your pc needs to own the actor for server rpc to work
oh i see, its why the playercontroller is the most used in this case. Because it owns the widget, right ?
or not even that
Yeah I see
we told me that i should avoid using lot of RPCs
so thats why i asked a non-RPC way
Ok ok
there is no other mechanism available
BeginPlay is called on both client and server
So every local actions, to be performed server-side, should be sent via RPCs (if replication is needed)
I have the player controller own a hud reference which has all my widget creation, destruction, and references. The Controller is a great middle man since a version exists on the server and the client. Then the widgets can call server functions from the controller. I find the controller is like the middle man for the client side stuff and the game. I like to have the game state as a middle man for the serverside stuff and the game.
I see, pretty cool actually. I like using the gamestate aswell for this but playerController was like only for HUD personnally but now i'm going to implement some networked features with LocalPlayer actions (most often with widgets)
RPCs I belevie are fine as long as they aren't on tick. If it's 100 things doing rpcs in a 2 minute match, but those rpcs are staggered and about 1 a second, it's fine. It's when you have 100 a second that you run into trouble.
Oh okay nice
ye in that case better batch them and make a single bigger RPC
but i had a question, what if a basic function/event (set as not replicated) is called from server-side via an rpc. It looks like the function/event is replicated since it is called by server, I might be wrong tho
(or avoid it if possible xD)
It's not necessarily wrong to have a lot of RPCs though. There are use cases for it. The CMC sends a ton of RPCs generally.
But often it's just not needed.
Just don't do it reliably if you do so ๐
yeah unreliable ones
I'm just using reliables for important game features
I unreliable RPC on tick. Fite me โ
I like people that break boundaries
My biggest issue with networking now is getting my packaged listen server to let clients join. It works perfectly as an editor server. Not sure why the editor version works but not the packaged version. Anyone know if listen servers have been broken?
I haven't had any issues. Did a Steam test like 2 weeks ago
Is this LAN or across the internet? Should work fine regardless.
Unless it's across the internet and you're not properly dealing with port forwarding or using some kind of other system I guess :p
Sorry to ask this but i need to know. What if a basic function is called from server-side via an rpc. The function becomes "replicated" so i don't need to mark it as replicated ?
Functions aren't replicated
I have the most basic game ever. I have 2 blueprints in a player controller and 2 maps. J for Open level with the noip address, and H for open level as a listen server. And it's broken. Server just will not work when packaged.
Actors and variables are.
I meant Events
My team needs netcode devs for online play
They are RPCs or not. An RPC is not replication
I meant marked as replicated when you use the "Replicated" keyword with UPROPERTY()
Look in the logs and see if they say anything. A lot of the time there's some kind of message in there.
That's a variable, not a function
Do packaged games have logs?
Like imagine if i have this function : c++ UFUNCTION(BlueprintCallable, Replicated) bool HasEnoughMoney(float InMoney) const;
The function is called on the server ?
Development builds should have logs. "Shipped" packaged builds don't I believe but you should be able to switch pretty easily.
Although you can also enable it for shipped builds in some way I just don't exactly recall how though.
It won't compile. Replicated does not go on functions
but what if in a RPC, i call the same function without "replicated" mark
You are bouncing back and forth between concepts
Yeah mb, then ReplicatedUsing_(any repnotifiy)
Can you collect your thoughts and ask your question in a less confusing way?
What logging should I use? This is all I have. This is all I'm testing. How can I get these 2 nodes wrong?
You've jumped between multiple different concepts.
Yeah sorry let me some time
i'm coming back later with a relaxed mind
and a good question
I would just try 127.0.0.1:7777 instead of that. I've absolutely never seen that before and have no idea why that even works in the editor honestly. With the log thing I was referring to that the engine often tells you what went wrong with connections etc. you don't need to log anything your self but just look at if there's anything in the logs ๐
Yeah I just want an old school listen server so my son can make maps and play with his mates over the internet. What you have there is a lan address. I've got NoIP redirecting to my PC and having my computer as the server address. It works fine until it's packaged.
I don't want to screw around with paying money for anything or some hugely complicated set up. I just want them to type in my IP and connect to my server and play.
Not sure then. I've never used this in specific but listen servers definitely do just work as long as the server can be reached by a client.
I would still recommend making a development build and just looking at the logs though. Perhaps it tells you it simply can't connect or perhaps something else doesn't work ๐คทโโ๏ธ
That's what I'm trying to get to work. But I don't know what logs you are talking about
In the folder of the packaged build once you've ran it it should create a log in there.
Unless your build is set to a certain configuration, then it indeed doesn't do it.
Really great job. Thx you
I click file>package project> build configuration>development. Then file>package project> windows(64bit)
Ooh I'll have a look
What Unreal version are you using?
4.72.
If you go to your project settings there should be a "packaging" menu with at the very bottom all the settings.
Yep. I left it default.
can you set ownership of an actor on a client? ie, call the function "set owner" of an actor from a client connection?
or is it only the server that is able to set ownership?
No. The server is the one responsible for setting and maintaining the owners.
Here are my settings
Should just be fine ๐ค
I'm currently making a build too to test.
Although with my own project. But I'm pretty sure development should just generate the logs.
It's weird. 2 single maps. Start map. Game map. And 2 buttons. Host and Join. LOL It couldn't be more simple of a multiplayer game.
I had to do port forwarding on my router though
I tried to bring some light into your dark world.
You can use "What's my IP" on google to get your current IP address. Then you just need :7777 for the port
I'm aware how port forwarding works. But I can't really tell you what the problem in specific with your setup is. Hence why I keep suggesting the logs ๐
But if those are no where to be found it's a bit weird lol.
Only server. Do a server RPC to request ownership of something.
You don't want client's to be able to do it anyway.
Found them
Man these are huge!
I don't know what I'm looking for
Look at the log for your client and see if there's at any point any 'connecting to server' logs or similar.
Usually you can skip a decent part of the beginning of the log because it's just initialization nonsense.
But do make sure that you actually attempted to connect to the server with the session log you're searching through.
Cheaters about to have a great day if that was possible ๐
Thank you. This is giving me ideas
Hi, if you have an actor in the level that emits a long lasting smoke effect trail, is that by default replicated? Thanks
We need to normalize "initialization" only logs ๐
Generally VFX are not replicated it may however be that your smoke is on an actor that is replicated. In that case it could very well show up.
So we can rid a lot of cruft in 99% of logs
I mean.. Unreal should just enable logs in the first place IMO. It's absolutely nonsense that it's disabled in shipping builds unless you very specifically enable it in some "hidden" build variable xD
I feel like it is pretty common for games to do that though - so I have no complaints.
It's just weird Unreal doesn't do it yeah xD
It can be so useful. It's not a golden ticket out of all scenarios but depending on how your team implements logs too it can be a huge help. Also pretty sure BP errors get logged right?
thanks for the clarification, yes i have an asset called boom and it takes care of the explosions, it says its replicated. So probably the logic is already there. I wanted to make a smoke from the ground up but given that its must be replicated I assumed all clients must spawn them. I guess using such asset will remove this burden.
You can spawn a replicated smoke actor for example sure. It's probably the easiest way although not necessarily the best in a lot of cases ๐
The more common way is to bundle VFX based on an event that is already being send to everyone although that definitely depends on the use. Imagine you have a platformer game where if you jump you get some particle effects going on then obviously you would just want to wait for an incoming "jump packet" and then play the VFX based on that. To name an example.
But again. Just depends on what you're doing. Spawning an actor my be perfectly fine ๐คทโโ๏ธ
Anyone else have this bug with 5.1? Pawns that go out of net relevancy and come back in are still invisible to each other.
Simple test: in a fresh third person project, open up the character's blueprint and change net cull distance to something like 10,000. Put it into 2 clients dedicated server mode. Start game. Run outside of range, disappear, run back in, and never reappear. wtf?
Anyone still here?
From what I can tell, everybody left to party
Not me, I'm at work. All weekend.
So I did the logs on my listen server. It's weird. The Editor Server which works, gets this:
"LogNet: NotifyAcceptingConnection accepted from: 60.242.81.333:49935"
but the packaged Server doesn't do anything. The client package when it's connecting to the editor server, gets to send this:
"LogHandshake: SendChallengeResponse. Timestamp: 12.670132, Cookie"
But when the server is packaged, the client gets this:
"LogNet: UChannel::Close: Sending CloseBunch. ChIndex == 0. Name: [UChannel] ChIndex: 0, Closing: 0 [UNetConnection] RemoteAddr: 60.242.81.333:7777, Name: IpConnection_2147482532, Driver: PendingNetDriver IpNetDriver_2147482533, IsServer: NO, PC: NULL, Owner: NULL, UniqueId: INVALID
[2023.04.07-12.33.12:477][672]LogNet: DestroyNamedNetDriver IpNetDriver_2147482533 [PendingNetDriver]
[2023.04.07-12.33.12:477][672]LogExit: PendingNetDriver IpNetDriver_2147482533 shut down"
I don't know what it all means. When I have 2 BP nodes in the entire game, what is it that I need to fix?
GPT4 says this:
Firewall: Check if your firewall settings are blocking the packaged server from receiving connections. You can try temporarily disabling your firewall to see if it resolves the issue.
Port forwarding: Ensure that the necessary ports are forwarded correctly in your router settings. Typically, for Unreal Engine, ports 7777 (UDP) and 27015 (UDP) are used. You might need to check your game's documentation for specific ports.
Server settings: Verify that the server settings in your packaged game are correct. Ensure that the server IP, port, and other necessary settings are properly set up.
Network configuration: Check your game's network configuration (DefaultEngine.ini) and ensure that there are no discrepancies between the editor and packaged versions of the game. You can compare the network settings in your editor and packaged game to see if there are any differences.
It also said like 4 more but I only thought the first two were really key for now tbh
Are you testing this on the same PC?
heyy everyone, so can someone help me blueprint out a way for someone to interact with a door, and then teleport somewhere in the map when in a session. However only they teleport and anyone else can follow them through the door. thanks!
im really bad with the blueprints and such
Hello, I have some replication problems.
That's my structure of things that are related to the problem:
class EquipmentInstance : UObject
{
UPROPERTY(Replicated)
UObject* Instigator;
virtual bool IsSupportedForNetworking() const override { return true; }
}
struct EquipmentEntry : FFastArraySerializerItem
{
UPROPERTY()
EquipmentInstance* Instance;
}
struct EquipmentList : FFastArraySerializer
{
UPROPERTY()
TArray<EquipmentEntry> Entries;
}
Whenever I create an EquipmentInstance assign a valid Instigator to it, create a new EquipmentEntry I assign the EquipmentInstance to, and mark the entry reference as dirty, the Instigator doesn't get replicated.
On EquipmentList::PostReplicatedAdd entry containing the created EquipmentInstance has a nullptr Instigator.
That's how I create a new entry:
void EquipmentList::AddEntry(UObject* InInstigator)
{
EquipmentEntry& NewEntry = Entries.AddDefaulted_GetRef();
NewEntry.Instance = NewObject<EquipmentInstance>();
NewEntry.Instance->Instigator = InInstigator;
MarkItemDirty(NewEntry);
}
I do the following with the newly created EquipmentInstance:
if (IsUsingRegisteredSubObjectList() && IsReadyForReplication())
{
AddReplicatedSubObject(Result);
}
Does anyone have an idea what may be wrong?
UObjects don't replicate, only Actors.
The thing is that I'm using something else to replicate the UObject, hence it should work
I have the FFastArraySerializer inside an ActorComponent, which adds the created UObjects into its own replication subobjects list
the uobject can be replicated
You implemented all of these?
virtual bool IsSupportedForNetworking() const override { return true; }
virtual bool ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override;```
On my UObject I only implemented IsSupportedForNetworking
I shouldn't implement the rest of the functions since it's an ActorComponent the one responsible for deciding when to replicate them
What do you mean "what do I get"? My override makes it always return true
ah
Even if it was an actor, you'd still have to implement GetLifetimeReplicatedProps
why are you using a uobject if you want to replicate its properties?
Because I don't need to flood the replication channels for such a simple thing. As you can understand from my code snippets, I'm making an equipment system, and there are many equipment instances, which can be handled by one single component rather than making them handle themselves. In my game the replication channels are very important, and I can't use many of them for things that can be implemented using one single channel instead.
fair enough
I haven't personally added replication capability to uobjects, so I don't know from experience what you need to do.
Nevertheless, I forgot to mention that the ActorComponent holding the EquipmentList marks it with UPROPERTY(Replicated) and implements the GetLifetimeReplicatedProps() using the DOREPLIFETIME on EquipmentList.
I don't think I'd expect Instigator to be replicated here, as it lives inside something that doesn't support property replication yet.
It should be replicated. I have already implemented an inventory system which replicates some UObjects which store 2 replicated objects, but for some reason the equipment system doesn't play well
So I'm trying to figure it out
I can tell you what I know based on replicating actors and actor components, but if you're rolling your own replication, I don't know that I'm going to be much help unfortunately.
does EquipmentInstance need to be a UCLASS?
Yeah, it must to, however, I didn't write the macro in my code snippet
k
Sounds like you already have a different case working, but maybe reading through this will remind you of something you've missed?
https://jambax.co.uk/replicating-uobjects/
For the inventory system I wrote, item instances were structs, so I never ran into this.
I have a general question just to see how people deal with this stuff. I have a few OnRep functions that I use to set cosmetic data on my characters. These onrep functions inject some information from the PlayerState about the network client. During standard gameplay all of this works well, and I have 0 issues.
Startup, however, is an absolute nightmare. The client and server have different initialization orders, and the clients get their PlayerStates long after all of the onRep functions have processed. 50% of the references required aren't available when the rep functions fire because the clients have not finished setting up their pawns, controllers, player states, components, or anything else that's required to actually to bootstrap a player.
How do people normally handle this? Should the onReps call a generic function and I just have to manually call the function a second time?
I was chatting with people about this last night. I'm still hoping there's a more elegant way to do this, but I've ended up having the client systems collect their init data once they're up and running. Essentially what you're proposing.
Apparently I did everything in a correct way, the reason why it doens't work is because I'm using the very same inventory system to store the items the equipment is created from, anad the inventory manager component is stored on the player controlled, which is not replicated to the proxy clients, which means they cannot know the instigator (item instance) that created the equipment, and perhaps that's the reason why it's nullptr.
However, I have a TSubclassOf<T> in the very same struct where the Instigator doesn't get replicated, and it's nullptr as well...
yeah, if other clients need the data, it can't be on player controller.
However, the equipment manager component is on character class, so it should work
The equipment manager component is the one holding the fast serializer array containing the uobjects I want to replicate
It's infuriating to me that the boot orders are not predictable. It's looking more and more that I'm just going to have to write something that is in charge of one-time setup which seems like a pretty large waste of time for something so small. I have a pretty good workflow for general runtime updates and I basically have to deal with all of it in two different ways.
I was kinda just wondering if there was a standard practice for handling stuff like this, or if it's basically a free for all
Can you go over all the relevant components, actors, uobjects, and who their owners are? I'm getting a bit lost.
I think the only relevant ones are the EquipmentManagerComponent that recides on the player character. The component holds the EquipmentList which stores an array on EquipmentEntry that contains the EquipmentInstance that has to be replicated
My understanding is it is predictable. You're going to get OnRep calls before BeginPlay on that actor.
AEquipmentManagerComponent?
It's a component, hence U
right, meant actor component
Yeap
what type is equipment list?
Fast Serializer Array
I don't think I can keep track of all of this in my head. I'd need to see all the code. Unfortunately work starts in 10 minutes. :(
Hmm..Maybe I need to do a little more testing, between my server and the three clients each one of them tends to have a different order every time I look
My one ends in 10 minutes ๐
if you get all the classes in a pastebin or something, I'd still like to take a look
The Fast Serializer Array is an UE thing
I'm generally familiar with it.
Well, since we don't have much time, I'll probably try to figure it out on my own. However, thanks for the help ๐
sorry, I have coworkers who've set up uobject replication, but I haven't personally done it
and like I said, my inventory system used structs for all my items and things since they're just data
and those replicate just fine
so I can give you the standard stack overflow answer, "rewrite your entire program to be different, then it will work" :P
I think at the end it doesn't make difference, but maybe I'm not familiar with replication enough, or simply missing something in this context
at least you've gotten it working in another context right?
so in theory you can eventually find the discrepancy
Yeah, I will try to follow the whole thing from there
I have custom replicated uobjects almost exactly like what you're describing
I would probably investigate replicating subobjects first. Make sure everything there looks right.
Did you read the snippets I've sent? Does anything come to your mind of what I could've missed?
I briefly looked at your code, I don't see a line adding the new object to the subobjects list in the addEntry function. Is that Instigator already in the subobjects list?
Also, I have to mark each one of my UProperties in my uobjects as replicated, or they do not send over the network
I have this after I create a new entry
You're trying to replicate this guy, right? Is that variable added to the subobjects list? You will have to nest them if you are replicating uobjects inside of uobjects
Yeah, each one of the objects that I want to replicate in EquipmentInstance are marked as UPROPERTY
oh yeah, does the instigator support being replicated?
I probably isn't, I'll try to replicate it
Check to see. If you pass in a UObjectA to UObjectB, you need to add ObjectA to ObjectB's subobjects and set the property as replicated. Nesting objects and replicating gets a little messy
You also have to remove them from the subobject list manually once you're done with it or you'll have a reference preventing garbage collection of the object
If my game involves moving between levels often and PIE doesn't support seamless travel, does this mean I'm going to have to test most everything in standalone? If so, that's highly unfortunate.
I have an inventory manager component which holds the item instances the equipment is spawned from, and the item instances are passed to the AddEntry as the Instigator. Are you saying that the equipment manager component, that has to replicate the equipment instance that holds the item instance, has to add the item instance to its replicated subobjects?
The thing is that I have a TSubclassOf inside the UObject I'm trying to replicate, and it's not replicated either, it's nullptr even though it isn't on the server side
This prolly won't help but one thing I've done is in the Game Mode BP I use Event OnPostLogin which only fires once the player has been given a Player Controller
You would then multicast a message telling client systems they can go ahead and get their previously OnRep'd properties?
Yea that's what I was thinking
Either multi RPC or perhaps a Run On Owning RPC, not sure tbh. Just thought I'd throw it out there.
it's a nifty time to be aware of
ya
timing of initialization is always awkward
I mean it's technically maybe "too late" but during those awkward moments of initialization I think it's okay to have a bit of loading going on
I currently use it to animate my player stats in the widget, i.e. health/stam/mana bars grow from zero to full size as the player spawns in
Could see it being a bad choice if, for example, you want the player to see the pawn with cosmetics already applied the moment the screen shows anything. Might have to work some weirdness there
Something like a full-screen loading widget that hides things for a second heh
Any suggestions for working on a game that switches between ~5-10min combat and then a draft screen? I was switching to a different level and using seamless travel to persist data. But that doesn't work in PIE. I'm hoping there's something to this that I'm missing that would make developing and testing this easier.
I haven't used this event much, does this fire before or after a PlayerState is given to a client? My largest pain point is that the PlayerState is given to clients near-last in the list, and the PlayerState houses a lot of data that determines the cosmetics of the Character actor. I was actually thinking about triggering a rebuild on PlayerState's beginplay to ensure it was present
Hello guys i have a Problem with my Character that the character while moving looks on other Clients laggy does anyone know how can i fix that? https://gyazo.com/d904077210cb25bca96caef270ceb058
Any actor that is replicating these objects needs to have a valid outer and have the object added to its subobjects to replicate. This includes nested UObjects
If you are handing objects to a new owner, you also need to update the outer reference
using UCharacterMovementComponent?
yes
Off the top of my head it looks like the client and servers do not have the same movement speed
i try with a clean project and have the same issue
I've literally had this same issue. But I don't remember what I did to solve it.
didnt change anything on the component just created new character with camera and add movement inputs
can you show the movement component properties?
also, did you enable replication for other things like the mesh and the collider?
edit: because I don't think you want to, movement component should handle these on the client
there we go
after changing it back to 100 its not laggy anymore
I had that when I refactored an actor into an actor on the player state. Player state ticks WAY less often.
thanks for directing me a bit closer to my problem ๐
no problem, just talking it out with someone often helps you figure it out
Player Controller is before Player State iirc
Even so, I am forced to wonder if that Event doesn't give you the timing you want, Alduron
It does, sometimes. The way I'm solving this right now is that Pawn, PlayerState, and an OnPosession repnotify bool all send a unique message. Once all three messages are received it calls a custom event that fires only after everything I need is ready
Hello! I have a question that's probably not super easy to answer, but I was wondering if someone might be able to explain to me how the CharacterMovementComponent synchronises its server and client deltaTime? I've been combing through the code for a good while now but it's a little tricky to know for sure if I see what it's doing.
Context: I've been trying to implement a simple version of what the CMC does but for my own movement, but unfortunately I can't get the movement to be deterministic, even though it should. There's still slight delays in changes to velocity and acceleration, and as a result it means where something might move past a wall on the client the server may just barely get snagged on it, causing a huge desync that would correct the client back against the wall - even with zero latency. As far as I can tell, the only reason I can think of as to why this happens is because of slight differences in their delta time, which is why I've been combing through the CMC for guidance. But unfortunately I've come up short. Any help there would be super appreciated. Thank you!
Nice, with a Do Once?
PlayerState calls I believe immediately after controller on server, and calls after pawn, posession, and controller on clients
No do-once for that one, but I will probably add it
May not be needed but I'm paranoid about that
Like I said, my bootup is a nightmare of code. I'm trying to streamline it so I don't have a bunch of wasted calls. The new messages are part of that effort. I also have an activation function in all my components that returns a failure if a reference is missing then retries to activate in a few frames
These feel like Band-Aids though...and not solid code practices
I'm somewhat surprised there isn't a more standard practice published on this
I assumed I was just an idiot and there was some simple way to handle all of this. It seems really silly that Server has one order, client 1 has another, and client 2 has another. I don't know how to plan out activation if I can't rely on anything being available from one machine to another. I had a custom dependency manager but I just replaced it since it required specific manual configuration
it does seem like there should be an authoritative article on how to do this in a standard case
I've looked a bit at some of the project examples but I would need to dedicate a large portion of time to read through and understand their order
does anyone know how multiplayer FPS's replicate a 3rd person model to others while keeping only the arms shown to the client?
I imagined having 2 meshes and apply the inputs to both but only show the hand mesh for the client and show the full body mesh for others
but wondered if there's a better solution
pretty sure that's the common approach
local player using first person blueprint, clients using third person blueprint for the same pawn, etc etc
huh?
so it's a completely different character?
I imagined 2 meshes within the same character
dunno how that would work unless you changed animation blueprints on the fly
No it's the same character, The meshes are different.
yeah I think it's done multiple ways
that seems most reasonable, thanks for the help
So with that approach how are you playing animations correctly? some kind of animgraph blend by bool or?
It's either the same mesh with FP/3rdP cameras or two different meshes and animation layers.
each mesh would have its own animations
ok so when you load into the game you're setting the mesh and associated animbp
i've actually not touched animations yet so I'll have to figure that out
just designing it before I get into it
if it's on one first person blueprint then you have to do some logic to replicate the fact that this is switching to the full mesh and animation blueprint for the simulated proxies
sure I can figure that out
the hardest part for me would probably be getting animations and testing with them
IIRC the CMC sends over all client delta values and the server uses that to simulate the movement.
What you should note however is that Unreal's physics engine and the engine them selves are not deterministic. You're going to get some amount of inaccuracy regardless. Even with the normal CMC. Also packet loss kind of ruins this anyway.
Another note is I was messing with the CMC input my self at some point and this is a rather important thing to do is that you round the input vector to match what will be send over the network. The CMC has a less accurate version for input because it doesn't need full float precision so it rounds the input vector before doing anything locally with it regards to movement to whatever precision it uses to prevent desyncs. Sounds like that could also be a potential pitfall here.
That's interesting, so CMC does quantize the positions server-side to match the compressed replicated one? To increase determinism I assume
Not the positions.
It sends over an input vector to determine what direction it should go towards. However that vector is quantized to have less network overhead. The problem with quantized vectors is that they loose accuracy the further you go. So what they did is round the local input before processing anything with that value to match the value it will be rounded towards when send over the network. But in the end it's to increase determinism yes.
The problem is if you don't do that is that very quickly you're building up rounding errors because what you send over the network is slightly different to what you actually process locally. Especially with controllers I would imagine.
ahh yes my bad, I am to used to think about movement replication in terms of just position xd
No worries ๐
yeah ofc, makes sense
I was trying to make my own CMC at some point and this was one of the things that I was like "Huh. Never actually thought about that" ๐
But yeah it makes sense once you realise it exists.
Thank you for this all! That's useful to know. Hmm. I was hoping just the basic acceleration and velocity in the movement systems were deterministic, that makes things a little complicated since i'm trying to minimise desync to be virtually non-existent before any latency or packet loss is introduced and so far I'm really struggling. I suspect the deltatime isn't helping, and from combing through the code it seemed sort of like the server calculated some deltaTime by grabbing the last received move's timestamp and subtracting it from the current timestamp, but it wouldn't be just that since it would end up being really wonky when inputs weren't pressed but you had a lingering velocity to dampen. (which is kind of my issue right now anyways)
I'm actually not quantising any of the vectors yet, only because I was going to go through and optimise everything after - so I don't think that's an issue for me quite yet, but it is a very good point to round it to the correct precision on the autonomous clients before passing them through. But alas that's an issue for once I've resolved what's causing the greatest amount of desync for me right now.
There aren't alternative ways of moving from level to level and persisting data other than seamless travel right? I want to make sure I'm not missing something before I start debugging this in standalone since PIE doesn't work.
Use your game instance to store data.
and don't use seamless travel?
I'm not intimately familiar with the pros/cons of the different systems, which is what I'm trying to learn.
it sounded like if you don't use seamless travel it disconnects and reconnects all the clients
is that not a concern?
I don't know. I don't know what the ramifications are.
does it auto reconnect them?
I guess I'm not sure what the user experience is if they're disconnecting. I assumed it would auto reconnect.
When a client executes a non-seamless travel, the client will disconnect from the server and then re-connect to the same server, which will have the new map ready to load.
It is recommended that Unreal Engine multiplayer games use seamless travel when possible. It will generally result in a smoother experience, and will avoid any issues that can occur during the reconnection process.
so it sounds like we have to deal with not being able to test this in PIE
is that your understanding?
if that's the case that's fine, I just want to avoid embracing an onerous work flow if I don't have ot
Oh? They reconnect? I see. I'm thinking of the browse thing which just resets everything.
I mean it doesn't sound like it's much effort to set up seamless travel.
I mostly have it working. I don't think the data on my PlayerState is persisting... but it's hard to tell since it crashes in PIE.
I did already switch to GameMode. :P
Hello everyone!
Could you pls suggest me book or course for C++ UE5 online game dev ?
pinned resources, Neukirchen's compendium
lol, didnt look at pinned messages at all. thx !
@sterile plaza gotta add that if you target steam you'll need Seamless travel
Steam is not at all happy about the reconnecting process of hard travels and will leave some or even all your clients behind
Thanks for the heads up. At work we do whatever, someone else is worrying about it. This is currently a hobby project so no steam plans for now. I'm convinced figuring out how to make seamless work is the thing to do.
Whats the easiest way to send a variable from my player pawn to the playerstate, and then get it back again on death / respawn?
What sort of variable?
well i stored all my player stats on my character ๐ and its too much to change now. so im going to send all that to the playerstate when they die, then grab it back when they respawn to keep their level / health amount, stats etc...
I mean I you can just change how they are initialised.
But yeah, just add those stats to the player state too and copy them from/to characters?
how would i go about doing that? ive only just realized my problem now that ive killed a player and they reset to 0 xD
and which method is less performant heavy?
Just as simple as that?
and then to save them, make a custom event server and pass through that player state / stats and update them all that way
You don't need to worry about performance when copy a few stats from one object to another...
its gonna be like 60-70 variables, still new to unreal so dont really know how demanding stuff is
Don't create server events for backing up stats, that should happen only on the server anyway.
meh
In that case you want a large struct holding all your shit.
And just copy it as a whole.
but yes, none of what you're asking for should be networked
ah rogey, havent even touched stucts yet ๐
it should all be on the server
yeah only the server can update the playerstate right? i thought the easiest way is just when the player dies, he calls a server function to send it over. then when he spawns he just grabs it again. What is the proper way?
I'm doing a seamless travel and I implemented CopyProperties on my player state. I'm using that to copy a UActorComponent* from the old player state to the new one. At some point, that pointer goes to null. I'm struggling to come up with a reason why.
The pointer is in a UPROPERTY, so it shouldn't be GC'd... oh I bet the actor component is destroyed when the server travels. Is that what's going on?
Are you simply doing NewPlayerState->MyComponent = OldPlayerState->MyComponent; ?
Actors from the old world will be destroyed and destroy their components. So it's disappearing when the GC finally runs.
yeah, I need to copy all the values over
they explicitly destroy them though? even if there are references to them?
This is why structs are great. You just copy once and you're done. ๐
I believe so?
Honestly I've never looked into it, but it's the impression I get from everyone else who actually uses actors. And levels. And games in general.
hmm, I'll think about putting all the state in this component in a struct
oh no, I'm replicating individual members, they can't all go in a struct
Enjoy writing your 70 copy commands! ๐
Though I believe structs replicate individual members, not the whole struct. So you could just stick them all in a struct anyway.
Unless they have the Atomic specifier.
okay struc is done. much easier to use xD
and from my player, do i just get player controller 0 and cast to player state? or is there an easier way to access it
You can't cast a player controller to a player state.
If you have the cahracter, use Get Controller on it (or Get Player Controller). Get the playerstate from that and then cast that.
You may need to cast to player controller first if you just get the controller, rather than player controller directly.
rogey, i was trying this before but wasn't working xD
If you have a character, don't use the global functions (that take an index), just use the character itself to get the controller.
I think playerstate is on the controller class. 'Cause AI controllers can have a playerstate as well
That's what I was thinking, but I wasn't sure.
it reckons player state doesnt inherit from player controller?
As BP Player Controller -> Get Player State -> Cast
thats the one, ty
All working now ๐
now to find the million variables i need to pass around ๐
ReplicatedUsing
Can the struct members not ahve their own replicatedusing?
Player state does not live on the player controller or else you'd be able to server rpc.
Sure it does. And you can?
clients can call RPCs on their player state?
clients can call RPCs on anything they have ownership of
which includes the player state by default
huh, I guess I didn't know they owned their player state
clients have ownership over their controller, controlled pawn, and player state by default
and any other actors you set ownership for, but that's up to you
huh, controller does create the player state
I've rarely used it and apparently what I know is wrong.
good to know
can you specify an onrep function that lives in a different class?
Set the owner as a struct member (basically a version of a UObject's Outer) and then forward the call.
So, player stats, working, my spell hotbar working. My next issue is, when i learn a spell, i spawn an invisible actor in the world that holds its current level etc... what would be the best way to pass this through the player state and back for death / respawn? am i going to have to change the whole way i store that information instead of storing it on a separate actor?
Whats the Spell Actor doing?
it pretty much just exists in the world to store the spells level etc when they upgrade it, as i cant change class defaults
should i redo it so it stores the level of the spell in the player state?
Probably, it doesnt need to be an Actor.
You could create a Struct that holds information about a "Spell"
Like its level etc
Then hold that in a property on the PlayerState.
yeah, my spell system was my first attempt at making something without any tutorials ๐ so its a bit messy, but works xD. Yeah i think thats going to be the go, not looking forward to redoing this and breaking it along the way ๐
Refactoring is an essential part of programming/development.
and when i make a structure for the spell, and pass it to the player state, is there a way to search through multiple structures by name or something? (only started using structs today)
What do you mean "search through multiple structures" ?
I would use a map myself, map the spell class to teh struct detailing its current state.
Though maps can't be replicated, so maybe not.
All this sounds like GAS is what he needs lol
i think im going to have to take a bit of time and think through this whole process haha. But yeah for my spells, as an icon its using class defaults, then when i press learn, i was spawning an actor adding it to an array, and if you press learn/upgrade again, it would search that array for actors of class and if it exists, update the level on that actor.
Yeah.
GAS is c++ only yeah? im a long way off touching c++ if i can help it ๐
Not necessarily.
i would rather try learn without using it, im still soaking in all this BP stuff, just starting to make stuff without tutorials / guides. im only a few weeks in
GAS is pretty complicated, it might be worth it for you to try your hand at building your own system and then when you are more competent, making the leap to GAS later.
yeah that was my thoughts
Yeah - I wouldn't move to GAS until you are passed the beginner stage.
So am i in the right thinking here. Add a struc into the class defaults for my spells. When i press learn, it will update that struc info with the variables. Then add it to an array of "learnt spells" in the player state. When i press learn/upgrade again, how can i check if there is a struct with that class in the playerstate array? then i can grab it, and update it there. And when i cast my spell, it will check again, grab that struct and update the projectile with that info. Am i on the right path here?
Sounds like a plan
How many spells are you going to have?
Still not sure on that, so i want it to be fairly modular
want it to be easy to add / remove spells
I would add those details to the struct in your player state, not the spell class defaults, but sounds like a plan.
I do have a concern about the lookup for the spells. If you have 10 spells, it won't take long to check if you have a spell. If you have 500, it will be another story.
Reason im using class defaults, is i have a master spell bp, then just create childs off that, fill out the details, and add that into my spell book array and it all works pretty smoothly. ive only discovered playerstate today now that im trying to save / load on death / respawn
i wont be having 500 haha. maybe like 50 tops?
does checking through an array take a fair bit of time?
Not really, but if you do it a lot, it'll add up. What if you have systems that rely on you knowing a certain spell and it has to check repeatedly?
yeah true
The issue is a matter of scope. A spell class defines a spell, right? Not your player's spell. What if you start a new game and you have a different player? Are they going to share each other's spells?
for my spell hotbar, it only uses the class defaults as all it needs is the icon really which doesnt change. its more when i go to fire the spell, it will need to get the info to know its level / damage
Using the class defaults is great for icons and activating spells and stuff.
yeah thats what led me to spawn an actual actor that the player owns to store it. looking back on it, it was a terrible idea
But for recording the link between your player and spells (levels, etc) it's not ideal.
but its what i knew at the time of making it
It's not a terrible idea!
It's a good idea, just a little off. Instead of an actor in the level, you can use a struct on your player state.
so lets say, i have the struct with the info, and its on the player state. what is the best way to check that the spell class in my hotbar, is linked to a struct in my playerstate?
i need a reference between the two
You could simply search through the array each time for the correct spell.
When it becomes a problem, devise a better system.
rogey
ill give that a crack, cheers for your help, appreciate it
big day of fixing stuff today i think ๐
๐
Good luck!
Designing systems becomes a lot easier when you've learnt about database normalisation.
yeah i havent even touched datatables / structures etc yet haha until today
multiplayer rpg was a great first project ๐
MP as a first project is ambitious!
yeah i knew what i was getting into, but i hate singleplayer games. It will never be a complete game, more so a hobby and to mess around with mates on
just 1 thing, i have the array of my spell structs on my playerstate. whats the best way to search through them to see if it matches my spell class on my hotbar?
would i use like, contains, then send over the class default struct or will it not recognise it if i have changed values?
https://www.databasestar.com/database-normalization/ this seems to explain it pretty well. I'm not sure if you'll get anything out of it if you don't know anything about databases, though.
my only other thought is doing a for each loop and checking the name xD but i imagine thats slow
You would have to do a foreach, I think. Possibly inside a function. When you find the rigth struct, just return it from the function.
What do you think Contains does? ๐
๐
Why are you passing a struct with the "spell to find" instead of the spell directly?
Like that?
ahh as the input
You can just use the class name instead of the "name of the spell" as your name.
So "Spell To Find" -> Get Name
also, your struct doesn't need the spell name
I would put the spell as a variable inside your spell instance struct
a pointer to it
Yeah.
Honestly you don't need a struct on your spell at all.
Just have all the variables on the class itself.
so add the master spell class to the struct, then just pass the master spell class through, and see if thats == to the one in the struct?
what class?
that's what I was suggesting, yes
more just using a struct so its easier to send / retrieve stuff
what type are you spells?
actor
yeah, then just put the instance data on the actor I think
UCLASS(Blueprintable)
class ASpell : public AActor
{
GENERATED_BODY()
public:
// Spell definition values
UPROPERTY(EditDefaultsOnly)
int32 ManaCost;
UPROPERTY(EditDefaultsOnly)
FText Name;
UPROPERTY(EditDefaultsOnly)
int32 Damage = 1;
// Spell instance values
UPROPERTY(BlueprintReadWrite)
int SpellLevel = 1;
};```
or the equivalent in BP
He's using the spell class CDO only, though, so spell level shouldn't be there.
yeah sorry youve lost me there, thats beyond my knowledge so far ๐
yeah, you can't use the default object anymore, you'd have to instantiate
a tutorial on how to do spells might be useful
can walk you through how some of the things are pieced together in a way that we can't over chat
yeah rogey, its so hard to find whats good / bad tutorials online though. I hear a lot of people saying theres a lot of bad practices out there so its hard to determine which ones to follow
being my first project, i dont expect everything to be perfect, far from it. if it works, it works. But ideally id like to try and learn the best practices
I think you add the instance variables to your spell class, and then create the actor from that and then you can modify any of the variables on the spell instance
It's not perfect, but I think it's totally reasonable for what you're doing.
what class is this in?
when i press the learn/upgrade spell button, it send it to the player states, if it exists, it will update its level / damage etc. if it doesnt, it will add it to the array in the player state
what is CheckSpell doing?
this is in my AC spell component
it is seeing if that spell class exists in the playerstate already
ah
do you ever create an actor from the actor class?
im trying to get rid of that. Thats how i use to do it
for that loop, you don't need a local variable
if you find one, return true
if you complete, return false
i use to just spawn an actor to store the info when they learnt the spell. but i wanted to change it for if they leave / join the game it seemed like a headache to try store all that
can you show the definition of your master spell?
ah right, didnt know it would end as soon as it did. so i made that extra bool. wasnt sure if it counts as completed when it returns
if you return it stops iterating
sweet
Do you mean that?
so my hotbar just shows the spell from the class default, then it will check that with the spell in the structure that i send to the playerstate
yeah
i probably dont need to send everything, but ive chucked it in there anyway
are any of those values you can read from the spell definition?
only really need level / damage
CastingAnim for example?
yeah i can grab them from the class defaults
awesome
i just chucked it all in there for the hell of it ๐
and then, since you're only using the class defaults, I think a DataAsset is going to be easier to work with than an actor
yeah i havent touched them just yet haha
although I forget how you define the type of the data asset in BP
i done a inventory tutorial that set up all the items from a master item, then childs of that. so i sort of used that logic and made my enemies the same, my spells the same, my harvestable objects the same
sure
pretty much just using what ive learnt so far to continue and learn along the way. after discovering strutures i wish i used them a lot more, but thats the next projects job ๐
structs are great
also, with say animation in the structure. Would i send the data for the whole animation over to the playerstate, or just a reference to it? like that actual data would already be on the client right. just wanting to confirm
so, all you're going to need to save on the player state is which spell it is, which currently would be the master spell class, and then level and damage
everything else is defined in the master spell right?
yeah thats right
and when you talk about the spell across the network, you can just talk about the spell class, which is going to be fairly light weight, and the other side can look up the values from the CDO
yep rogey
hmm, it never finds the spell
Its printing that its adding it, but i can see its not in the array
sorry, was putting the kid to bed
no worries. if i manually add it whilst in game. everything else is working. but my add / upgrade isnt working
im calling them from server
do i need to run check spell from server too?
I would probably do that only on the server
yeah rogey
have an rpc that is, AddOrLevelUpSpell(TSubclassOf<Spell)
does that make sense?
then on the server you figure out whether to add or upgrade it
What is a Data Asset in Unreal Engine 4.
Followup video showing how use Blueprints Only for Data Assets using the Primary Data Asset type: https://youtu.be/hcwo5m8E_1o
Source Files: https://github.com/MWadstein/UnrealEngineProjects/tree/CPP-Examples
Note: You will need to be logged into your Epic approved GitHub account to access these exampl...
As a followup to an earlier video we show how to use the C++ Data Asset class using Blueprints only using the Primary Data Asset class type.
Original Data Asset Video: https://youtu.be/gLWXZ3FXhO8
love the titles xD
I think you will find these informative and a more elegant solution for defining your spells, rather than an actor.
the first one goes over what data assets are, how you define them in C++, and how you use them
the second one shows how to make them without any C++ using PrimaryDataAsset
Rogey, ill definitely give them a watch tonight
It's essentially the same as using an actor only for the default values, only it's going to be way easier to use and much lighter weight
okay so now its "adding" the spell, and its printing found the second time. although if i check my player state in the outliner, i can see theres nothing in there. and its not showing in the book unless i manually add it to the player state in game then it shows fine. I am passing the player who presses the button's player state through as well and its printing the correct playerstate. so where the hell is it adding it ๐
have you tried putting breakpoints at various points in the code to see if it's getting hit and then stepping through to see where it goes?
once i get to a stage where its a semi playable game, which im close to. im going to go back, and learn more optimized approaches to stuff and slowly work back through it
i have print strings, and its hitting them all
I would try breakpoints
rogey
breakpoints are to print strings as a ferrari is to my wife's honda civic
it gets the job done...
๐ ay theres some civics that can beat ferrari's ๐
yep so its going through, adding it the first time, then its finding it the second with break points. but if i view my playerstate in the outliner, i can see the array has nothing in it
on the client or the server?
you updated the server instance
does playerstate not replicate?
unless you're replicating that, it won't have changed on the client
i thought only the server can update it
i didnt, i swear i read everything in playerstate already replicates ๐
don't worry about it
with my player stats, i get server to update that on the player state, then the player grabs it, and that works fine
I've been doing this a long time and it took me 2 hours to figure out why my camera wasn't replicating rotation to the client a few weeks ago.
Everything that's already on it might well replicate, but if you add things, you still have to tell it.
Rogeyy
Just about got it all working, just need it to update my widget properly and its sorted ๐ appreciate all the help guys
of course
seems to be quite a bit of delay from when the player state increases the spells level to when i update the spell book. its around .7-1s is that right?
if i play as standalone, its instant. just not sure how to work around the delay from playerstate to pawn
im thinking maybe just keep it all on the client until you die, then it send to the playerstate to save, and when you respawn it gets it back
ahhh yep, just found that, its set to 1 per second xD
i just changed everything back over to client side... rip
good to know for future though
Its ok to have actors that rarely need an update on low priority/frequency
And just ForceNetUpdate when they have something important to replicate
Cheers for that. I think ill re do it tomorrow and chuck a force update in there and see how it goes. burnt out a bit from today now ๐
Upgraded my project to 5.1 and changed the 'Server Default Map'. I'm able to load into the lobby map, but the game won't connect/load the main world map when I use the 'Open Level' BP Command using the local IP (127.0.0.1). Any ideas?
Server log at the bottom shows multiple accepted connection attempts, I assume this means there's no firewall issues...
Client log at the top just shows a 'timed out' network error. No logic as-to why it timed out.
in ue4.27 im having an issue where my fast tarray of structs is failing to resolve an actor reference on the client side when that actor is replicated after the actor with the tarray... the relevant actor does exist on the client, but its as if its net replication does not always trigger a refresh/resolve of the delta serialized tarray actor's references, so the struct property remains a nullptr on client... is this a known issue or something i can work around somehow?
I created an TArray that is replicated but in blueprint i cant get item by ref, why?
You can't replicate to the server.
typo, i mean just replicate
Copied pointers still point to the same object. Changing values on the pointed-to object will be the same no matter how many times you copy the pointer itself.
Unless you mean you want to change the object it's pointing to? (i.e. change the pointer value tiself)
no, just object variables
Then something else is wrong in your code.
Yes, and?
ah understand, will check other code
That tooltip refers to the pointer, not the object it's pointing to.
Is there anything I can do to get my timers to act as tick functions so that they get called every frame, without actually using tick functions? 
It's just that I have this timer delegate lambda that's very convenient to use
maybe better describe what i want to do
I have this replicated array
On client i press button and check variable
On server i set varaible of object in index 0 to some value and want to see that when i press button on client
But thats not work, on client variable is unchanged
Is the server event being executed? Add a print string or something.
Is "Name" your own variable? Is it set to replicate?
This is the hack I need to replicate a change in an array of structs
Can I avoid that?
set members alone doesnt replicate
Why not just tick?
The behavior I'm looking for on my actor comes and goes and I want it working independently of tick, which may need to be enabled at all times, and I don't want to bloat tick because it's kinda niche
Also woops just realized we're in multiplayer and not cpp
@unkempt tiger could wrap your logic into a tickable object
Or call a timer for next frame and let it retrigger itself
But not sure what the overhead is
I thought of this but something about using timers felt hacky, I ended up discovering that instead of a timer handle, I can use a FTSTicker::FDelegateHandle MyHandle and do something along the lines of:
MyHandle = FTSTicker::GetCoreTicker().AddTicker(
FTickerDelegate::CreateWeakLambda(
this,
[&](float DeltaTime) // Expects functions that accept a delta time float argument to compile
{
DoSomething();
return true; // It's expected of the function to return true to continue ticking or false to stop ticking
}
)
);
And I can remove it like so: FTSTicker::GetCoreTicker().RemoveTicker(MyHandle);
This ended up working wonderfully, plus I kind of expect minimal overhead since this FTSTicker type is used everywhere in the engine at quite low levels
I see myself using this a lot in the future, it's so much more convenient than having to setup a tick function imo
I would advise against using [&].
It kinda destroys the point of having a weak lambda?
Oh, can you explain why?
It captures things by reference. Including things which you may not want it to.
If you're using a weaklambda, why not capture [this] instead?
It will ensure this is valid when the lambda runs.
Doesn't a weak lambda already ensure that this is valid?
It ensure this is valid. Not everything else it may capture.
You might capture a local variable which becomes stale or something. Or you might capture a sharedptr which keeps something alive and causes bugs.
It's just generally a bad idea to use [&]
Makes sense, I'll change it, thank you ๐
Unless the lambda is run within the same scope.
If you're accessing the array through a "Get" make sure it's a Get (by ref), then the Set Members should work.
Heads up to all who may be interested in the GMC plugin
seems like it's becoming like a marketplace network prediction plugin
good move I think, definitely an underserved thing
what does GMC stand for?
Pretty sure its the Generic Movement Component?
Hi - If I want to set the AI character hidden in game and stop brain logic,etc, I want this to effect only the clients since I'm using viewport. Would I do ClientsOnly events to set them?
You can't make Clients stop an AI's brain logic, and I think hidden in game only works on the server aswell? For clients I think you're suppose to use set visibility
iirc setting hidden in game on server hides it on clients aswell but I can't remember
What about setting tick intervals and applying skmesh optimization via c++
You can change the tick intervals for whatever you want as long as client has their own simulation of it
so things like meshes, capsules, movement components, and anything attached to it
you can change/optimize them as you see fit for server and clients, they don't have to be the same
but clients don't have a brain component for AI which is why you can't stop it
you'll get an error everytime
My HUD is created in standalone, but in play as client, it's not. It's being set on the game mode.
client doesn't have a game mode, how does that data get to the client?
That's where it lives though... is there another place to specify it? Why is it a member of game mode in the first place?
Literally the first thing I found was a call from the game mode to the player controller telling it to set the HUD. I'm confused.
There's two things involved:
HUD Class and Widgets. Siliex was thinking you were creating widgets in the Game Mode as was I when I first read your message.
Using a base template game, I made my own HUD class with a simple image widget that I add to the viewport on begin play of the HUD class. Works fine on clients.
You discovered how it communicates it to the client - it uses the player controller which is replicated, so the game mode sends the message through player controller which the client receives and it can instantiate and use the appropriate HUD class.
If I toggle visibility of Skeletal mesh using Client RPC would it work?
So I'm making a multiplayer rpg. Are there any tutorials anyone could recommend on how to store players info on a server so they keep their name / levels / items etc when they join every game instead of resetting each time they join a new server
Probably nothing related to UE directly
If your intention is to retain their data on only a single server (ie. player connects to a server, plays, levels up, gets items, quits game, later returns to the same server and they should have all the same data) then all you need to do is utilize Save Games - all data about the player you want to save about the player you would save in the save file, when the player reconnects, you read the save file and load whatever data where you need it.
If you are intending on a player being able to retain that same data across multiple servers (ie. player connects to a server, plays, levels up, etc. quits game, later returns but connects to a different server and they should have all the same data), then you're getting into the realm of requiring a database, but this would also then require that you host all game servers as otherwise malicious actors could upload bogus data to your database or overwrite other player's data as you'd have to allow those servers write access in order to make changes to player data. There's also no native support within UE to connect and utilize a database, so you'd either need to build up an API of some kind to connect into your database server, have a plugin that can make the connection to the database, or you'd need to code it yourself within C++ . There's little point in recommending a tutorial for how to do any of this, as it would depend highly on what database solution you decide to go with.
Also, you need a unique identifier for your player
For both of those writeups
If you aren't intending on using a subsystem like Steam or EOS, then you'd also need to setup some sort of login system with unique identifier
Otherwise you can't really track the player.
Thanks for the in depth reply. I'm not 100% sure it will ever be a complete game. More so a hobby for myself and friends to play so I'm not so concerned about malicious intent. I would like to ise the steam subsystem for ease of joining eachother but yeah the idea was store all their data on a database, and they can each host their own server and do their own playthrough with people. As my first project this is sounding to be a bit out of my realm so I might just dig into dedicated servers and run one 24/7 that stores everything and everyone can just play on the one server
Honestly, it might be better to just figure out how to send the SaveGames of Characters to the Server and make the whole game ListenServer based
If you don't care about cheating and a DataBase is too much, then that would be the easiest solution
Every client saves its progress locally and on connection tells the Server what their character is
That sounds like a great solution atleast for a long time until I want to dive into it and spend months learning it ๐ putting all my focus into just learning the engine and blueprints atm
Sending the SaveGame data to the Server might be best done i nC++ though
just an fyi
roger that. I know im going to have to dive into c++ at some point. Although i havent got much coding experience, only a bit of c#. mainly just getting proficient at blueprints for now
and still a long way off that xD
Character data shouldn't be that big depending on structure. Could store most all in a struct and just RPC it for the most part.
Yeah but there are some size limits
We had to send multiple batches of data for The Ascent
To be fair. I'm not considering stuff like history or anything. Was just considering basic visual definitions and stats. ๐ It could get pretty complex I guess.
Still working on my damage popups, trying to get the widget to scale depending on how far from the enemy you are. Im running this on the owning clients and setting the scale based off the enemies location and the location of the player. Yet its printing the same distance for every client still. How can i make it only set the scale on the owning client?
Not entirely sure why you need so many RPCs
Server Damage Popup shouldn't really exist
Cause the Server is the one dealing the damage already
The Multicast is theoreitically fine
can a player call a MC? i thought server had to
Server has to but you aren't dealing damage locally, are you
no thats all on the server, this is just for the damage popup widget
so everyone makes their own, and i want them to all set their own scale locally
You are overcomplicating this a bit
One single "Multicast_OnDamaged" would be enough in the Enemy
Pass in all the info from the damage
rogey
And then handle everything you need
Also you are getting PlayerController in your image
You probably meant to get the Character
You also don't need the EnemyToAttachTo
Cause the MC should just be in the Enemy you damaged
Makes it all a lot simpler
it can also attach to players / trees / harvestables etc so i just kept it on the player
I would just put that into a Component then I guess
HealthComponent and DamageNumberComponent or so
They don't need to know what they are attached to
rogey
i just have it as a MC now, but both clients are still printing the same distance from the enemy
That'll do it, works a charm now. Cheers
Is this a workaround instead of doing SessionSettings->bAllowJoinInProgress = false; and then calling SessionInterface->UpdateSession(GameSessionName, *SessionSettings, true);?
As I've noticed that this never works and players can still join in progress even if that bool is set to false
I will try your workaround instead, just curious if it's a common thing that bAllowJoinInProgress doesn't seem to update or take effect if setting it later than session creation time
Shouldn't the timer variable be automatically updated for all the clients if it's set to replicate like this? Right now the timer stays at 0 for all the clients
This is in a normal actor blueprint
The actor is replicated and only spawned on server?
damn.. totally forgot to check replicates on the actor itself. Thanks mate ๐
๐ Also be careful with the ++ node or any SetByRef stuff in BP. Not related to your current thing but if you set a value on a RepNotify variable without explicitly using the Set node for it, the OnRep will not run on server like you'd expect in BP on the server.
Ah good to know, thanks!
I have an anim notify in my characters animation bp, for some reason, that is triggering on all of my clients, how can i make sure it only triggers on the client that actually doing it?
If i play as host, it works fine and only fires once. If i play as client it will fire for every client :/
Bold move to increase the price even more when Epic is aware of the limitations of CMC and has spoken about addressing them. (Granted, Epic will take a while to do so.)
Sounds like you're replicating it somewhere. Hard to diagnose without more detail.
That gets triggered by the ags anim notify
Even running it like that the server prints it twice
I see "damaging enemy" and in your print in game "damaging player"
just want to be sure you aren't printing from some other logic somewheres and not what you shared
sorry, the next line down is the same but for player, thats why the strings different
does the same for player and enemies
i think i just sorted it with that
but should i be doing the trace on the client or the server? it feels a bit janky
yeah before, you were running that logic twice, on your client and on client 2's version of your client
at least that's what it looks like to me...
I've decided to try not to have much coffee this morning though so... lol
Hi there, is there a way to make sure this does not replicate when ran from the server?
I tried using a run on owning client but that also seems to spawn it for the clients
turn off the actor's replication?
The placeable Actor's replication you mean?
Yeah
That is turned off
Hmm, maybe that BP node is doing it internally then. Not sure
Yeah think so
I don't think it is bold at all personally.
V2 will be ready far before Epic actually does anything with CMC
Iris is already in experimental, though. But yeah I agree GMC is still going to be valuable for a long time probably.
Iris isn't meant to replace CMC
TBH I am probably going to buy it when I sort out my budget.
True, but GMC appears to be edging into the replication space harder with V2.
one other thing mythic, all my enemies are a child of my master enemy bp. If theres 2 enemies fairly close, but definitely not close enough to be hit by the trace, it still seems to damage both, im guessing either the ags combat manager trace is a bit dodgy, or something else is up
Shouldn't matter if they're children if you're doing the trace right imo
rogey, its a plugin im using so im guessing its something up with that
General Movement Component
vs. Epic's built-in Character Movement Component
That's the fun with plugins! Save a lot of time building the plugin yourself. Lose all of that time integrating it and debugging it with your game. (not true always, look at GMC. Good luck writing that one)