Moving a object on the top surface of another

Basically I am making a placement system. And I need it so that the items that are being placed are actually touching the object they are currently suppose to be on top of.

Currently I’m trying to use this to do that

part.Size.Y + model.PrimaryPart.Size.Y

but it comes out with this unwanted issue where its hovering over the plane (excuse terrible test model)

Anybody have any ideas on a way to fix this?

4 Likes

Try this, it might not work but you never know;

(Part.Size.Y/2) + (Model.PrimaryPart.Size.Y/2)

not exactly
image

Are objects placed on a n by n stud grid? If so then the Dragger service may be of interest to you.

I think that dragger only supports a 1x1 grid. My grid is 3x3

Yeah, but I believe it can be easily extended to any n by n grid where n is a counting number by limiting how often you call the MouseMove method (only call it when mouse.hit has moved in the x, y, or z directions more than your desired grid cell size). It is an option, but I’d understand if you don’t want such hacky code in your project. ^.^

On one of my projects, Free Build I have a build tool so when I get on my computer later, I will post the code for that. I use raycasts though but I don’t remember all the code.

1 Like

Can you use Model:MoveTo()? If you set a part’s position instead of CFrame, then if I remember correctly the part jumps on top of any other part that is blocking it.

The behavior of setting Position that places parts on top of other parts is called ‘Safe move’. This behavior is either already removed or will likely be in the future. That goes only for setting the properties (Position, Size) directly though, with MoveTo this behavior will be kept.

https://devforum.roblox.com/t/feedback-on-potential-removal-of-safe-move-when-setting-position-orientation-from-lua/92913

Ah, well, that complicates things. I’d definitely consider using the Dragger service now. I’m assuming that placing the model and using the Touch event isn’t desirable for its delay? If not, here is a method that seems to be robust to me:

  1. get all parts nearby which may collide with the model that is moving
  2. perform a collision test with these parts
  3. if a collision occurred, start the process over but considering a new position above the hit part

To make this efficient you may want to run a FindPartsInRegion3, only consider parts the mouse has recently targeted / current target, or roll your own spatial storage. I’m not sure what the requirements for your game are, but I’d lean towards only checking with the current mouse target, or maybe the target’s model. Perhaps you could special case it in your game too, like if the mouse is pointing at a building, check all of the walls of the building.

For the collision test you also have a couple options. I’m particularly fond of the idea of casting all the surfaces onto the xz plane to check if any of the part surfaces lie above/inside/below our model. This could either be done with a AABB check or more granular depending on how much precision you want. Once this is done, I’d cut off all of the surfaces at the edges of the AABB so we have new surfaces whose cast down onto the xz plane lies entirely inside of our object’s shadow. Again, we have varying degrees of precision. We could simply check if any points lie inside of the height range for the AABB, or we could perform surface-surface collision tests. Deciding the height to place the part in case of a collision is another problem. If you actually want to go down this route, then I’ll try to come up with a good way to do it.

Another option for the collision test is to use my 3D GJK intersection library.

Overall, I don’t like any of these options, so if someone else has a better idea, please do share. If the developers could change ‘% 1’ to ‘% n’ in the Dragger service to allow for different grid sizes, that’d be great.

Unless I read your post wrong, are you only trying to place the model on top of a specific, unrotated part? If so, could we see the line of code that sets the position, and the lines containing the definitions of the variables used?

Here’s a diagram which might help.

To place the object, you’ll likely want to add Part.Size.Y/2 + PrimaryPart.Size.Y/2 on top of the PrimaryPart.Position.Y, which might be why you’re seeing the behavior you are.

Note that if any of the parts are rotated then your code will have to be more complex to take that into account.

25 Likes

Thank you :slight_smile:

1 Like

Awesome, could you run me through the code?

	part.CFrame = part.CFrame + Vector3.new(part.Size.y/2 + benchpart.Size.y/2)

(idk what I’m doing lol)