I’m currently working on a placement system similar to Lumber Tycoon 2, and have done the necessary calculations to achieve a system that is very closely similar.
My main issue is fixing the offset, you see, I use :Ceil() on my vector 3 position values to create a base offset for snapping objects into place, only problem is that the plot system is dynamic, and doesn’t have an “established position”, and can be moved to wherever.
Example of Plot System:
What I would like to achive: I want to be able to correct this offset so I will be able to snap relative to the current object the ray is hitting.
Refrence for Placing System:
Code used to determine the position of placed object (as shown above):
local params = RaycastParams.new() params.BruteForceAllSlow = true params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = {placeableSkeleton} local results = workspace:Raycast(camera.CFrame.Position, Vector3.new(1000, 1000, 1000) * mouse.Hit.LookVector, params) if not results then return end local placeableBounds : BasePart = placeableSkeleton.PrimaryPart local instance : BasePart = results.Instance local position = Vector3.new(results.Position:Ceil().X, results.Position.Y, results.Position:Ceil().Z) local normal = results.Normal local rotation = instance:GetPivot().Rotation local offsetPositon = normal * placeableBounds.Size/2 local placeableCFrame = CFrame.new(position + offsetPositon) * rotation placeableSkeleton:PivotTo(placeableCFrame)
Could you elaborate? Is the second video not what you are trying to achieve? or do you mean that the problem is that the object cant be placed in the corner of that plot
The second video is to showcase how the placeable objects (highlighted in dark green) are snaping and rotating to the instance of the ray cast (In that case the brown piece, which is the plot).
I have made some updates to my code to better help snapping to a selected object.
local params = RaycastParams.new() params.BruteForceAllSlow = true params.FilterType = Enum.RaycastFilterType.Exclude params.FilterDescendantsInstances = {placeableSkeleton, player.Character} local results = workspace:Raycast(camera.CFrame.Position, Vector3.new(1000, 1000, 1000) * mouse.Hit.LookVector, params) if not results then return end local placeableBounds : BasePart = placeableSkeleton.PrimaryPart local instance : BasePart = results.Instance local normal = results.Normal local position = results.Position local rayCFrame = CFrame.new(position) * instance:GetPivot().Rotation local offsetFromNormal = normal * placeableBounds.Size/2 local offsetFromInstance = instance.CFrame:ToObjectSpace(rayCFrame * CFrame.new(offsetFromNormal)) local placeableCFrame = CFrame.new(offsetFromInstance.Position:Ceil().X, offsetFromInstance.Position.Y, offsetFromInstance.Position:Ceil().Z) placeableSkeleton:PivotTo(instance.CFrame:ToWorldSpace(placeableCFrame))
Here is what is looks like now:
You can see that the placeable objects snaps along the instances CFrame.
local placeableBounds : BasePart = placeableSkeleton.PrimaryPart local instance : BasePart = raycastResult.Instance local normal = raycastResult.Normal local position = raycastResult.Position local rayCFrame = CFrame.new(position) * instance:GetPivot().Rotation local offsetFromNormal = normal * placeableBounds.Size/2 local offsetFromInstance = instance.CFrame:ToObjectSpace(rayCFrame * CFrame.new(offsetFromNormal)) local y = offsetFromInstance.Position.Y local x = math.round(offsetFromInstance.Position.X) + math.fmod(placeableBounds.Size.X/2, 1) local z = math.round(offsetFromInstance.Position.Z) + math.fmod(placeableBounds.Size.Z/2, 1) local placeableCFrame = CFrame.new(x, y, z) return instance.CFrame:ToWorldSpace(placeableCFrame)