Better method of getting collision points?

I’m currently creating a hitbox system for a vehicle game im making and wanted to implement proper impact damage that takes into consideration the rotational velocity of the object. This requires the position of the collision point between the objects in order to get the velocities on that position.

This is what i currently have for it, which uses shapecasts:

x._impactConnection = x.Part.Touched:Connect(function(other)
			local params = RaycastParams.new()
			params.FilterType = Enum.RaycastFilterType.Include
			params.FilterDescendantsInstances = {other}
			
			--shapecast
			local shapecast = workspace:Shapecast(x.Part,other.Position - x.Part.Position, params)

			if shapecast then
				--get velocities of both objects at the point and gets the difference
				local relativeVector = x.Part:GetVelocityAtPosition(shapecast.Position) - other:GetVelocityAtPosition(shapecast.Position)
				
				if relativeVector.Magnitude > 5 then
					local debounce = tick() - x.LastImpact

					if debounce > 0.5 then
						x.LastImpact = tick()
						x:TakeDamage(relativeVector.Magnitude * x.ImpactDamageMultiplier)
						
                        --debug part
						local collisionMarker = Instance.new("Part")
						collisionMarker.Position = shapecast.Position
						collisionMarker.Size = Vector3.new(1, 1, 1)
						collisionMarker.Anchored = true
						collisionMarker.CanCollide = false
						collisionMarker.BrickColor = BrickColor.new("Bright red")
						collisionMarker.Parent = workspace
					end
				end
			end
		end)

It mostly works fine, but it falls apart when it collides which a large object far away from its origin.

heres a video:

Is there a better way of finding that collision point? If the .touched event is the issue is there an alternative i can use instead?

8 Likes

So the problem is that the shapecast is trying to cast to the centre position of the baseplate (far away) which means that if the part is, for example, high up, the hit points are not accurate. Is this the problem?

3 Likes

yes that is the problem, what im looking now is how to get accuate shapecast collisions without relying on the origin of the colliding part

2 Likes

I’m thinking of two ways.
You could try do many small ray/shapecasts on the face closest to the hit part that also point in the direction of the face (or some variation of this)
Or you could split the victim part into smaller parts and then cast off of all of those.
Would that work?

1 Like

Raycasting to the result of the newly added GetClosestPointOnSurface method should do the trick.

Documentation for this function:

2 Likes

both methods would still need what im looking for. which is the direction i want the shapecast to fire at. How do i find the direction needed to always fire the cast directly into the other part?

1 Like

seems like it could help from the name, but the documentation has zero info for the function? could you explain what it exactly does?

1 Like

Oh sorry, guess I should’ve actually read the docs first. It pretty much just does what it sounds like.
There are two inputs:

  • the target part (the one you want to use the surface of, aka the object you collide with)
  • the position that the output should be closest to (the center of the vehicle?)

This should also eliminate the need for a shapecast

1 Like

Here is a simple demo on it:
GetClosestPointOnSurface Demo.rbxl (97.4 KB)

1 Like

Ok. While i dont get how this would eliminate the need for the shapecast, I ended up using this closest point to get the shapecast to shoot from the part directly to the other parts surface like this.

local closestPoint = other:GetClosestPointOnSurface(x.Part.Position)
			
			--uses it to create a direction vector pointing to that surface
			local shapecast = workspace:Shapecast(x.Part, closestPoint - x.Part.Position, params)

			if shapecast then
				local relativeVector = x.Part:GetVelocityAtPosition(shapecast.Position) - other:GetVelocityAtPosition(shapecast.Position)
				
				if relativeVector.Magnitude > 0 then
					local debounce = tick() - x.LastImpact

					if debounce > 0 then
						x.LastImpact = tick()
						x:TakeDamage(relativeVector.Magnitude * x.ImpactDamageMultiplier)
						print(relativeVector.Magnitude * x.ImpactDamageMultiplier)
						
						local collisionMarker = Instance.new("Part")
						collisionMarker.Position = shapecast.Position
						collisionMarker.Size = Vector3.new(1, 1, 1)
						collisionMarker.Anchored = true
						collisionMarker.CanCollide = false
						collisionMarker.BrickColor = BrickColor.new("Bright red")
						collisionMarker.Parent = workspace
					end
				end
			end

Here’s a poorly drawn diagram of what i meant:
Test2

Is this what you meant?

1 Like

I was wrong about the shapecast. What you drew seems to be the desired result though right? This should work accurately in most situations I believe.

2 Likes

Seems so, i played around with it a bit and it looks like the collision points are very accurate now.

Thanks for the help!

Also in case anyone needs it here’s the code:

local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Include
	
	part1.Touched:Connect(function(part2)
		params.FilterDescendantsInstances = {part2}
		
		local closestPoint = part2:GetClosestPointOnSurface(part1.Position)
		local shapecast = workspace:Shapecast(part1, (closestPoint - part1.Position).Unit, params)
		
		if shapecast then
			--Collision Point
			print(shapecast.Position)
		end
	end)
6 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.