How to split parts depending on mouse position?

image

I have this tree (which i’ll be using for testing), I want to make it so If I left click and the mouse’s position is at the tree or wood specifically, It will split into two and the top of the tree falls off and the bottom of the tree stays there. How can I achieve this?

When using the search, it doesn’t help me at all. The resources I found have bugs and doesn’t break like how it’s supposed to.

2 Likes

If it’s just for trees then you could skip a lot of the more complex maths by adding a part at the bottom of the tree trunk (invisible). Then when the player clicks on the trunk, you cast a ray from the player to the trunk, and find the position the ray intersected the part. From there you could calculate the distance of that position from the part at the bottom you added earlier.

This will give you the length of the bottom section of the trunk. After that, you’d need to calculate the length of the top part of the trunk (total trunk size - bottom section length). With these lengths you can resize the trunk to be the length of the top trunk part. Add a new trunk part with the bottom length and then you just need to position them based on the ray intersection position from before and you’ll have a trunk that’s split in two.

Make sure you weld all the parts together (except the bottom section). After that all you need to do is unanchor everything but the bottom section and the top half will appear to fall down with the lower half of the trunk still in the ground.

2 Likes

Roblox has service called BasePart | Roblox Creator Documentation
and BasePart | Roblox Creator Documentation.

I suggest you have a look at these, you should be able to negate this tree only if its union part using a script.

I leave the programming to you

2 Likes

I’d be careful with unions in this case as you might not get the physics result you want.

OP never asked for physics so i assumed he didn’t require it
EDIT: MB he did don’t do my solution if you did want working physics

Actually I don’t know how “adding a part at the bottom of the tree trunk invisible” would work and what if the player is cutting down a tree from a height below or way above, if that happens then after the players did that, they will find it odd and it would make it unrealistic. What math is it that would be complex?

What if you used Explosion | Roblox Creator Documentation? I’m not familiar with this API, though it might be close to what your looking for…

Sorry for the bad image, but imagine the red part at the bottom is the ‘invisible part’. The blue part is where the player hits it, and the green part represents the distance between the bottom part and the place the player hit. All the red part is there for is to allow you to easily calculate how long the bottom section of the tree needs to be.

My answer is assuming that you only want the player to be able to cut down this tree, if you’re wanting them to be able to cut absolutely anything in half then this won’t work.

3 Likes

There are definitely other ways to split parts instead of using explosions, and I don’t know how will that work so I’m not going to use that method.

1 Like

From what @eqis said you would be able to calculate the split parts, but that doesn’t answer the question in how you would split it.

1 Like

Explosion would most definitely allow you to split the part with proper physics, its what most games use… Unless you wanna re-invent the wheel, sure.

1 Like

I’m probably getting stuck so can I see the code example? I’m having a hard time trying to do this because the I don’t really get the explanation.

:smiley:

function SplitPart(Part, Axis)
	local Clone_1 = Part:Clone()
	local Clone_2 = Part:Clone()
	
	Clone_1.Parent = Part.Parent
	Clone_2.Parent = Part.Parent
	
	Clone_1.Size = Part.Size - (Vector3.fromAxis(Axis) * Part.Size * 0.5)
	Clone_2.Size = Clone_1.Size
	
	Clone_1.CFrame = Part.CFrame * CFrame.new(Vector3.fromAxis(Axis) * Clone_2.Size * 0.5)
	Clone_2.CFrame = Part.CFrame * CFrame.new(Vector3.fromAxis(Axis) * Clone_2.Size * -0.5)

	return Part, Clone_1, Clone_2
end

local Old_Branch, Top_Branch, Bottom_Branch = SplitPart(game.Workspace.Part, Enum.Axis.Y)
Old_Branch:Destroy()
print(Top_Branch:GetFullName(), Bottom_Branch:GetFullName())
Top_Branch.Anchored = true
Bottom_Branch.Anchored = true
2 Likes

It works except that it splits from the center instead of the mouse position.

2 Likes

I still need help, I still need to figure out how to split parts that depends on the mouse position. Not only I want it to detect if a mouse’s target is the wood but I also want to detect the position of the mouse specifically that breaks the wood and not just from the center.

2 Likes

You can make it a bit easier by restricting yourself to having all splitable parts only split along the Z axis. With that restriction, you can find out how far “along” the part a given position is like this:

function splitablePartPointToOffsetFromBase(part, point)
    local partSpaceBase = Vector3.FromNormalId(Enum.NormalId.Back) * part.Size.Z / 2 --Same as Vector3.new(0, 0, part.Size.Z/2)   
    local partSpacePoint = part.CFrame:PointToObjectSpace(point)
    return partSpacePoint.Z - partSpaceBase.Z
end

You can then create a function that splits a part some amount along its length like this:

function splitPartAtOffsetFromBase(part, offset)
    assert(offset < part.Size.Z, "Cannot split part further along its length that it is long.")

    local partSize = part.Size
    local partCFrame = part.CFrame

    local part1 = part
    part1.Size = Vector3.new(part.Size.X, part.Size.Y, offset)
    part1.CFrame = partCFrame * CFrame.new(0, 0, partSize.Z/2 - part1.Size.Z/2)

    local part2 = part:Clone()
    part2.Size = Vector3.new(part.Size.X, part.Size.Y, partSize.Z - offset)
    part2.CFrame = partCFrame * CFrame.new(0, 0, -partSize.Z/2 + part2.Size.Z/2)
    part2.Parent = part.Parent
end

Combining it all into a whole script, it could look like this:


local InputS = game:GetService("UserInputService")
local TagS = game:GetService("CollectionService")

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()

function getTargetSplitable()
	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Blacklist
	params.FilterDescendantsInstances = {player.Character}
	local result = game.Workspace:Raycast(
		mouse.UnitRay.Origin,
		mouse.UnitRay.Direction * 5000,
		params
	)
	
	if result and TagS:HasTag(result.Instance, "Splitable") then
		return result
	end
	
	return nil
end

function splitablePartPointToOffsetFromBase(part, point)
	local partSpaceBase = Vector3.FromNormalId(Enum.NormalId.Back) * part.Size.Z / 2 --Same as Vector3.new(0, 0, part.Size.Z/2)   
	local partSpacePoint = part.CFrame:PointToObjectSpace(point)
	return partSpaceBase.Z - partSpacePoint.Z
end

function splitPartAtOffsetFromBase(part, offset)
	assert(offset < part.Size.Z, "Cannot split part further along its length that it is long.")
	
	local partSize = part.Size
	local partCFrame = part.CFrame

	local part1 = part
	part1.Size = Vector3.new(partSize.X, partSize.Y, offset)
	part1.CFrame = partCFrame * CFrame.new(0, 0, partSize.Z/2 - part1.Size.Z/2)
	part1.BrickColor = BrickColor.Random()
	
	local part2 = part:Clone()
	part2.Size = Vector3.new(partSize.X, partSize.Y, partSize.Z - offset)
	part2.CFrame = partCFrame * CFrame.new(0, 0, -partSize.Z/2 + part2.Size.Z/2)
	part2.Parent = part.Parent
	part2.BrickColor = BrickColor.Random()
end

function onClicked()
	local result = getTargetSplitable()
	if result then
		local offset = splitablePartPointToOffsetFromBase(result.Instance, result.Position)
		splitPartAtOffsetFromBase(result.Instance, offset)
	end
end

InputS.InputBegan:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		onClicked()
	end
end)

Keep in mind this wouldn’t replicate the splitting to the server or any other clients, only the clicking player will see the changes.

2 Likes

I made a boolvalue named “Splitable” on the wood and it still find it as nil. (It’s also set as true and I don’t know how collectionservice works)

It needs to be tagged as Splitable. You can tag things with CollectionService, but I’d recommend getting a tag manager plugin for easy of use.

Ah ok, anyway how can I make it working if a tree is tilted or sideways or upside down because i’m applying this tree to my planet game?

It should already work with arbitrarily rotated parts?