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?
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?
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?
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?
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
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)