Unity Character Controller Samples

repository·master·Indexed 18 days ago

https://github.com/unity-technologies/charactercontrollersamples

A collection of sample projects demonstrating the capabilities and customization of the Unity Character Controller package. Includes a Basic character playground for fundamental interactions, a StressTest project for performance profiling, a Platformer sample for advanced movement, and an OnlineFPS sample showcasing client-predicted movement using DOTS Netcode.

Tokens
29.6K
Snippets
39
Records
120
Agent score
64%

What's inside unity-technologies-charactercontrollersamples

  1. Explore the OnlineFPS Sample

    master

    The OnlineFPS Sample is a demonstration of a fast-paced, client-predicted online first-person shooter (FPS) game. It is implemented using DOTS Netcode to handle networked gameplay and client-side prediction.

    To understand the specific implementation details of this sample, refer to the following specialized guides:

    • Building & Playing: Instructions on how to compile and run the sample.
    • Game Management: Details on how game states and sessions are handled.
    • Input, Character & Camera: How player input is processed and how the character and camera systems are integrated.
    • Weapons: Implementation details for the weapon systems within the networked environment.
  2. Manage camera transitions in OrbitCameraSystem

    master
    Camera behavior is managed by the OrbitCameraSystem. While it follows the standard third-person camera patterns, it includes specialized logic for managing smooth transitions between different camera targets and parameters. These transitions are driven by the current state of the character. The transition logic is located within the OrbitCameraSystem under the // Camera target handling comment block.
  3. Implementing Prefab projectile weapons

    master

    Prefab weapons (e.g., RocketLauncher, PlasmaGun) spawn projectiles as ghost prefabs that handle their own movement and collision.

    Simulation Flow

    1. Spawning: WeaponsSimulationSystem runs a PrefabWeaponSimulationJob. For each event in the WeaponProjectileEvent buffer, it spawns a projectile prefab on the server and as a predicted prefab on clients.
    2. Resolution: ProjectileClassificationSystem resolves predicted-spawned projectile ghosts on clients with the authoritative server ghosts once they arrive.
    3. Movement & Collision:
      • ProjectileSimulationsJob serves as the base job for movement and collision.
      • Specialized jobs like ProjectileBulletSimulationJob (for plasma) and RocketSimulationJob (for rockets) extend this logic for specific projectile behaviors.
  4. Optimize Third Person Orbit Camera Netcode

    master

    For third-person characters using an orbit camera, you can apply the following optimizations:

    • Target Distance: If the simulation doesn't rely on the camera's exact position or distance, remove the ghost field attribute from OrbitCamera.TargetDistance. Move distance/position handling to the non-predicted OrbitCameraLateUpdateSystem before orbitCamera.SmoothedTargetDistance is calculated.
    • Non-Ghost Camera: Avoid making the orbit camera prefab a ghost entirely. Instead, have character components/systems calculate and store a "camera rotation". The owning client spawns a local (non-ghost) camera prefab that follows this stored rotation. Use this stored rotation for movement/rotation logic instead of the camera entity's actual rotation.
    • Camera Yaw: If the camera only rotates around the world up axis and doesn't need to follow changes in the character's up direction, replace the float3 PlanarForward ghost field with a simple float YawAngle to reduce bandwidth.
  5. Understand the GroundMoveState in the Platformer Sample

    master

    The GroundMoveState is responsible for standard grounded movement logic within the Platformer Sample. It manages several key behaviors:

    • Movement Types: Handles regular walking, sprinting, and jumping.
    • Surface Detection: Detects "sticky surfaces" (allowing the character to walk on walls) and "friction surfaces" (such as ice).
    • Rotation Adaptation: Automatically adapts the character's rotation to match the orientation of detected friction surfaces.
    • Jump Grace Times: Implements JumpBeforeGroundedGraceTime, which allows a jump input to be registered slightly before the character actually touches the ground, ensuring more responsive controls.

    Transition Logic: Typically, the character transitions into this state when they are grounded and not performing other specific actions like crouching.

  6. Implement air movement and jumping with AirMoveState

    master

    In the Platformer Sample, AirMoveState is the state responsible for handling standard air movement, air jumping, and detecting ungrounded walls (which is a prerequisite for wall-running transitions).

    Key features include:

    • Air Movement & Jumping: Manages standard physics and input while the character is airborne.
    • Wall Detection: Detects ungrounded walls to facilitate transitions into wall-running states.
    • Jump Grace Time: Supports a 'coyote time' mechanic via JumpAfterUngroundedGraceTime. This allows a jump input to be registered slightly after the character has left a grounded surface, treating the character as if they were still grounded for the purpose of the jump.

    Transition Logic: Typically, the character transitions to AirMoveState whenever they are not grounded and are not performing any other specialized aerial actions (such as wall running).

  7. Optimize Character Rotation Synchronization

    master

    If your character only rotates around the world up axis, you can reduce bandwidth by synchronizing only the Y euler angle instead of a full quaternion.

    To implement this:

    1. Add a prediction system that runs in the PredictedSimulationSystemGroup before the PredictedFixedStepSimulationSystemGroup.
    2. Reconstruct the character's LocalTransform.Rotation from the Y euler angle.
    3. Ensure this reconstruction happens before any other system uses the rotation (e.g., before OrbitCameraPrePhysicsSystem if using a third-person character).
  8. Implement Planet Gravity for characters

    master

    Gravity in this sample is managed via a combination of components and systems rather than standard physics engine gravity.

    • CustomGravity: A component placed on entities to receive gravity calculations.
    • GravityZonesSystem: Calculates spherical gravity for entities within a SphericalGravityZone or applies global gravity via GlobalGravityZone to those not in a specific zone.
    • Character Integration: Because the character is not a dynamic body, it does not have its velocity modified automatically by the GravityZonesSystem. Instead, the character must manually add the calculated gravity to its KinematicCharacterBody.RelativeVelocity within its state updates. The character should also orient its rotation to point towards the opposite of the custom gravity's direction.
  9. Optimize Netcode for Character and Player Entities

    master

    To reduce the number of ghosts being synchronized, you can merge the Player and the Character into a single entity if your game design does not require switching controlled characters or destroying character entities independently of player data.

    If you merge them, you should also optimize your Player systems to access components directly on the same entity rather than performing lookups to find the associated character entity.

  10. How ClimbingState works in the Platformer Sample

    master

    The ClimbingState enables characters to climb surfaces tagged with specific physics tags.

    Key Behaviors:

    • Collision Management: Upon entering the state (OnStateEnter), the character's standard collision detection is disabled. The state takes over manual collision detection and velocity projection.
    • Shape Transformation: To prevent rotation-induced jitter, the character's capsule collider is converted into a sphere shape during the state. This ensures that as the character rotates to align with the climbing surface normal, the detected hits remain consistent.
    • Movement Logic: The state follows a specific update loop:
      1. Detect climbing hits via ClimbingState.ClimbingDetection.
      2. Stitch the character close to the climbing surface.
      3. Move towards the input direction, projected onto the climbing surface normal.
      4. Project velocity against non-climbable obstructions using the VelocityProjectionHits buffer and PlatformerCharacterAspect.ProjectVelocityOnHits.
      5. Orient the character towards the average climbing normal.

    Transitioning to Climbing: Transition occurs when the climb input is pressed while near a climbable surface. Other states check ClimbingState.CanStartClimbing to determine if this transition is valid.

  11. Implementing Raycast projectile weapons

    master

    Raycast weapons (e.g., MachineGun, RailGun, Shotgun) use instantaneous raycasts for hit detection. The projectiles themselves are purely visual prefabs.

    Simulation Flow

    WeaponsSimulationSystem runs a RaycastWeaponSimulationJob for entities with RaycastWeapon and DynamicBuffer<RaycastWeaponVisualProjectileEvent>. For every event in the WeaponProjectileEvent buffer, the job:

    1. Performs a raycast to detect hits.
    2. Adds a RaycastWeaponVisualProjectileEvent to spawn visuals.
    3. Applies damage to the hit entity.

    Network Synchronization Modes

    The system provides two modes via RaycastWeaponProjectileVisualsJob:

    • Precise Mode: Maintains a synchronized buffer of RaycastWeaponVisualProjectileEvent on the weapon entity. This buffer contains exact start/end points and ticks, allowing remote clients to recreate visuals exactly. Events are cleared by the server after a certain tick age.
    • BandwidthEfficient Mode: Does not use a visual event buffer. Instead, it compares BaseWeapon.TotalProjectilesCount (ghost) against BaseWeapon.LastVisualTotalProjectilesCount (local) to determine how many visuals to spawn. Projectile spread is reconstructed deterministically using a seed derived from the projectile index. This mode uses the latest interpolated weapon transform, sacrificing some precision for significantly lower bandwidth.