Snowboard Clipping Into Floor

Hello! I’ve been trying to fix an issue where my snowboard begins clipping into the floor when moving up slopes. I tried finding solutions to this problem, but I couldn’t seem to find any. Does anyone know how to fix this??

It works perfectly fine when not moving

External Media

The code is messy since I was in a rush :sweat_smile:

local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")

local Player = game.Players.LocalPlayer
local Character = Player.Character
local RootPart = Character:WaitForChild("HumanoidRootPart")
local Humanoid: Humanoid = Character:WaitForChild("Humanoid")
local Animator: Animator = Humanoid:WaitForChild("Animator")

local FloorAlignmentSpeed = 7

local StartupSpeed = 7
local HaltSpeed = 4.5
local DefaultSpeed = 45
local Speed = DefaultSpeed

local defaultC0 = Character.LowerTorso.Root.C0
local defaultC01 = Character.Hoverboard.PrimaryPart.Motor6D.C0
local defaultC02 = Character.UpperTorso.Waist.C0


local BodyVelocity = Instance.new("BodyVelocity",RootPart)
local BodyGyro = Instance.new("BodyGyro",RootPart)
BodyGyro.MaxTorque = Vector3.new(1,1,1)*math.huge
BodyGyro.D = 390
BodyGyro.P = 6575
BodyVelocity.MaxForce = Vector3.new(100_000,0,100_000)

local AnimationsFolder: Folder = script.Animations

local LoadedAnimations: {[string]: AnimationTrack} = {}

for _,animation: Animation in AnimationsFolder:GetChildren() do
    if animation:IsA("Animation") then
        LoadedAnimations[animation.Name] = Animator:LoadAnimation(animation)
    end
end

task.defer(function()
    LoadedAnimations.Idle:Play(0)
end)

RootPart:WaitForChild("Running").Volume = 0

local moving = false

local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.IgnoreWater = true
rayParams.FilterDescendantsInstances = {Character}


local function Lerp(a,b,t)
    return a + (b-a)*t
end

local Dot1 = Instance.new("Part")
Dot1.Size = Vector3.one/4
Dot1.BrickColor = BrickColor.Yellow()
Dot1.Anchored = true
Dot1.CanCollide = false
Dot1.CanQuery = false
Dot1.Material = "Neon"
Dot1.Parent = workspace

local Dot2 = Dot1:Clone()
Dot2.BrickColor = BrickColor.Green()
Dot2.Parent = workspace

local Dot3 = Dot1:Clone()
Dot3.BrickColor = BrickColor.Blue()
Dot3.Parent = workspace

local Highlight1 = Instance.new("Highlight",Dot1)
Highlight1.FillTransparency = 1
local Highlight2 = Instance.new("Highlight",Dot2)
Highlight2.FillTransparency = 1
local Highlight2 = Instance.new("Highlight",Dot3)
Highlight2.FillTransparency = 1

-- FIND A WAY TO MAKE IT STOP SINKING AT HIGH SPEEDS


RunService.RenderStepped:Connect(function(deltaTime)
    local MoveDirection = Humanoid.MoveDirection
    local Magnitude = MoveDirection.Magnitude

    local ray = workspace:Raycast(RootPart.Position + Vector3.new(0,2,0), Vector3.new(0,-10,0), rayParams)
    local ray2 = workspace:Raycast((RootPart.CFrame +( RootPart.CFrame.LookVector*(Character.Hoverboard:GetExtentsSize().Z/2))).Position+ Vector3.new(0,2,0), Vector3.new(0,-10,0), rayParams)
    local ray3 = workspace:Raycast((RootPart.CFrame +( RootPart.CFrame.LookVector*-(Character.Hoverboard:GetExtentsSize().Z/2))).Position+ Vector3.new(0,2,0), Vector3.new(0,-10,0), rayParams)
    
    local upVector = Vector3.yAxis

	local Offset = CFrame.new(0,2,0)
	
	Character.UpperTorso.Waist.C0 =Character.UpperTorso.Waist.C0:Lerp( defaultC02 * CFrame.Angles(Humanoid.MoveDirection.Z/2,0,0) , deltaTime*3)

    if ray then

        local vector = RootPart.CFrame:VectorToObjectSpace(ray.Normal)
        local vector2 = RootPart.CFrame:VectorToObjectSpace(ray2.Normal)
        local vector3 = RootPart.CFrame:VectorToObjectSpace(ray3.Normal)
        
        local averageVector = (vector+vector2+vector3)/3

        local dot = ray.Normal:Angle(RootPart.CFrame.UpVector) 
        dot = math.deg(dot)
        local dot2 = ray2.Normal:Angle(RootPart.CFrame.UpVector) 
        dot2 = math.deg(dot2)
        local dot3 = ray3.Normal:Angle(RootPart.CFrame.UpVector) 
        dot3 = math.deg(dot3)
        
        local averageDot = (dot+dot2+dot3)/3

        
        Speed = Lerp(Speed,DefaultSpeed + -dot/4,deltaTime*2.5)
        

        Dot1.Position = ray.Position
        Dot2.Position = ray2.Position
        Dot3.Position = ray3.Position
        

        local CF0 = defaultC0 * CFrame.Angles(averageVector.x, 0, averageVector.z)
        local CF1 = defaultC02 * CFrame.Angles(averageVector.z, 0, -averageVector.x)


        local NewOffset =  Character.Hoverboard.PrimaryPart.Position -(ray.Position + Offset.Position) 
        
        Character.LowerTorso.Root.C0 = Character.LowerTorso.Root.C0:Lerp(CF0  ,deltaTime*FloorAlignmentSpeed)
        Character.Hoverboard.PrimaryPart.Motor6D.C0 = Character.Hoverboard.PrimaryPart.Motor6D.C0:Lerp(CF1 ,deltaTime*FloorAlignmentSpeed)


        local PredeterminedSize = Lerp(0,Character.Hoverboard:GetExtentsSize().Y*2,math.abs(averageDot)/40)
        
        PredeterminedSize *= deltaTime*FloorAlignmentSpeed
        

        Character.Hoverboard.PrimaryPart.Motor6D.C0 *= CFrame.new(0,PredeterminedSize,0)
        Character.LowerTorso.Root.C0 *= CFrame.new(0,PredeterminedSize,0)
        
    

    end

    if Humanoid.FloorMaterial == Enum.Material.Air then
        Character.Hoverboard.PrimaryPart.Trail.Enabled = false
    else
        Character.Hoverboard.PrimaryPart.Trail.Enabled = true
    end
    BodyGyro.CFrame = CFrame.lookAlong(RootPart.Position,MoveDirection)

    if Humanoid.FloorMaterial == Enum.Material.Air then
        if not LoadedAnimations.Jump.IsPlaying then
            LoadedAnimations.Jump:Play(0.3)
        end
    else
        if LoadedAnimations.Jump.IsPlaying then
            LoadedAnimations.Jump:Stop(0.25)
        end
    end



    if Magnitude == 0 then

        if LoadedAnimations.Move.IsPlaying then
            LoadedAnimations.Move:Stop(0.325)
        end

        BodyGyro.MaxTorque = Vector3.zero
        BodyVelocity.Velocity = BodyVelocity.Velocity:Lerp(Vector3.zero,HaltSpeed*deltaTime)

        if moving and Humanoid.FloorMaterial ~= Enum.Material.Air then
            moving = false

            if not LoadedAnimations.Halt.IsPlaying then
                LoadedAnimations.Halt:Play(0.325)

                task.delay(0.6*BodyVelocity.Velocity.Magnitude/24,function()
                    LoadedAnimations.Halt:Stop(0.325)
                end)
            end
        end

    else

        if not LoadedAnimations.Move.IsPlaying then

            LoadedAnimations.Move:Play(0.325)
        end

        moving = true


        local Target = MoveDirection*Speed

        BodyVelocity.Velocity = BodyVelocity.Velocity:Lerp(Target,StartupSpeed*deltaTime)
        BodyGyro.MaxTorque = Vector3.new(1,1,1)*math.huge

    end

end)







PS: The animation is not at fault here & I didn’t use a vehicle seat, just regular old animation (Motor6D Attachment).

1 Like

try decreasing the lerp. it WILL look rougher but it will somewhat decrease the clipping

If your environment has actually snow and you emit some snow particles while the board is clipping then I see no problem. :slight_smile:

I fixed it by detecting if the character is tilted a certain way and lifted the character up by the speed they go