Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

How do I position a part in between 2 points?

Asked by 9 years ago

I was experimenting with some stuff and this is my code. It just sees for a hit and then gets p1 and p2, 2 points..

and then I want to just make a part in btw those points and stretch it, (much like a measurement tool)

So, Here's my script: I am not able to get it to work :/ the only problem is the position and IDK how to position it perfectly.

tool = script.Parent
handle = tool.Handle
p = game.Players.LocalPlayer
m = p:GetMouse()

tool.Equipped:connect(function()
    local p1
    local p2
    tool.Activated:connect(function()
        if not p1 then
            p1 = m.Hit.p
        else 
            p2 = m.Hit.p
        end

        if p1 and p2 then
            local part = Instance.new("Part", game.Workspace)
            local dist = (p1-p2).magnitude
            print("Distance :"..dist)
            part.CFrame = CFrame.new(p1.X, p2.Z)
            part.Size = Vector3.new(dist,1,1)
        end
    end)
end)


0
Distance :22.704313278198 13:11:57.696 - Players.Player1.Backpack.Tool.LocalScript:20: bad argument #1 to 'new' (Vector3 expected, got number) 13:11:57.697 - Script 'Players.Player1.Backpack.Tool.LocalScript', Line 20 13:11:57.697 - Stack End buoyantair 123 — 9y

2 answers

Log in to vote
0
Answered by
Redbullusa 1580 Moderation Voter
8 years ago

Not to change your scripting habits, but I find it a lot more professional to capitalize more often and be more specific with your variables. This will greatly improve your reputation and give that "Wow, that scripter is really organized!" factor.

Tool = script.Parent
Handle = Tool:WaitForChild("Handle")
Player = game.Players.LocalPlayer
-- You don't need the mouse. The ".Equipped" event comes with the Mouse argument.

Tool.Equipped:connect(function (Mouse)
    local Point1
    local Point2
    Tool.Activated:connect(function ()
        if not Point1 then
            Point1 = Mouse.Hit.p
        else
            Point2 = Mouse.Hit.p
        end
        if Point1 and Point2 then
            local Visual = Instance.new("Part", workspace)
            local Distance = (p1 - p2).magnitude
            print("Distance: " .. Distance)
            Visual.Anchored = true
            Visual.CanCollide = true
            Visual.FormFactor = Enum.FormFactor.Custom
            -- More precise formfactor!
            Visual.Size = Vector3.new(1, 1, Distance)
            -- I found out that the Z axis works better in this demonstration
            Point1 = nil
            Point2 = nil
            -- This is to reset both of points
            game:GetService("Debris"):AddItem(Visual, 5)
            -- Ya gotta destroy it
        end
    end)
end)

You know what's the awesome thing about CFrame? You could have your part point to a particular direction if both of the points are Vector3 properties.

You'll need the first point (starting point).

Visual.CFrame = CFrame.new(Point1)

You'll need the second point (the direction it is pointing to).

Visual.CFrame = CFrame.new(Point1, Point2)

The problem with this is that the central position of Visual will always be on Point1. That's not what you want. What you want is a visual measuring tape.

You can do this by calculating the mean (the average) of both Point1 and Point2 components (X, Y, & Z). Because you need to position Visual in between Point1 and Point2.

function Mean(a, b)
    local solution = (a + b) / 2
    return solution
end

-- ...

Visual.CFrame = (
    Vector3.new(
        Mean(Point1.X, Point2.X),
        Mean(Point1.Y, Point2.Y),
        Mean(Point1.Z, Point2.Z)
    ), Point2)

Your final script should be this:

Tool = script.Parent
Handle = Tool:WaitForChild("Handle")
Player = game.Players.LocalPlayer

function Mean(a, b)
    local solution = (a + b) / 2
    return solution
end

Tool.Equipped:connect(function (Mouse)
    local Point1
    local Point2
    Tool.Activated:connect(function ()
        if not Point1 then
            Point1 = Mouse.Hit.p
        else
            Point2 = Mouse.Hit.p
        end
        if Point1 and Point2 then
            local Visual = Instance.new("Part", workspace)
            local Distance = (p1 - p2).magnitude
            print("Distance: " .. Distance)
            Visual.Anchored = true
            Visual.CanCollide = true

            Visual.CFrame = CFrame.new(Vector3.new(Mean(Point1.X, Point2.X), Mean(Point1.Y, Point2.Y), Mean(Point1.Z, Point2.Z)), Point2)

            Visual.FormFactor = Enum.FormFactor.Custom
            Visual.Size = Vector3.new(1, 1, Distance)
            Point1 = nil
            Point2 = nil
            game:GetService("Debris"):AddItem(Visual, 5)
        end
    end)
end)
0
I have come from a world of Javascript programming where we use the 'Camel' syntax, You put the variable's first letter small example - a simple variable like this var lastName = 'string' anyways, thanks so much! buoyantair 123 — 8y
Ad
Log in to vote
1
Answered by
davness 376 Moderation Voter
9 years ago

It's simple. CFrame property calls CFrame.new and Vector3.new over it:

tool = script.Parent
handle = tool.Handle
p = game.Players.LocalPlayer
m = p:GetMouse()

tool.Equipped:connect(function()
    local p1
    local p2
    tool.Activated:connect(function()
        if not p1 then
            p1 = m.Hit.p
        else 
            p2 = m.Hit.p
        end

        if p1 and p2 then
            local part = Instance.new("Part", game.Workspace)
            local dist = (p1-p2).magnitude
            print("Distance :"..dist)
            part.CFrame = CFrame.new(Vector3.new(p1.X, p2.Z)) -- You forgot to call Vector3.new over CFrame.
            part.Size = Vector3.new(dist,1,1)
        end
    end)
end)

But it does not work because once generated, the part will fall, so do not forget to anchor it.

tool = script.Parent
handle = tool.Handle
p = game.Players.LocalPlayer
m = p:GetMouse()

tool.Equipped:connect(function()
    local p1
    local p2
    tool.Activated:connect(function()
        if not p1 then
            p1 = m.Hit.p
        else 
            p2 = m.Hit.p
        end

        if p1 and p2 then
            local part = Instance.new("Part", game.Workspace)
            part.Anchored = true -- Anchor the part
            local dist = (p1-p2).magnitude
            print("Distance :"..dist)
            part.CFrame = CFrame.new(Vector3.new(p1.X, p2.Z))
            part.Size = Vector3.new(dist,1,1)
        end
    end)
end)

But there's another problem. With the clicks, the tool starts getting bugged. To prevent it, immediately after the part generation, we will "clear" p1 and p2 so they can be assigned with new values. Who's better than nil value?

tool = script.Parent
handle = tool.Handle
p = game.Players.LocalPlayer
m = p:GetMouse()

tool.Equipped:connect(function()
    local p1
    local p2
    tool.Activated:connect(function()
        if not p1 then
            p1 = m.Hit.p
        else 
            p2 = m.Hit.p
        end

        if p1 and p2 then
            local part = Instance.new("Part", game.Workspace)
            part.Anchored = true
            local dist = (p1-p2).magnitude
            print("Distance :"..dist)
            part.CFrame = CFrame.new(Vector3.new(p1.X, p2.Z))
            part.Size = Vector3.new(dist,1,1)
            p1 = nil
            p2 = nil
        end
    end)
end)

And a thing. When you are trying to set Z, you are setting Y value instead. To correct this, you must to set a value to Y. I recommend to use p1 or p2

tool = script.Parent
handle = tool.Handle
p = game.Players.LocalPlayer
m = p:GetMouse()

tool.Equipped:connect(function()
    local p1
    local p2
    tool.Activated:connect(function()
        if not p1 then
            p1 = m.Hit.p
        else 
            p2 = m.Hit.p
        end

        if p1 and p2 then
            local part = Instance.new("Part", game.Workspace)
            part.Anchored = true
            local dist = (p1-p2).magnitude
            print("Distance :"..dist)
            part.CFrame = CFrame.new(Vector3.new(p1.X, p1.Y, p2.Z))
            part.Size = Vector3.new(dist,1,1)
            p1 = nil
            p2 = nil
        end
    end)
end)

If you want to make the part disappear of the game after a while, I think you can do it by yourself :p. But, because I'm friend:

tool = script.Parent
handle = tool.Handle
p = game.Players.LocalPlayer
m = p:GetMouse()

tool.Equipped:connect(function()
    local p1
    local p2
    tool.Activated:connect(function()
        if not p1 then
            p1 = m.Hit.p
        else 
            p2 = m.Hit.p
        end

        if p1 and p2 then
            local part = Instance.new("Part", game.Workspace)
            part.Anchored = true
            local dist = (p1-p2).magnitude
            print("Distance :"..dist)
            part.CFrame = CFrame.new(Vector3.new(p1.X, p1.Y, p2.Z))
            part.Size = Vector3.new(dist,1,1)
            p1 = nil
            p2 = nil
            wait(3) -- how much seconds do you want?
            part.Parent = nil
        end
    end)
end)

Answer this question