I’m trying to write a script that prevents players from going threw walls by projecting a raycast from the last saved position to the current position and pushing the player in the correct position, however it’s proving to be rather difficult to figure out how to pull off as the player seem to teleport in front of the wall and get stuck. I also attempted to simply just set the player to the last position to no avail. How do I solve this?
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local rootPart = character:WaitForChild("HumanoidRootPart")
local cam = character:WaitForChild("Camera")
local BlackList = {character, game.ReplicatedStorage.Resources}
local Players = game:GetService("Players")
local Char = Players.LocalPlayer.Character
local Hum = Char:WaitForChild("Humanoid")
local Root = Char:WaitForChild("HumanoidRootPart")
local lastRootPosition = rootPart.Position
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
--raycastParams.FilterDescendantsInstances = BlackList
raycastParams.CollisionGroup = "Players"
--local viewpart = Instance.new("Part")
--viewpart.CanCollide = false
--viewpart.CanQuery = false
--viewpart.Parent = workspace
local function createRay(dt)
--viewpart.Position = lastRootPosition
local currentRootPosition = rootPart.Position
local ray = workspace:Raycast(lastRootPosition, (currentRootPosition - lastRootPosition).Unit * (currentRootPosition - lastRootPosition).Magnitude, raycastParams)
if ray then
local part = ray.Instance
if part and part.CanCollide then
rootPart.Position = lastRootPosition + ray.Normal
rootPart.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
rootPart.AssemblyAngularVelocity = Vector3.new(0, 0, 0)
else
lastRootPosition = currentRootPosition
end
else
lastRootPosition = currentRootPosition
end
end
RunService.RenderStepped:Connect(createRay)
Have you tried offsetting the raycast .Normal value? Players are being teleported into the wall because you’re positioning the rootPart. The rootPart is not directly in front of the player but rather directly on the inside of the character model, hence, ~50% of the character model will be stuck into the wall when you try to position the rootPart at the exact point of the .Normal coordinate. Instead, try offsetting the .Normal value by say 5 or so studs and this should suffice in teleporting the player in front of the wall, and not halfway inside the wall.
Yes I have done this, however when I do it. It seems to depend on luck if it works or not, so I have to make it a larger value like 10 which risks teleporting outside another wall if they are too close to each other. I want the exact point where to place the player while keeping them in bounds.
I have a couple of solutions to this so I’ll start with the first one that came to mind. When a player dashes shoot ray casts rapidly until the dashing stops. While the ray casts are being fired, detect how close a player is to a wall then cancel the dash
Isn’t that the direction perpendicular to the surface hit? If thats the case, wouldn’t the offset become too large/small if you hit the surface at an angle? (and wouldn’t the direction be wrong since you should be going by the angle of the ray not the surface you hit)
You would be right, this code assumes the player went entire threw the wall in the past frame and the current frame, however since from what the first person mentioned the normal seems to be hitting at the opposite angle of what I should be using 50% of the time.
In that case, perhaps try to calculate the actual correct angle using a bit of trig and the start and end position, since that the actual direction you want to offset in to send the player back where they came from.
I can’t think of a method at the top of my head, but theres only a single right triangle between 2 points in a 2D space, and so you can probably use the 3 right triangles (one on each of the 3 planes formed by the 3 axises) to find the angle you want.
(this might actually be an appropriate question to ask ChatGPT lol)
Actually I rethought about this a bit and i’m pretty sure the idea is that you want to find a point 5 studs away from the final point on the line formed by the final and initial point. That might (or might not) help.
The answer from ChatGPT was that the location of the 3rd point is
(X+N*(X2-X)/Magnitude, Y+N*(Y2-Y)/Magnitude, Z+N*(Z2-Z)/Magnitude)
For points (X, Y, Z) and (X2, Y2, Z2) with offset N
Magnitude is just the distance between the first and last point
(I can’t garantee that works, I haven’t actually tried it myself)
Im deducing that you’re using AssemblyLinearVelocity for your dash.
Instead of raycasting, why not just detect when the player hits a wall? Its much simpler
local wall = script.Parent
wall.Touched:Connect(function(hit)
if not hit.Parent:FindFirstChild("Humanoid") then return end
local char = hit.Parent
if not char:GetAttribute("IsDashing") then return end
char:SetAttribute("IsDashing",false)
char.HumanoidRootPart.AssemblyLinearVelocity = Vector3.zero
char.HumanoidRootPart.CFrame *= CFrame.new(-char.HumanoidRootPart.CFrame.LookVector * 5)
end)
This isn’t a very good solution, because that would mean I would have to put a wall touched in every single part in the game which is also very expensive.