# First Person Template Integration

{% stepper %}
{% step %}

### Install Plugin

* Find the Replicated Gravity plugin in your Fab Library.
* Install to your preferred engine
* Enable the plugin in Edit > Plugins
* Restart the editor
  {% endstep %}

{% step %}

### Replace `CharacterMovementComponent`

* Open your Character Blueprint (inherits Character).
* In the Components list (Left side) select your `CharacterMovementComponent`
* In the Details panel (Right side) change the Component Class to `GravityMovementComponent`
* Compile and save your character
  {% endstep %}

{% step %}

### Configure Character Rotation

#### Set Use Controller Desired Rotation

Make sure your character is highlighted in the component list (left side).

* In the search bar in the details panel (right side) type "Movement Rotation"
* Find "Use Controller Desired Rotation" under Character Movement Component
* Set Use Controller Desired Rotation to **True**

**What This Does**:

* Character rotation follows camera orientation
* Essential for gravity-aligned first person movement
* Works correctly in all gravity orientations

#### Disable Pawn Controller Rotation Yaw

Now type in the search bar "Pawn":

* Find "Use Controller Rotation Yaw" under Pawn settings
* Set Use Controller Rotation Yaw to **False**

**What This Does**:

* Prevents double rotation from both pawn and movement component
* Movement component handles all rotation via gravity system
* Camera stays aligned to gravity direction

### Why These Settings Matter

#### Use Controller Desired Rotation = True

This tells the GravityMovementComponent to rotate the character capsule toward the camera's facing direction while respecting gravity orientation. Without this:

* Character won't turn with camera look input
* Movement will be locked to initial spawn rotation
* First-person camera will feel disconnected from movement

#### Use Controller Rotation Yaw = False

This prevents the Pawn base class from applying its own rotation, which conflicts with gravity-aligned rotation. Without this:

* Character will try to rotate using world-space yaw (Z-axis only)
* Gravity rotation and pawn rotation will fight each other
* Rotation will break on walls, ceilings, and planets

### Result

With both settings configured:

* Camera look input rotates character around gravity-aligned up axis
* Character orientation stays correct in all gravity directions
* Movement input (WASD) works relative to where you're looking
* Smooth transitions when gravity direction changes
  {% endstep %}

{% step %}

### Choose a Gravity Mode and Parameters

#### Directional Gravity (Classic Down or Any Vector)

In your character:

* Make sure your `CharacterMovementComponent` is selected
* In the Details panel (Right side) find the "Gravity" category
* Set `GravityMode` = `Directional`
* Set `GravityDirectionVector`= your normalized direction (e.g., 0, 0, -1)

#### Planetary Gravity (Attraction to a Point)

In your character:

* Make sure your `CharacterMovementComponent` is selected
* In the Details panel (Right side) find the "Gravity" category
* Set `GravityMode` = `Planetary`
* Set `GravityCenter` = desired world-space point (e.g., level origin or a planet actor's center)

#### **Dynamic Gravity (Multi-Probe Surface Detection)**

In your character:

* Select your `CharacterMovementComponent`
* In the Details panel (right side), locate the **Gravity** category
* Set `GravityMode = Dynamic`
* Set `DynamicGravityTraceChannel` to your configured collision channel

**Important:**

* Create a custom collision channel in **Project Settings → Collision**
* Configure which object types respond to this channel (e.g., `WorldStatic`, `WorldDynamic`, etc.)

**Optional (Surface Forward Probe System):**

* Enable `bUsePredictiveProbes` to activate the Surface Forward Probe system
* When enabled, it drives wall and ledge transitions through fully tunable variables while utilizing full hysteresis
  {% endstep %}

{% step %}

### Setup Movement

#### Update Move Function

* Replace the logic inside the Move function like so:

  <figure><img src="/files/Ti9xSCaaw4DxVZ5o4b54" alt=""><figcaption></figcaption></figure>

{% endstep %}

{% step %}

### Re-parent Template Controller

### Change Controller Parent Class

* Open `BP_ThirdPersonPlayerController`:
* Go to File > Reparent Blueprint
* Search for and choose `GravityController`
* In the Input section of the details panel add 2 Input Mappings
* Set them to the Default Template Input Mappings
  {% endstep %}

{% step %}

### Animation Blueprint Setup

#### Cast to `GravityMovementComponent`

* Drag off the original `MovementComponent` Set node:
* Cast to `GravityMovementComponent`
* Promote it to a variable (Example: `AsGravityMovementComponent`)
* This gives access to custom gravity functions

  <figure><img src="/files/1TR0cESZMroZeho2Tn8Y" alt=""><figcaption></figcaption></figure>

{% endstep %}

{% step %}

### Replace `IsFalling` Logic

Replace all standard `IsFalling` calls:

* Get your `AsGravityMovementComponent` variable
* Call the custom `GetIsFalling()` function (Category: Gravity/Runtime)
* This returns predicted falling (owner) and replicated falling (remotes)
* Fixes animation correctness in all gravity modes

  <figure><img src="/files/vIGrIdIQa18VjoNepQZS" alt=""><figcaption></figcaption></figure>

**Why This Matters**:

* Standard `IsFalling()` only works for Z-down gravity
* Custom `GetIsFalling()` works for arbitrary gravity directions
* Ensures jump/fall animations trigger correctly on walls, ceilings, planets

{% endstep %}

{% step %}

### Fix Equator Animation Issues

* For this we will make one simple change.

* **Change these:**

  <figure><img src="/files/aDHjEZdlo4X2yoP4B5nZ" alt=""><figcaption></figcaption></figure>

  <figure><img src="/files/LT9YjeW4NWn8d0hqyTC0" alt=""><figcaption></figcaption></figure>

* **With these:**

  <figure><img src="/files/U3ObWyd02DclcaFftZuE" alt=""><figcaption></figcaption></figure>

  <figure><img src="/files/b3oJbu9dqrXIBv6HmQ67" alt=""><figcaption></figcaption></figure>

  * *Now our animations will work correctly all the way around the planet.*

{% endstep %}

{% step %}

### Fix Jump Animation Loop Direction

#### Create a rotation vector for gravity-relative velocity:

**Steps**:

* Get `Velocity` (world-space)

* Get `Character`

* Get `ActorRotation`

* `Un-Rotate` the `Velocity` vector by the `ActorRotation`

  <figure><img src="/files/5rAmqfByithLpFk7ZKKc" alt=""><figcaption></figcaption></figure>

* We will Use the `Un-Rotated` `velocity` inside our jump loop.

  <figure><img src="/files/ATsSfOlcVF2lmIBITDZZ" alt=""><figcaption></figcaption></figure>

{% endstep %}

{% step %}

### Add Correct Rotation Direction

<figure><img src="/files/4PA3Ih8ICVyjTyWWmo3c" alt=""><figcaption></figcaption></figure>

* *Now we can drive our animations from the correct directions.*

{% endstep %}

{% step %}

### Fix the Blend Space

#### Open BS\_Idle\_Walk\_Run

* Remove all the animations

  <figure><img src="/files/wEYvlzRKY5gjs6zq66hF" alt=""><figcaption></figcaption></figure>

* Drop down Horizontal Axis and Vertical Axis

* Rename them to Right/Left and Forward/Backward

  <figure><img src="/files/quqE4wbniocn9JY0Y3iR" alt=""><figcaption></figcaption></figure>

* Set Snap To Grid to **False**

* Set Grid Divisions to 4

  <figure><img src="/files/QczitGV1j8DXaybtU0gO" alt=""><figcaption></figcaption></figure>

* Set Minimum Axis Value to -600

* Set Maximum Axis Value to 600

* **Important**: Make sure Snap To Grid is False before changing min/max values

  <figure><img src="/files/QXMeAU3l969rAIMpX4CH" alt=""><figcaption></figcaption></figure>

* Set Snap To Grid back to True

  <figure><img src="/files/UTujsjC3jXD50B6UVvaj" alt=""><figcaption></figcaption></figure>

#### Replace Animations

* Re-add the animations to the blend space at appropriate grid points

  <figure><img src="/files/mjAH7NQ9DXF9DMFHlN9j" alt=""><figcaption></figcaption></figure>

* Now our animations will work correctly.

{% endstep %}

{% step %}

#### Clean Up Unused Nodes

* Delete this:

  <figure><img src="/files/I7uR9yDeS1MYoj7VyqMH" alt=""><figcaption></figcaption></figure>

  * And delete this entire setup:

  <figure><img src="/files/1npRmazDTXSulSliZFfa" alt=""><figcaption></figcaption></figure>

{% endstep %}

{% step %}

### Blueprint Events for Cosmetics

#### Available Events

Use these events for UI, VFX, audio, camera effects, and other cosmetic responses.

#### OnFallingStateChanged

Called whenever the character's falling state changes.

**Parameters**

* bool IsFalling

**Example Uses**

* Dust effects
* Landing effects
* Falling animations
* Audio cues

#### OnEffectiveGravityDirectionChanged

Called whenever the effective gravity direction changes.

**Parameters**

* FVector GravityDirection

**Example Uses**

* Camera effects
* Gravity transition VFX
* UI updates
* Audio feedback

{% endstep %}

{% step %}

### Tuning and Debugging

#### Dynamic Gravity Parameters

`DynamicGravityTraceChannel`:

* Collision channel used for all probes (head, movement, feet)
* Must be configured in Project Settings > Collision
* Set which objects respond (`WorldStatic`, `WorldDynamic`, etc.)

`FallBackDir`:

* The 'Safety' direction used when a Dynamic gravity latch fails or expires
* Usually set to (0,0,-1) to return the character to standard downward gravity
* Used when falling off walls or ceilings without finding new surface

`FallBackTimer`:

* How long the system waits after a ceiling catch before reverting
* Default: 0.5 seconds
* If no floor is found within this time, gravity reverts to `FallBackDir`

`FloorDetectionTolerance`:

* Defines the extra reach for the 'Safety Net' fuzzy probes
* Default: 100 units
* If the standard floor check fails, the system probes this much further below the capsule
* Prevents accidental falling on jagged or poor collision

#### Rotation Parameters

**`RotationSpeed` (deg/s)**:

* Controls quaternion stepping speed for large angle changes
* Higher values = snappier alignment
* Lower values = smoother transitions
* Default: varies by mode

`SurfaceLerpSpeed`:

* Speed at which gravity direction smoothly adjusts during final alignment
* Used in Planetary and Dynamic modes when close to target
* Higher values = faster final snap
* Lower values = smoother final approach

`RotationStopTolerance`:

* Angle threshold for switching from quaternion rotation to snap/lerp
* When current and target directions are within this tolerance, use final alignment method
* Smaller values = more quaternion rotation, smoother large transitions
* Larger values = more snap/lerp, faster small adjustments

#### Debugging

`bShowVisualDebugs`:

* Toggles system-wide visual debugging for gravity
* Shows probe locations, hit points, and active rotation methods
* On-screen messages indicate which rotation path is active
* Essential for tuning Dynamic gravity probe distances

**Debug Indicators** (when enabled):

* Blue line: Current gravity direction
* Red sphere: Head probe hits (ceiling detection)
* Green spheres: Movement probe hits (wall detection)
* Blue capsule: Feet probe with adaptive height
* Yellow line: Final selected direction from best probe hit
* On-screen text: Active rotation method (Quat/Lerp)
  {% endstep %}

{% step %}

### Advanced Features

### Moving Platforms (Important)

#### Important Limitation

Unreal does **not** replicate arbitrary base rotation for non-Z gravity.

This can cause:

* Client visual drift
* Z-down fallback on listen servers

#### Solution

Enable:

```cpp
bApplyReplicatedRotationOnMovingBases = true;
```

What this does:

* Tracks base quaternion changes in `UpdateBasedRotation()`
* Applies gravity-aligned yaw compensation
* Fixes client-side visual desync only
* Does not affect physics or collision

If you do not want base rotation at all:

```cpp
bIgnoreBaseRotation = true;  // Default in constructor
```

### Flying Mode Interaction

#### Default Behavior

Directional gravity does not rotate the character while flying.

* Early-out in `RotateCharacter()` when `MOVE_Flying` and `!bApplyGravityRotationWhileFlying`
* `GravityDirCached` is still updated (for other systems)
* No rotation applied

#### Optional

To force gravity-aligned rotation while flying:

```cpp
bApplyGravityRotationWhileFlying = true;
```

Notes:

* Handled in `UpdateCharacterStateBeforeMovement()`
* Rotation is interpolated
* Forward direction is preserved
  {% endstep %}
  {% endstepper %}

### Summary

Your character is now ready for:

* Arbitrary gravity directions (walls, ceilings, planets)
* Network replication with prediction
* Moving and rotating platforms
* Correct animations in all orientations
* Dynamic surface detection and transitions


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://replicated-gravity.gitbook.io/replicated-gravity-docs/getting-started/setup-guides-and-tutorials/first-person-template-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
