Created
May 15, 2021 23:17
-
-
Save Elmuti/5fc0aadaa4fbea17b38c919b72c24da6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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