Announcement
Collapse
No announcement yet.
Able Ability System Info and Support Thread
Collapse
X
-
JSwigart repliedInterestingly, forcing the ability from a boolean parameter only when called from OnServerActiveAbilityChanged also gets non dedicated server mode working correctly.
-
JSwigart repliedThanks. So that gets the client->server ability activation order working consistently. I'm still unable to get the clients and server side ability conditionals to work reliably. The replication of the dash charges from the server often still beats the starting of the ability, so while the owning client will activate first, followed by the server, the other client will fail to activate due to getting the replicated dash charge change from the server ability activate before activating the ability on their end.
The failure comes from the call to InternalStartAbility called from OnServerActiveAbilityChanged(), so I wonder if it would be reasonable to add a parameter that allows the client to skip CanActivateAbility when told by the server what the active ability is. Seems reasonable to me that if the server tells you what ability is running, the client should not be doing conditionals that can fail to activate that ability. The CanActivateAbility would still be executed on the client when they activate it locally.Last edited by JSwigart; 09-19-2019, 05:37 PM.
Leave a comment:
-
ExtraLifeMatt repliedOriginally posted by JSwigart View PostOk, so the issue seems to be that there is a behavioral difference between the client(listen server?) running in the editor window, and the client running in the popup window during PIE.
In the Editor window, the call to UAblAbilityComponent::ActivateAbility call ends up activating the ability server side first, because it takes the code path for authoritative
// We're authoritative. Start the Ability.
Result = InternalStartAbility(Context);
While the client in the popup window functions as you describe, where it's not authoritative, so it sends the ServerActivateAbility RPC and then starts the ability locally, which activates the abilities in the 'proper' order of client then server.
How do you handle this inconsistency in PIE ?
Leave a comment:
-
JSwigart repliedOk, so the issue seems to be that there is a behavioral difference between the client(listen server?) running in the editor window, and the client running in the popup window during PIE.
In the Editor window, the call to UAblAbilityComponent::ActivateAbility call ends up activating the ability server side first, because it takes the code path for authoritative
// We're authoritative. Start the Ability.
Result = InternalStartAbility(Context);
While the client in the popup window functions as you describe, where it's not authoritative, so it sends the ServerActivateAbility RPC and then starts the ability locally, which activates the abilities in the 'proper' order of client then server.
How do you handle this inconsistency in PIE ?
Leave a comment:
-
ExtraLifeMatt repliedOriginally posted by JSwigart View PostI have a question about able and networking. What is the typical philosophy behind the logic one might want to have implemented inside the CanAbilityExecute function of the ability?.
I have a dash ability that has a CanAbilityExecute function which checks if the owner pawn has any available "dash charges" that recharge over time. When the ability activates, only the server subtracts 1 dash charge. During The dash charge variable is replicated to the client apparently before the ability starts(at least in PIE), so the client fails the custom check and does not activate the ability, while the server does.
How do you normally handle these sorts of data dependencies?
Leave a comment:
-
JSwigart repliedI have a question about able and networking. What is the typical philosophy behind the logic one might want to have implemented inside the CanAbilityExecute function of the ability?.
I have a dash ability that has a CanAbilityExecute function which checks if the owner pawn has any available "dash charges" that recharge over time. When the ability activates, only the server subtracts 1 dash charge. During The dash charge variable is replicated to the client apparently before the ability starts(at least in PIE), so the client fails the custom check and does not activate the ability, while the server does.
How do you normally handle these sorts of data dependencies?
Leave a comment:
-
ExtraLifeMatt repliedOriginally posted by JSwigart View PostIt can do broken stuff if the reference passed in falls into the memory range of the list as the removal moves stuff around and effectively changes the value from under the remove parameter., so their CheckAddress is a interesting protection against that edge case.
Gotcha, yea, I'll get that in this weekend.
Leave a comment:
-
JSwigart repliedIt can do broken stuff if the reference passed in falls into the memory range of the list as the removal moves stuff around and effectively changes the value from under the remove parameter., so their CheckAddress is a interesting protection against that edge case.
Leave a comment:
-
ExtraLifeMatt repliedOriginally posted by JSwigart View PostFyi, there's a crash in HandlePendingCancels that I fixed as follows.
Didn't make sense to me at first until I read a few posts about it, such as https://answers.unrealengine.com/que...ml?sort=oldest
Basically the CheckAddress call in the Remove function verifies that you aren't passing a reference that is within the array, because it can get corrupted during removal. The fix is just to grab a local reference to the object being removed and pass that in.
Leave a comment:
-
JSwigart repliedFyi, there's a crash in HandlePendingCancels that I fixed as follows.
Didn't make sense to me at first until I read a few posts about it, such as https://answers.unrealengine.com/que...ml?sort=oldest
Basically the CheckAddress call in the Remove function verifies that you aren't passing a reference that is within the array, because it can get corrupted during removal. The fix is just to grab a local reference to the object being removed and pass that in.
Leave a comment:
-
ExtraLifeMatt repliedOriginally posted by JSwigart View PostCan you explain the logic of UAblCancelAbilityTask::ShouldCancelAbility ?
Specifically, why does the function have that first early return true?
if (*m_Ability && m_Ability->GetDefaultObject<UAblAbility>()->GetAbilityNameHash() == Ability.GetAbilityNameHash())
I was trying to make a stackable DOT fire effect with a task that cancelled itself if the conditions of the ShouldCancelAbilityBP were met, so it can manage its own decay and take advantage of the RemoveOneStack functionality already implemented here, but this early out was preventing my function from being called. Curious why this early out exists?
Leave a comment:
-
JSwigart repliedCan you explain the logic of UAblCancelAbilityTask::ShouldCancelAbility ?
Specifically, why does the function have that first early return true?
if (*m_Ability && m_Ability->GetDefaultObject<UAblAbility>()->GetAbilityNameHash() == Ability.GetAbilityNameHash())
I was trying to make a stackable DOT fire effect with a task that cancelled itself if the conditions of the ShouldCancelAbilityBP were met, so it can manage its own decay and take advantage of the RemoveOneStack functionality already implemented here, but this early out was preventing my function from being called. Curious why this early out exists?
Leave a comment:
-
JSwigart repliedI re-created the problematic abilities from scratch and so far I'm not getting the issue described. I'm thinking there is definitely an issue with duplicating abilities.
Leave a comment:
-
ExtraLifeMatt repliedOriginally posted by JSwigart View PostFor the CDO crash, here's where it looks like it's self referencing. In FLinkerLoad::FindExistingExport
The lines
TheClass->GetDefaultObject(); // build the CDO if it isn't already built
Export.Object = StaticFindObject(TheClass, OuterObject, *Export.ObjectName.ToString(), 1);
Originally posted by JSwigart View PostThis may be unrelated, but is there a possibility that if you duplicate an ability, that it could be broken? I want to say the abilities I am having these issues with are ones that I had duplicated from another similar ability to avoid recreating them from scratch.
Any idea what might cause this?
Blueprints work well, but they have lots of gotchas. I find duplicating them to be a dubious task at best. If you find yourself doing a lot of duplication, you may want to try and take one layer of complexity out by putting that into a custom C++ task with whatever values you are just tweaking exposed.
Leave a comment:
-
JSwigart repliedThis may be unrelated, but is there a possibility that if you duplicate an ability, that it could be broken? I want to say the abilities I am having these issues with are ones that I had duplicated from another similar ability to avoid recreating them from scratch.
Leave a comment:
Leave a comment: