Rotate hover car according to surface normal

What do you want to achieve?
I’m trying to make the part Root hover a set height above the ground and to be rotated according to the ground

What is the issue?

What solutions have you tried so far?
None as I have not found what causes this.

Script

local RunService = game:GetService("RunService")

local HoverCar = script.Parent
local HoverParts = HoverCar.HoverParts
local Root = HoverCar.PrimaryPart
local BodyPosition = Root.BodyPosition
local BodyGyro = Root.BodyGyro

local TARGET_HEIGHT = 8
local RAY_LENGTH = 32

RunService.Stepped:Connect(function()
	local totalNormals = Vector3.new()
	for _, hoverPart in pairs(HoverParts:GetChildren()) do
		local RaycastResult = workspace:Raycast(hoverPart.CFrame.Position, hoverPart.CFrame.UpVector * -RAY_LENGTH)
		if RaycastResult then
			totalNormals += RaycastResult.Normal
		end
	end
	local averageNormals = totalNormals / #HoverParts:GetChildren()
	BodyPosition.Position = averageNormals * TARGET_HEIGHT
	
	BodyGyro.CFrame = CFrame.lookAt(Root.Position, averageNormals * TARGET_HEIGHT)
end)

Hierarchy:
Desktop Screenshot 2020.11.04 - 16.05.55.98 (2)

1 Like

Looking at the video the problem seems to be with the Orientation of the hovercraft turning sideways which messes up the subsequent raycasting and causes the weird behavior.

The code related to it is this.

The issue is that the second parameter using average normal times height is…weird I don’t know what lookAt point that is relative to the world origin (0,0,0) you are trying to achieve with the second parameter.

I believe the solution is to take notes at this community resource to see how @Quasiduck rotates his horse to be normal to the ground and apply it to your hovercraft.

Specifically using CFrame.fromMatrix instead of CFrame.lookAt which uses the world position of two positions within the world.

	bg.CFrame = CFrame.fromMatrix(pos, rightVector, upVector)*CFrame.Angles(0, TurnSpeed*(a-d), 0)
4 Likes