docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Limit sliding along walls

    When your character is moving against a wall, you might want to prevent it from sliding sideways along the wall. Or, you might want to simulate a friction with the wall to slow down the character velocity. To do this, you can use the ProjectVelocityOnHits callback of your character aspect.

    Ir order to prevent wall sliding completely, you can get the regular sliding velocity solved by the default implementation of the callback, but if it detects that the character is moving against a wall within a certain angle threshold, project the velocity to keep only the vertical part of it:

    public void ProjectVelocityOnHits(
        ref ThirdPersonCharacterUpdateContext context,
        ref KinematicCharacterUpdateContext baseContext,
        ref float3 velocity,
        ref bool characterIsGrounded,
        ref BasicHit characterGroundHit,
        in DynamicBuffer<KinematicVelocityProjectionHit> velocityProjectionHits,
        float3 originalVelocityDirection)
    {
        ThirdPersonCharacterComponent characterComponent = CharacterComponent.ValueRO;
        KinematicCharacterBody characterBody = CharacterAspect.CharacterBody.ValueRO;
        
        // Remember velocity before it was projected
        float3 velocityBeforeProjection = velocity;
        
        CharacterAspect.Default_ProjectVelocityOnHits(
            ref velocity,
            ref characterIsGrounded,
            ref characterGroundHit,
            in velocityProjectionHits,
            originalVelocityDirection,
            characterComponent.StepAndSlopeHandling.ConstrainVelocityToGroundPlane);
    
        // if the latest hit was not-grounded and was within a certain angle threshold with our original velocity (that threshold is calculated with the dot product)...
        KinematicVelocityProjectionHit latestHit = velocityProjectionHits[velocityProjectionHits.Length - 1];
        if (!latestHit.IsGroundedOnHit && math.dot(latestHit.Normal, math.normalizesafe(velocityBeforeProjection)) < -0.85f)
        {
            // ...project the final velocity onto the up vector, to keep only the vertical part of it
            velocity = math.projectsafe(velocity, characterBody.GroundingUp);
        }
    }
    

    The velocity projection works with a collection of all hits so far in the frame to better deal with creases and corners. But the last hit in the velocityProjectionHits buffer represents the most recent hit.

    Without this change:

    With this change:

    If you don't want to completely stop the velocity horizontally, but instead simulate a certain friction or slowdown when the character moves against a wall, you could do something like this instead, which reduces velocity:

    public void ProjectVelocityOnHits(
        ref ThirdPersonCharacterUpdateContext context,
        ref KinematicCharacterUpdateContext baseContext,
        ref float3 velocity,
        ref bool characterIsGrounded,
        ref BasicHit characterGroundHit,
        in DynamicBuffer<KinematicVelocityProjectionHit> velocityProjectionHits,
        float3 originalVelocityDirection)
    {
        ThirdPersonCharacterComponent characterComponent = CharacterComponent.ValueRO;
        
        CharacterAspect.Default_ProjectVelocityOnHits(
            ref velocity,
            ref characterIsGrounded,
            ref characterGroundHit,
            in velocityProjectionHits,
            originalVelocityDirection,
            characterComponent.StepAndSlopeHandling.ConstrainVelocityToGroundPlane);
    
        // if the latest hit was not-grounded...
        KinematicVelocityProjectionHit latestHit = velocityProjectionHits[velocityProjectionHits.Length - 1];
        if (!latestHit.IsGroundedOnHit)
        {
            // Reduce the final solved velocity
            velocity *= 1f - frictionRatio;
        }
    }
    
    In This Article
    Back to top
    Copyright © 2024 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)