I need to upgrade the sensor system of my cube mechanics

Im currently making a game inspired by RoBeats and geometryDash. So i have scripted this cube which can jump and rotate. however i dont think the current sensor system is good enough, as unintended behavior is created by the bad sensor system that i currently got in place.

By sensor system i refeer to the system that detects if the cube hit something etc.
I currently send out 9 rays to detect for hits. 3 to the front, 3 to the top and 3 to the bottom, as seen in the image below. As you could see in the image i do not account for the rotation of the cube when i send out the rays, which is what i would need to do if i wanted a reliable sensor system. So i would need to set the start point of the rays based on the current rotation of the cube. I havent succeeded with this and probably wont which is the reason i need help.

Feel free to suggest any other way that i can use to get a reliable sensor system.

Image

Code

For the front rays:

local First = Vector3.new(PrimaryPartPos.X + PrimaryPartSize.X/2, PrimaryPartPos.Y + PrimaryPartSize.Y/2.02, PrimaryPartPos.Z)
	local Second = Vector3.new(PrimaryPartPos.X + PrimaryPartSize.X/2, PrimaryPartPos.Y, PrimaryPartPos.Z)
	local Third = Vector3.new(PrimaryPartPos.X + PrimaryPartSize.X/2, PrimaryPartPos.Y - PrimaryPartSize.Y/2.02, PrimaryPartPos.Z)
	
	local Dir = Vector3.new(1,0,0)
	local Magnitude = 0.035

For the top rays:

local First = Vector3.new(PrimaryPartPos.X - PrimaryPartSize.X/2, PrimaryPartPos.Y + PrimaryPartSize.Y/2 - 0.2, PrimaryPartPos.Z)
	local Second = Vector3.new(PrimaryPartPos.X, PrimaryPartPos.Y + PrimaryPartSize.Y/2 - 0.2, PrimaryPartPos.Z)
	local Third = Vector3.new(PrimaryPartPos.X + PrimaryPartSize.X/2, PrimaryPartPos.Y + PrimaryPartSize.Y/2 - 0.2, PrimaryPartPos.Z)
	
	local Dir = Vector3.new(0,1,0)
	local Magnitude = 0.8

For the bottom rays:

local First = Vector3.new(PrimaryPartPos.X - PrimaryPartSize.X/2, PrimaryPartPos.Y - PrimaryPartSize.Y/2 + 0.2, PrimaryPartPos.Z)
	local Second = Vector3.new(PrimaryPartPos.X, PrimaryPartPos.Y - PrimaryPartSize.Y/2 + 0.2, PrimaryPartPos.Z)
	local Third = Vector3.new(PrimaryPartPos.X + PrimaryPartSize.X/2, PrimaryPartPos.Y - PrimaryPartSize.Y/2 + 0.2, PrimaryPartPos.Z)
	
	local Dir = Vector3.new(0,-1,0)
	local Magnitude = 0.8

First, Second and third marks the start point of the rays.

1 Like

You can get the direction vector of the up, right and front vectors of a part regardless of its rotation through the upvector, rightvector and lookvector properties of part.CFrame .

Then do your raycasts using those directions.

The cube will rotate when you jump, meaning that the look vector will change. I think i could fix this using cross product though, since i do keep track of a number between 1-4 which corresponds to the rotation of the cube.

I personally reccommend abandoning this raycast method for collision detection as using bodyvelocities and alignorientations will be far more performant to move your cube with collision detection and response plus you won’t have to worry about collisions possibly not being detected.

Yeah I misinterpreted your question originally, I think using bodymovers and constraints is best tho.

Im already using bodymovers, and i still do not understand what you suggested i would switch it out for.

But you’re using the raycasts as a quasi collision detection system?

I dont understand what you mean with quasi detection system, but yes im using raycasting to detect collisions.

Here’s how you can take in account cube’s rotation:

local PrimaryPart = workspace.Cube

local function CreateRays(cframe, normal, shift, length)
	local direction = (cframe - cframe.p) * CFrame.new(Vector3.FromNormalId(normal))
	cframe = cframe * CFrame.new(Vector3.new(), Vector3.FromNormalId(normal)) * CFrame.new(0, 0, -shift)
	return	Ray.new((cframe * CFrame.new(-shift, 0, 0)).p, direction.p * length),
			Ray.new(cframe.p, direction.p * length),
			Ray.new((cframe * CFrame.new(shift, 0, 0)).p, direction.p * length)
end

local Shift = PrimaryPart.Size.X/2
local Size = 1

local Front = {CreateRays(PrimaryPart.CFrame, Enum.NormalId.Front, Shift, Size)}
local Right = {CreateRays(PrimaryPart.CFrame, Enum.NormalId.Right, Shift, Size)}
local Back = {CreateRays(PrimaryPart.CFrame, Enum.NormalId.Back, Shift, Size)}

Visualization:
image
Blue rays are the front rays

1 Like

You could try using rotated Region3s, there was a module for that somewhere on the dev forum.

1 Like

You can use an anchored CanCollide false part (MeshParts and CSG work too) and then connect a Touched event. That will let you use GetTouchingParts to find any parts intersecting with that part.

I need Surface normals though

Hmm okay… In that case it would just take some CFrame and math to create each Ray… It’s gonna get kinda complicated.

First take the CFrame of your cube and use CFrame.UpVector, RightVector, and LookVector for Ray directions (use the size of the cube/2 for length).

Then you can create an offset CFrame (rotated) by multiplying the cube’s CFrame with CFrame.Angles which takes radians as input. This will rotate the CFrame relative to the cube’s CFrame (y axis rotates around the cube’s top point). You probably want to rotate at a 45 degree angle for two axes (use math.rad to convert to radians) so your Ray faces each corner of the cube.

Then you can use the Pythagorean distance formula to find the distance from the cube’s center to each corner of the cube for the ray: ((cube.Size.X/2)^2+(cube.Size.Y/2)^2+(cube.Size.Z/2))^(1/2)

Make sure you add maybe 0.2 studs to the length of the ray so it will actually hit stuff.

Let me know if there’s something you don’t understand and I’ll try to help you through it.

The CFrame of the cube will change when i jump(automatically rotates) Meaning lookVector wont really be forward anymore.

Do you need to know which direction the cube collided? If you do you could keep track of which direction the cube is facing by swapping vectors around. You just need to know which face is up and then you know which faces are the sides and which face is the bottom… Just check the y component of the cubes position plus the vector and see which ones are higher up compared to the others.

local function Associate(cframe, normal, State)
	local tab = {
		cframe.RightVector,
		-cframe.UpVector,
		-cframe.RightVector,
		cframe.UpVector
	}
	local Direction = Vector3.FromNormalId(normal)
	
	for i,v in pairs(tab) do
		if v:Dot(Direction) >= 0.5 then
			return v
		end
	end	
end

^^Thats how i fixed that problem