Steps to Reproduce
ENVIRONMENT:
- Engine: UE 5.7 (stock, no engine modifications)
- Project: Lyra Sample Game (from Fab/Marketplace)
- Platform: Windows (Win64), Development Editor
- Net Mode: Play As Client with dedicated server
REQUIRED SETTINGS:
- IRIS replication enabled (net.Iris.UseIrisReplication=1 in DefaultEngine.ini [ConsoleVariables])
- FGameplayAbilityTargetData_SingleTargetHit registered in SupportsStructNetSerializerList (this is already the case in BaseEngine.ini by default)
- PIE: Run Under One Process = Unchecked, Run Dedicated Server as Separate Process = Checked
RELEVANT ENGINE FEATURE:
- IRIS native struct serialization (FStructNetSerializer) for structs in SupportsStructNetSerializerList
- FActorInstanceHandle lazy resolution in FHitResult.HitObjectHandle
REPRO PROJECT:
The attached Lyra project contains a minimal repro ability (GA_IrisHitResultRepro) and two cheat commands. Only 4 files were added/modified from stock Lyra:
- Source/LyraGame/Tests/GA_IrisHitResultRepro.h/.cpp (new — repro ability)
- Source/LyraGame/Player/LyraCheatManager.h/.cpp (modified — added 2 cheat commands)
- Config/DefaultEngine.ini (modified — added net.Iris.UseIrisReplication=1 and base struct to SupportsStructNetSerializerList)
STEPS TO REPRODUCE:
1. Open the attached Lyra project (Lyra.uproject) in UE 5.7 Editor.
2. Build the project (Development Editor, Win64).
3. Configure PIE settings (Edit > Editor Preferences > Level Editor > Play):
- Number of Players: 1
- Net Mode: Play As Client
- Run Under One Process: Unchecked
- Run Dedicated Server as Separate Process: Checked
4. Hit Play. Wait for the dedicated server log window and client window to appear. Wait for the client to fully spawn into the map.
5. On the client viewport, open the console (~ key) and type:
Cheat IrisRepro
This sends a command to the server which grants the repro ability to the player’s AbilitySystemComponent.
6. Aim the camera at any static mesh in the level (a wall, the floor, a prop — anything with physics collision).
7. Open the console again and type:
IrisReproFire
This activates the repro ability on the client, which:
a) Performs a LineTraceSingleByChannel (ECC_Visibility) from the camera
b) Packages the resulting FHitResult into FGameplayAbilityTargetData_SingleTargetHit
c) Sends it to the server via ServerSetReplicatedTargetData (GAS target data RPC)
8. Check the dedicated server log window for the result.
EXPECTED RESULT:
Server log shows the hit actor name:
LogIrisRepro: Display: SERVER: bBlockingHit=true GetActor()=SomeActor_0 GetComponent()=StaticMeshComponent0
ACTUAL RESULT:
Server log shows NULL actor:
LogIrisRepro: Error: SERVER: bBlockingHit=true GetActor()=NULL GetComponent()=StaticMeshComponent0 <-- BUG
Note: GetComponent() returns a valid component, confirming the FHitResult data arrived correctly. Only GetActor() fails.
WORKAROUND VERIFICATION:
To confirm the root cause, open Source/LyraGame/Tests/GA_IrisHitResultRepro.cpp, find the commented line (around line 105):
// HitResult.GetActor(); // <-- UNCOMMENT THIS LINE TO FIX THE BUG
Uncomment it, recompile, and repeat steps 4-8. GetActor() now returns the correct actor because calling it before serialization forces FActorInstanceHandle lazy resolution, updating ReferenceObject from the hit component to the owning actor.
[Attachment Removed]