Browse by type
[!IMPORTANT] Actor-Based Turn in Place (TIP) Solution. A superior substitute to Mesh-Based Turn in Place without the endless list of issues that comes with it.
[!WARNING] Download Content from Releases and unzip to the plugin's Content directory
Or download the pre-compiled binaries here
Install this as a project plugin, not an engine plugin
[!TIP] Supports UE5.4+
[!NOTE] Read the Wiki for Instructions and Complete Features!
[!TIP] Showcase Video
[!IMPORTANT] Read the Wiki for Instructions and Complete Features!
Actor-Based TIP does not have any of the issues that come with Mesh-Based TIP. Read below for a detailed list.
We don't rotate the mesh, we simply use the existing functionality from ACharacter::FaceRotation() and UCharacterMovementComponent::PhysicsRotation() to store a TurnOffset on the UTurnInPlace Actor Component then apply it when we apply rotation to the Character. That's it!
This is my own solution that I developed from scratch because no adequate solution existed. This is released for free because it should become the industry standard for Unreal Engine Turn In Place.
Multiplayer Ready: No extra steps required
Provides turn in place for the following movement types:
* ACharacter::bUseControllerRotationYaw for strafing movement used in shooters (Lyra uses this exclusively)
* UCharacterMovementComponent::bUseControllerDesiredRotation for strafing movement that interpolates smoothly
* UCharacterMovementComponent::bOrientRotationToMovement by turning towards the LastInputVector, which has been added to the Character Movement Component for you
Built with different stances in mind, allowing for different step sizes (e.g. 60, 90, 135) for different stances. But none of this is limited to stances, you can determine which AnimSet to use based on anything you like.
Handles increasing the turn rate when you reach the max turn angle, and also when you change directions mid-turn, e.g. playing left turn but now turning to the right, the left turn can complete rapidly using a specific multiplier.
Handles montages out of the box. Plenty of functions to override to determine behaviour in the UTurnInPlace component.
This system is very condensed. There is a TurnInPlace UActorComponent that is responsible for the functionality, and functions that you can call to from your Anim Graph that handle everything you need.
Primarily this setup is seen in LyraStarterGame. It is inadequate and causes significant issues everywhere it touches.
This technique negates the rotation from the character's mesh by applying a RootYawOffset to the skeleton's root bone, using the Rotate Root Bone anim graph node.
Simulated proxies are characters other than your own that you see in multiplayer games. Simulated proxies receive a very simplistic condensed location and rotation from the server, then applies smoothing directly to the mesh so that you don't notice the considerable jitter due to intermittent replication and compression of these properties.
This mesh smoothing applies to the root bone rotation, and they fight each other. This causes considerable jitter that increases with latency. The jitter will be particularly noticable when the RootYawOffset is higher, and a turn has not been initiated.
To counteract this, you must switch NetworkSmoothingMode from the default Exponential to Linear. Exponential looks really good, its distance based, linear doesn't look particularly good. You also need to increase the NetworkSimulatedSmoothRotationTime to help mask this defect, but now your simulated proxies are very late updating to their actual facing direction, which has quality issues but also gameplay issues for fast action-based competitive games.
The larger issue with using Linear over Exponential isn't rotation, its translation. Linear translation looks truly poor. Your sim proxies constantly get yoinked backwards when they come to a stop and the start doesn't look great either!
This leaves you making serious sacrifices for something that is entirely not important affecting every aspect of your game. One option is to modify the engine to decouple the NetworkSmoothingMode so that you can set Translation separately from Rotation, however that is very difficult and can be prone to issues that are extremely difficult to diagnose because they are tightly interconnected.
We now have additional rotation to factor into every single system we build. Do we want to use a rotation based on the actual mesh rotation, or do we want the mesh rotation based on where we see it facing based on the RootYawOffset?
Furthermore, when adding procedural systems, however simple, they might fight your Rotate Root Bone, especially when sockets come into play which you will often find to be a frame behind the Rotate Root Bone!
There is too much in the anim graph that goes into building the system Lyra uses.
WARNING: UPDATE YOUR CONTENT OR ANIM GRAPHS
Implementation/TurnInPlaceAnimGraph.h that contains C++ implementation of the Anim Graph functionsShouldRotateToLastInputVector() added for runtime overrideUpdateLastInputVector() now virtualIf these changes break stuff for you maybe ping @vaei in Unreal Source Discord or open an Issue here
float to double for FTurnInPlaceGraphNodeData::AnimStateTime due to 5.6 deprecationbAbortTurn that will abort a turn anim if we become unable to turn and CanAbortTurnAnimation returns true (by default, it is true)IdleUTurnInPlace::CanAbortTurnAnimation() to false to keep original behaviour, or toggle this during runtimeITurnInPlaceAnimInterface::Execute_GetTurnInPlaceAnimSet() to own function UTurnInPlace::GetTurnInPlaceAnimSet()PauseTurnInPlace or LockTurnInPlaceBREAKING CHANGES
Consider using perforce to diff ABP_Manny_Turn in particular when updating your project
StartRotationABP_Manny_Turn to support updated system that has been condensed with pseudo anim states in mindFTurnInPlaceGraphNodeData AnimNodeDataGetTurnInPlaceAnimation()ThreadSafeUpdateTurnInPlaceNode()SetupTurnInPlaceRecovery() node function from ABP_Manny_Turnp.Turn.Override for debugging/isolation testingTRACE_CPUPROFILER_EVENT_SCOPE for profiling via insightsDebugRotation and DebugServerPhysicsBodies for projects to remove/add debugging functionalityCacheUpdatedCharacter() from UTurnInPlace::PostLoad(), fails check calling BlueprintNativeEventAPawn without ACharacter + UCharacterMovementComponentETurnInPlaceEnabledState wasn't always handled properlyETurnInPlaceEnabledState$ claude mcp add TurnInPlace \
-- python -m otcore.mcp_server <graph>