Collision detection based on the velocity direction of an object

I’m trying to implement some momentum-based interactions between a player and some moving parts. My aim is to create something that is a little comical and over the top as seen by the clip below:

Obviously, this is not realistic. The player would be pushed at a similar rate to the cube but I don’t want that. This is an extremely large object that would likely never appear in the actual game, and interactions with smaller objects have been fairly realistic.

My problem with this system is that this effect is applied via touched event. Of course, touched has its caveats but they haven’t been troublesome. Except for what you’re about to see below:

My code seems to fall apart when an object is touched from the side. Again, this would likely not be a large problem in the real game since most objects colliding with you are bits of debris traveling quickly but I’d still like to patch out any of these outrageous interactions.

My code is simple and probably not mathematically accurate:

-- Some constants
local charMassConst = 9.1
local momentumThreshold = 100
local damageMultiplierConst = 0.5

-- wrap this inside a `touched` event and use this function to determine the players velocity
function calculateMomentum(otherpart)
	return ((otherpart.Velocity * otherpart.Size)/ charMassConst)
end

char["Left Arm"].Touched:Connect(function(otherPart)
	local momentum = calculateMomentum(otherPart)
	if momentum.Magnitude > momentumThreshold and otherPart.Parent ~= char then
		impulse(char, otherPart)
		damagePlayer(char["Left Arm"], char, momentum.Magnitude)
		
	end
end)

...

My guess is that I have to find the angle between a player’s position vector and the otherparts’ position vector + otherparts velocity but I’m not even sure if it would work.

How would I go about making it only detect a collision when the player is in the same direction as the traveling part?

This is going to be some stuff with math, so close to what you were saying. Here’s two methods I’ll give since I didn’t fully understand your question. If you want to detect if the player and part are moving in the same or opposite direction than

        local PartsDirection = (part.CFrame.LookVector).unit

        -- Check if the player is moving in the same direction as the part
        local dp = Character.Humanoid.MoveDirection.Unit:Dot(PartsDirection )
        if dp > 0.7 then -- Positive if they are moving the same way, negative if not 
           
            print("Player is moving in the same direction as the part!")
        end

Or if you just want to know if the part is facing the player and is hitting the player from the front

if Part.CFrame:toObjectSpace(Character.PrimaryPart.CFrame).Z < 0 then
print("Infront of me")
end
-- or
if Character.PrimaryPart.CFrame:toObjectSpace(Part.CFrame).Z < 0 then
		print("Infront")
end

either way works.

The latter option is great and partially works. It detects the object is in front just fine, but the object may not always be traveling towards its front. Is there a way I could change it so that front is the velocity?

I tried this but it doesn’t work (obviously):

	local charOtherSpace = otherpart.CFrame:toObjectSpace(char.PrimaryPart.CFrame).Position
	if  charOtherSpace.X > otherpart.Velocity.Unit.X and charOtherSpace.Y > otherpart.Velocity.Unit.Y and charOtherSpace.Z > otherpart.Velocity.Unit.Z then
		print("Infront of me")
	end

My character should be in front of the objects moving direction to get hit

@StraightScared I figured it out.

You can use your solution paired with the use of the vector dot product between the velocity of an object and the player’s position. If the resulting dot product is positive, the player is in the same direction as the velocity. If it’s 0, the player is perpendicular to the velocity and if it’s < 0 then the player is not in the direction of the velocity. I got this resulting code:

function calculateMomentum(otherpart)
		local charOtherSpace = otherpart.CFrame:toObjectSpace(char.PrimaryPart.CFrame).Position
		if  otherpart.Velocity:Dot(charOtherSpace) > 0 then
			return ((otherpart.Velocity * otherpart.Size) / charMassConst * elasticDampening)
		end
		return Vector3.zero
end

I think you can also specify an angle of tolerance through this formula:
a . b = |a| |b| cos θ .

but I haven’t tested this yet since my solution worked.

Thank you!

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