How can you check what side of a part a player is touching

Can someone tell me the best way to detect the side of a part a player is touching? I’ve been trying to find a solution for a couple hours now.

4 Likes

@Hikoutai OP does not want that. He wants to know what side they are touching. E.g. top, back, left.

An easy solution is just to have a very thin part on each side of the part that needs to be touched, and listen for the Touched event for each part.

This may be of some use:

Basically:

function getSurface(position, object)
	local surfaces = {
		back = object.CFrame * CFrame.new(0, 0, object.Size.Z);
		front = object.CFrame * CFrame.new(0, 0, -object.Size.Z);
		top = object.CFrame * CFrame.new(0, object.Size.Y, 0);
		bottom = object.CFrame * CFrame.new(0, -object.Size.Y, 0);
		right = object.CFrame * CFrame.new(object.Size.X, 0, 0);
		left = object.CFrame * CFrame.new(-object.Size.X, 0, 0);
	}
	local surface = "back"
	for side, cframe in pairs (surfaces) do
		surface = ((position - cframe.p).magnitude > (position - surfaces[surface].p).magnitude and surface or side)
	end
	return surface
end
12 Likes

Thanks let me test that in studio to see if it works

If you use the getSurface code above to try and find the normal of a collision between two parts using one part’s position, it unfortunately wont always work. The best example is when the part who’s position you are using is very long, perpendicular to the touching surface normal, and the very end is just touching the other part. In this case getSurface will report that the touch was on one of the other sides.

I had the same question here Deformable Parts and Collisions (under Collision Location). The best solution I’ve come up with but haven’t implemented would be to start with my GJK distance code found here and edit it to find the minimum contact manifold as described here:
http://www.dyn4j.org/2011/11/contact-points-using-clipping/

1 Like

I highly doubt this will be an issue with the player’s character.

While the example I used was extreme, it doesn’t need to be so. First, some definitions.

Let part A be the humanoid part or more generally the part whose position we are going to use in the module above.

Let part B be the other part involved in the collision and the part on which we want to find what surface part A is touching.

In the method for determining which surface normal is closest could be improved (and I’ll show how below) but as is it determines the center of each surface of the part and finds the closest surface center point to part A’s position (part A’s center point). This fails very often close to edges. Consider for example a 0.2 studs thick by 4 studs wide by 5 studs high door as part B. If the player were to touch the largest surface of the door while the part A’s center position projected onto the surface is more than 1.2 studs to the left or right from the center or more than 1.45 studs up or down from the center then this method will report that the edge of the door was touched. That is nearly half of the area of the door. If the player were to approach the door from the side, this method would almost always fail.

A better way would be to convert part A’s center to part B’s local space scaled by the part’s size. The largest axis would determine front/back, top/bottom, or left/right and the sign would determine which of those surfaces. This would fail though if the line from the center of part A to the center of part B crossed the wrong surface. This could happen as shown below:
Error

Analyzing this error case, as long as the angle formed by Part B’s center to part A’s center and partB’s center to the point of contact is smaller then the angle between part B’s center to the surface edge/corner point and part B’s center to the point of contact, the surface reported by this method is correct. In order for this to happen, the similarity formed by the triangles using the same points must be broken with the distance orthogonal to the surface normal becoming greater. In other words, the further part A is from part B, the smaller part A is, and the less depth part B has when looking at the surface, the better. However as soon as half of part A’s diagonal size (imagine the radius of a bounding sphere) divided by the distance to the center of part B becomes larger then the ratio of half the largest orthogonal length of part B to the surface normal divided by the distance from the center to the center of the surface, then the test will fail.

This means that for a 0.2x4x5 door as part B and a 2x1x1 part as part A it won’t fail unless sqrt(6 / sqrt(4.36)) is larger then sqrt(2 / 0.01). In reality, part A would have to be infinitely thin and 20 studs long to cause a problem. However, if we were going to try and find out of the point of contact was on the 0.2x5 edge of the door, it would almost always fail. The bottom line is that while this method is better then the one in the module above it still fails often.

In order to find the contact manifolds in GJK, the closest manifold to the origin in the Minkowski sum is found. The original manifolds of each convex polyhedra forming the Minkowski sum manifold are what we are looking for. This manifold may be a point, edge, or plane. The GJK code is almost there (it finds the minimum manifold) but it doesn’t keep track of the points that formed it. Keep track of the points that formed it, and you get either your closest planes/edges/points or planes/edges/points of contact.

8 Likes