Casting Rays to the side to keep distance to the wall?

Hello community!

Maybe you saw my post regarding leaning with the hovercraft and now I am thinking about adding another thing. I was thinking on maybe adding something so the hovercraft cannot actually hit the walls and always keeps a distance to it.

I was thinking of maybe casting rays to the side of the vehicle and moving the hovercraft If needed ( if the hovercraft is to close to a wall ) So it never actually touches a wall and always keeps a distance :))

Any ideas on how to do this code-wise?
If not, any ideas on how to do this better?

Btw. having an invisible part acting as a hitbox isnt the solution I am looking for

3 Likes

What I’d do is detect if a part is intercepting the ray then I’d run the code to move the hovercraft.
Make sure to blacklist the hovercraft.

Why are you opposed to using invisible parts acting as hitboxes? Maybe you could use them in a way you are not considering (we can use them to avoid lots of raycasts and then perform some math to do the actual adjustments).

You may be interested in my GJK implementation. Given a function defining the convex hull of the hovercraft, it will find the distance to the wall. You can then use the rejection of the velocity on the wall to determine how long until a collision and thus how much force to apply to escape.

(Sorry, meant to update my last post)

That sounds very interesting, do you mind helping me out?
Sounds like it would work

I have a fairly simple way to do this. I’ll try to explain it as much as I can, but if you only want the code, I’ll have it at the bottom of the post.

First of all, let’s define some constants:

local push_force = 30;
local check_dist = 10;

local origin = your_vehicle.PrimaryPart; -- change if needed, this is an example
local force = your_vehicle.BodyForce; -- this is your main force

check_dist is your distance from the wall, push_force is the amount of force used to push your vehicle.
Now, let’s get into the meat!

local rs = game:GetService("RunService");

local function check_dir(direction)
    local ray = Ray.new(origin.Position, direction*check_dist);
    local part = workspace:FindPartOnRayWithIgnoreList(ray, {your_vehicle});
    if part then
        return true;
    end
    return false;
end

rs.Heartbeat:Connect(function()
    force.Force = Vector3.new(); -- reset force

    for i = 1, 4 do
        local direction;

        if i == 1 then
            direction = origin.CFrame.LookVector; -- front
        elseif i == 2 then
            direction = -origin.CFrame.LookVector; -- back
        elseif i == 3 then
            direction = origin.CFrame.RightVector; -- right
        elseif i == 4 then
            direction = -origin.CFrame.RightVector; -- left
        end

        if check_dir(direction) then
            force.Force = force.Force + -direction*push_force;
        end
    end
end);

check_dir checks whether a given direction is obstructed, using check_dist as the distance from the wall.
force.Force = force.Force + -direction*push_force; takes the direction, makes it negative (so it faces the opposite direction), multiplies it by push_force for the extra oomp, then finally adds it to the net force on force.

Final code:
local rs = game:GetService("RunService");

local push_force = 30;
local check_dist = 10;

local origin = your_vehicle.PrimaryPart; -- change if needed, this is an example
local force = your_vehicle.BodyForce; -- this is your main force

local function check_dir(direction)
    local ray = Ray.new(origin.Position, direction*check_dist);
    local part = workspace:FindPartOnRayWithIgnoreList(ray, {your_vehicle});
    if part then
        return true;
    end
    return false;
end

rs.Heartbeat:Connect(function()
    force.Force = Vector3.new(); -- reset force

    for i = 1, 4 do
        local direction;
        if i == 1 then
            direction = origin.CFrame.LookVector; -- front
        elseif i == 2 then
            direction = -origin.CFrame.LookVector; -- back
        elseif i == 3 then
            direction = origin.CFrame.RightVector; -- right
        elseif i == 4 then
            direction = -origin.CFrame.RightVector; -- left
        end

        if check_dir(direction) then
            force.Force = force.Force + -direction*push_force;
        end
    end
end);

Hope I helped :wink:

This was typed on a mobile device so feel free to yell at me if there’s any mistakes :blush:

First of all I appreciate your help!
But inserting the code didn’t work for me. I removed some errors that occured, example: Chaning Line 7, the Origin. It’s important to get the CFrame of that obj. In my example

local origin = script.Parent.Chassis.CFrame

But for some reason it’s not doing what it is supposed to do rn.
I inserted some print statements to see what he is detecting and it is printing everything out. every direction.

Code:

local rs = game:GetService("RunService");
local hovercraft = script.Parent

local push_force = 30;
local check_dist = 10;

local origin = hovercraft.Chassis.CFrame -- change if needed, this is an example
local force = hovercraft.Chassis.BodyForce; -- this is your main force

local function check_dir(direction)
    local ray = Ray.new(origin.Position, direction*check_dist);
    local part = workspace:FindPartOnRayWithIgnoreList(ray, {hovercraft});
    if part then
        return true;
    end
    return false;
end

rs.Heartbeat:Connect(function()
    for i = 1, 4 do
        local direction;
        force.Force = Vector3.new(); -- reset force

        if i == 1 then
	print("Front")
            direction = origin.LookVector; -- front
        elseif i == 2 then
	print("Back")
            direction = -origin.LookVector; -- back
        elseif i == 3 then
	print("Right")
            direction = origin.RightVector; -- right
        elseif i == 4 then
	print("Left")
            direction = -origin.RightVector; -- left
        end

        if check_dir(direction) then
            force.Force = force.Force + -direction*push_force;
        end
    end
end);
1 Like

Maybe my ignorelist is wrong? Hovercraft is the whole model. Isnt that correct?

pushforce = 30 is faar too low to stop something like a hovecraft from colliding,maybe increase it to 200-1000 also you might wanna add the character in the ignore list aswell.

Aha! Thanks for pointing that out. In your edit, however, you referenced origin.CFrame only once at the beginning of the script, which will cause issues. I’ve edited my code and it should probably work a lot better.

Also fixed a small logical error, it’s supposed to reset the force once per loop, but it was doing it four times.

I’ll try it out in a minute! :))

1 Like

Aight, because it is still not working, I’ll show some stuff so you guys can get a better understanding.
This is my Explorer tab for the hovercaft
image

I want it to push away from these walls

and I am using the code you have me in a diffrent normal script inside the hovercraft ( see photo 1 , it’s called Collision )

Is Collision the script I sent earlier?
If so, you should probably switch to a LocalScript since client-sided physics is almost always better. If you haven’t already, use SetNetworkOwner() from a Script so that the player can fully control the vehicle’s physics without interference.

I tried that too now and It didnt seem to work hm.
Here is the whole model for you, I am sorry if it takes so long to figure out!
Thanks for the help!
hovercraftnew.rbxm (112.9 KB)

Alright. Its getting the distance and ray correctly . I checked it with a print statement to see when it “would” push the vehicle away from the wall.
But even with force 600 it’s not doing much

Oh. Fixed it with changes to the force :)) 20k made it work. I’ll adjust it some more