So I have tried to make a custom collision system by checking if the part is inside a part and then setting the velocity to reflect off of it. My system isn’t very accurate so I need a better one.
Game File:
Collision Test.rbxl (54.2 KB)
Movement Script:
local RunService = game:GetService("RunService")
local part = script.Parent
part:SetAttribute("CurrentPosition", part.Position)
local movingCoroutine = nil
local function StopMoving()
if movingCoroutine and coroutine.status(movingCoroutine) ~= "running" then
coroutine.close(movingCoroutine)
movingCoroutine = nil
end
end
local function MoveToTarget(delta)
local origin = part:GetAttribute("CurrentPosition")
local WalkSpeed = part:GetAttribute("WalkSpeed")
local Velocity = part:GetAttribute("Velocity")
local cframe = part.CFrame
local lookVector = cframe.LookVector
local newPosition = origin + (lookVector * WalkSpeed) + Velocity
local distance = math.abs((newPosition - origin).Magnitude)
local timeToReachTarget = distance / WalkSpeed
local alpha = math.clamp(delta / timeToReachTarget, 0, 1)
local lerp = origin:Lerp(newPosition, alpha)
part.Position = lerp
part:SetAttribute("CurrentPosition", lerp)
end
RunService.Heartbeat:Connect(function(delta)
MoveToTarget(delta)
end)
Collision Script:
local RunService = game:GetService("RunService")
local part = script.Parent
local overlapParams = OverlapParams.new()
overlapParams.FilterDescendantsInstances = {part}
overlapParams.FilterType = Enum.RaycastFilterType.Exclude
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {part}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local function DetectCollision()
local origin = part:GetAttribute("CurrentPosition")
local WalkSpeed = part:GetAttribute("WalkSpeed")
local LookVector = part.CFrame.LookVector
local parts = workspace:GetPartsInPart(part, overlapParams)
local collided = #parts > 0
if not collided then
part:SetAttribute("Velocity", Vector3.new())
else
for i,v in ipairs(parts) do
local position = (v.Position - origin)
local direction = position.Unit * position.Magnitude
local raycast = workspace:Raycast(origin, direction, raycastParams)
if raycast then
local normal = raycast.Normal
local dot = LookVector:Dot(normal)
dot = if (math.abs(dot) == 0) then 1 else dot
local reflection = LookVector - 2 * dot * normal
local velocity = reflection.Unit * WalkSpeed
local position = origin + velocity
part:SetAttribute("Velocity", velocity)
end
end
end
end
RunService.Heartbeat:Connect(function()
DetectCollision()
end)
Video:
It would sometimes go through parts.