Ray-plane intersection

Hi!

I’m having an issue with trying to use the ray-plane intersection formula for an isometric shooting game. When I click on the screen, I want the bullets to follow exactly where the mouse is. But this only works for when the player is standing still.

Video of it working when standing still:

The problem is, that when the player starts walking, the bullets start to go in different directions and it stops working when I aim at certain spots.

Video of it not working when player is walking:

There is also another problem I ran into where if I move my mouse over the player, they start glitching out.

Video below:

Idea behind the code:

I put my code for player rotation below. I’m using the ray-plane intersection formula so I can calculate the required point for the player to steer towards so that the player shoots exactly where the mouse is pointing at. I’m doing it this way because with the height of the bullet and the height of the floor are different so when the player clicks on the floor, the bullet will travel over that spot in the floor. But that means if they are looking sideways, the bullet will be higher on the screen than the mouse.

Below is the code to make the player face their mouse.
Code:

local function rayPlane(planepoint, planenormal, origin, direction)
	return -((origin-planepoint):Dot(planenormal))/(direction:Dot(planenormal))
end

local function pointGun()
    local character = player.Character
    if character then
        local root = character:FindFirstChild("HumanoidRootPart")
        if root then
            local camera = workspace.CurrentCamera
            local unitRay = camera:ScreenPointToRay(mouse.X, mouse.Y)

            local RootPos = root.Position
            local t = rayPlane(character.Torso.Position, Vector3.new(0, 1, 0), unitRay.Origin, unitRay.Direction)
            local planeIntersect = (unitRay.Direction * t) + unitRay.Origin

            root.CFrame = CFrame.new(RootPos, planeIntersect)
        end
    end
end
gunModel.Equipped:Connect(function()
    RunService:BindToRenderStep("followMouse", 1, pointGun)
end)

Below is the code for shooting the ray from the gun with the bullet animation:

local function rayPlane(planepoint, planenormal, origin, direction)
	return -((origin-planepoint):Dot(planenormal))/(direction:Dot(planenormal))
end

function Weapon:castingBullet(gunModel, character)
    local raycastParams = RaycastParams.new()
    raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
    raycastParams.FilterDescendantsInstances = {gunModel, character, self.bullet}
    raycastParams.IgnoreWater = true

    local muzzle = gunModel.muzzle.WorldPosition
    local raycastResult = workspace:Raycast(character.HumanoidRootPart.Position, character.HumanoidRootPart.CFrame.LookVector*5000, raycastParams)

    if(raycastResult)then
        print(character.HumanoidRootPart.Position)
        self.bullet.Parent = game.Workspace.AllBullets
        local intersection = raycastResult and raycastResult.Position
        local distance = (muzzle - intersection).Magnitude

        local speed = 300
        local time = (distance/speed)
        local BulletInfo = TweenInfo.new(time, Enum.EasingStyle.Linear, Enum.EasingDirection.Out, 0, false, 0)
        
        self.bullet.Position = muzzle

        local BulletShot = TweenService:Create(self.bullet, BulletInfo, {Position = raycastResult.Position})
        BulletShot:Play()
    end
end

Been stuck on this for two days now while looking around for some methods but none of them seemed to work. Any advice would be helpful. :slight_smile:

4 Likes

Updated with better video:

Looking at the code and testing the ray plane intersection method to confirms it works, the issue can probably be narrowed down to this line:

local raycastResult = workspace:Raycast(character.HumanoidRootPart.Position, character.HumanoidRootPart.CFrame.LookVector*5000, raycastParams)

because this occurs when the walking happens there might be some non visibile rotation of the humanoid that isn’t corrected by your script settings its rotation (possible due to using renderstepped). I would suggest getting the intersection of the mouse on the plane and using that to derive the direction the bullet would fire. Maybe something like this for a more reliable way to get the shooting direction:

-- get camera ray stuff like you did in the first code piece
local point = ray.Direction * rayPlane(rootPart.Position, Vector3.new(0,1,0), ray.Origin, ray.Direction) + ray.Origin
local direction = (point - direction).Unit * 500 -- can adjust the range
-- do the raycast with this direction instead

Also you should probably handle the rotation of the character in heartbeat or stepped.

1 Like

Thank you king! It worked!