Skip to content

Instantly share code, notes, and snippets.

@Elmuti
Created May 15, 2021 23:17
Show Gist options
  • Save Elmuti/5fc0aadaa4fbea17b38c919b72c24da6 to your computer and use it in GitHub Desktop.
Save Elmuti/5fc0aadaa4fbea17b38c919b72c24da6 to your computer and use it in GitHub Desktop.
local function raycast(orig, dir)
return workspace:FindPartOnRayWithIgnoreList(Ray.new(orig, dir), {char, workspace.Ignore, workspace.PlayerSpawns, workspace.ItemPickups, workspace.ItemSpawns, workspace.Nodes})
end
-- Radius of player's hitbox:
local playerRadius = 2.95
-- STEP 1: cast forward into movement direction to find initial collision with wall:
-- (i.e. so you dont teleport the player into wall to begin with)
local origin = char:GetPrimaryPartCFrame().p -- player's current position
local movement = playerVelocity * dt -- player's movement vector
local movement_xz_unit = (playerVelocity * Vector3.new(1,0,1)).unit
local hitboxadjust = movement_xz_unit * playerRadius -- offset to be applied to take into account hitbox as well
-- Check for hit within movement vector:
local hit, hitpos = raycast(origin, movement)
if hit then
-- Hit found, so move to the wall position and move back from wall by hitboxadjust:
hitwall = true
origin = hitpos - hitboxadjust
playerVelocity = Vector3.new(0, playerVelocity.Y, 0)
else
-- No hit, simply move to the position:
origin = origin + movement
end
-- STEP 2: cast in a fan to check for collisions:
-- (i.e. making sure a player is approximately playerRadius away from any objects in any direction)
-- Precalculate direction vectors for angle-pairs:
local directionVector = {}
for i = -180, -0.1, 22.5 do
directionVector[i] = CFrame.Angles(0,math.rad(i),0) * hitboxadjust
end
-- Which angle-pairs have been done:
local done = {}
-- Do 8 rounds of correction (one for each angle-pair):
for _ = 1,8 do
-- Running variables:
local m = .001 -- Magnitude of maximum displacement
local n = nil -- Maximum displacement
local o = nil -- Angle of maximum displacement
-- Loop over all angle-pairs:
for i = -180, -0.1, 22.5 do
-- If we have corrected at this angle-pair already then we won't correct again this frame:
if not done[i] then
-- Raycast positive/negative angle (these rays are opposite):
local hit1, pos1 = raycast(origin, directionVector[i])
local hit2, pos2 = raycast(origin, -directionVector[i])
-- Determine offset in this angle-pair:
local off = Vector3.new(0,0,0)
if hit1 then
-- For negative angle:
hitwall = true
off = (directionVector[i] - (pos1 - origin))
end
if hit2 then
-- For positive angle:
hitwall = true
off = off + (-directionVector[i] - (pos2 - origin))
end
-- Check if displacement is greater than the tracked displacement:
if off.magnitude > m then
-- It's bigger, so update running variables:
m = off.magnitude
n = off
o = i
end
end
end
-- Check if a maximum displacement was found:
if o then
-- Apply the displacement for angle-pair 'o':
origin = origin - n
-- This angle-pair is now done:
done[o] = true
else
-- No displacement in any direction, so just stop:
break
end
end
char:SetPrimaryPartCFrame(CFrame.new(origin) * CFrame.Angles(0, -mouseAngles.X, 0))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment