HMD / controller replication with dedicated servers
Default server tick rate is 30tick, this may be a bit slow for VR games to really feel good so I would suggest upping it to 60tick if possible. For the HMD and Controller replication settings you need the UpdateRate to be AT or UNDER the server tick rate in order for smoothing to function properly (IE: for 60 tick, anything at or under 60 htz would work). Listen servers tick regardless and do not have this issue.
I will note though that the sweet spot for replication rate is 45htz, at 45htz if steamVR starts reprojecting then the updates will still be at full value, and when not reprojecting it will be about half refresh rate which is good.
Simulated objects and the character
By default I have gone in and disabled the player character from being blocked by simulating objects. This is because it is generally very disorienting and can cause movement hitching / stuttering when physx starts jittering.
You can turn it back on by setting
bool bAllowSimulatingCollision to true in the Root Component, this lets the capsule be blocked by physx simulating objects.
Also you may want to set bool bIgnoreSimulatingComponentsInFloorCheck in the movement component to false. This will let you stand on physx simulating objects.
For teleport tracing to nav mesh and any of the navigation modes, you should turn on bAllowClientSideNavigation in the project settings.
Currently there is a crash when NVIDIA ansel plugin is active and the bDisableServerUpdateCamera option is true in the VRPlayerController.
This option utilizes a built in engine feature to stop replicating the camera POV in the camera manager....
Until Epic fixes it you will want to turn off bDisableServerUpdateCamera if you want to use NVIDIA ansel for some reason.
Forcing SteamVR to run
Use the launch option -hmd=SteamVR in a shortcut or in the steam game setup.
If this is set to true (engine default) then objects on first load of a newly connected client may not replicate their current position if they are currently gripped (during client side movement grips movement replication is turned off to save bandwidth). You may want to set this to off for all pre-fab object thats you anticipate that being a problem for.
It was defaulted to off for awhile in the plugin, but placing random statics meshes into the level without making a subclass for them first wouldn't replicate the static mesh (since static meshes don't replicate).
IK Mesh ticking group
Skeletal meshes Animation Blueprint Graphs are ticked when the skeletal mesh itself is ticked. If your IK is lagging behind you should set the skeletal meshes tick group to something later in the stack (like post physics so physics grips are done by then).
As of 4.19 Epic added a scoped function to avoid updating the bones of a skeletal mesh until final movement when combining moves. I added a GetIKMesh() function that you can override in c++ or BP to pass in your IK mesh to avoid the bone movements. It may also be used in the future for further optimizations and features.
Client Authoritative Rotation
As of mid 4.19 / early 4.19 I switched the default VRCharacter behavior (not simple vr character) to have client rotations be server authoritive with correction support. This means that if you want to test an FPS pawn, or want the legacy default engine behavior period, that you need to enable bUseClientControlRotation in the VRCharacterMovementComponent. This is false by default, when true it will use the original engine setup of just blindly setting rotation to match what the client sent in.
With the rotation authoritative you will want to perform actor rotations with one of the rotation MoveActions that have been added to the character. IE: Snap turn with a value or delta value, or SetActorRotation move action.
Client Authoritative Position
While generally undesirable in 2D games, client authed movement is actually better suited to VR, see as how the client already controls most aspects of their movements clients side. While not on by default with the plugin, it is still an option should you have issues with the character rollback.
Unknown to most this is already an available feature in engine (though it is defaulted to off).
/* If client update is within MAXPOSITIONERRORSQUARED then he is authorative on his final position /
To turn it on you can add the following lines to your DefaultGame.ini
Although this makes the client authoritative within the range, you can force it to always be authoritative with:
Set to true in the CharacterMovementComponent
Smooth turning in multiplayer
Characters in engine default to using Bytes to replicate rotation axis's, I have defaulted characters as of late 4.18.3 to use short components as the Pitch/Roll generally don't replicate anyway. If you want to save the 1 byte cost and are not using smooth turning you can turn this back to byte components in your character BP or file. If you are on an older version you may want to set this to short components in order to get smoother rotation.
For many people acceleration is a potential cause of sickness in VR, to avoid acceleration when moving you can set the following variables in c++ or BP for the character movement component.
bRequestedMoveUseAcceleration = false; MaxAcceleration = 200048.0f; BrakingDecelerationWalking = 200048.0f;
Setting braking and max accel to high values effectively removes the ramp up accel time.
Grippable Components and Replication
By default all components in the engine are set to bReplicates = false. The grippable components specifically have some properties that can be useful to replicate to clients (Gameplay tags and VRGripInterfaceSettings), if an object is not set to NetLoadOnClient and is placed in the level with custom settings over its base class the values will not replicate to the client unless you set the component to replicate.
bReplicateGripSettingsAndGameplayTags enables / disables them being sent when the component is set to replicate.
Also there is now a bReplicateMovement variable on all clients so that when replication is enabled they don't add additional overhead by also defaulting to replicate their position.
Physics grip tips for better behavior:
Physics grips as of a few versions ago now grip at the COM (Center Of Mass) of the gripped object, this provides the most stability during the grip. However this can cause collision to behave slightly differently than expected for some items (like swords) where the point of rotation would be expected to be at the handle/grip itself.
Changing the center of mass of your object to known primary grip points or doing it at the time of gripping with SetCenterOfMass() will in many cases provide you with a better result.
This is now done by default in the plugin and can be turned off in advanced physics settings for a grippable
Using Additional Late Update Components
This array on the motion controllers allows for late updating additional un gripped / attached components. If you use this and remove an object from it without moving it afterwards you likely need to call UpdateComponentToWorld on it to correct for the late update offset post 4.18 (4.17 with my plugin). This is because the new late update comes in after the last movement and offsets the render primitive.
Using components instead of mesh sockets for snapping
If your game would be easier to make by passing in scene component transforms instead of socket transform for grip points (move around on the actor, rotate on startup, ect). You can override the GetClosestGripSocket function in c++ or Blueprint (VRGripInterface) and return the Relative Transforms of your chosen scene components instead of the default implementation of returning socket transforms.