Need Help Character Alignment and Spawn Offset Issues with Custom Ride Vehicle

Hi everyone, I’m currently developing an obby game and I’ve run into two specific issues with my custom ride system. I’ve attached videos to show what’s happening.

Issue 1: Alignment Problem [AngryFace] When the “FaceMarah” respawns/moves, it doesn’t align correctly with the obby path. Instead of following the straight path of the platforms, the orientation seems off and it doesn’t face the direction it’s supposed to. How can I ensure the CFrame stays perfectly aligned with the track?

Issue 2: Spawn Offset (NYAN! CAT) When the NYAN! CAT is summoned, it spawns to the left of the player instead of behind them. I want it to consistently spawn directly behind the character’s back, but my current script seems to be offsetting it to the side.

Here is the snippet of the code I’m using: [Pindahkan kode Lua yang saya berikan sebelumnya di sini]

I’ve tried adjusting the CFrame offsets and welding, but the behavior is still inconsistent. Does anyone know how to fix the math for the orientation and the spawn position?

Any help would be greatly appreciated! Thanks!

Here is a reference video showing the result I am trying to achieve:

And here is a video of my current progress and the issues I’m facing. Please take a look


Code–

NyanCatEvent –

NyanCatEvent.OnServerEvent:Connect(function(player)
	local char = player.Character
	local hrp = char and char:FindFirstChild("HumanoidRootPart")
	local nyanSource = ReplicatedStorage:FindFirstChild("NYAN! CAT")
	local MasukPartFolder = workspace.Maps:WaitForChild("MasukPart")

	if not hrp or not nyanSource then return end

	local nyanClone = nyanSource:Clone()
	nyanClone.Name = "NYAN_CAT_ACTIVE"
	nyanClone.Parent = workspace

	local targetPos = hrp.Position + (hrp.CFrame.LookVector * -5)
	nyanClone:SetPrimaryPartCFrame(CFrame.new(targetPos, targetPos + hrp.CFrame.LookVector))

	local ownerTag = Instance.new("ObjectValue")
	ownerTag.Name = "Owner"; ownerTag.Value = player; ownerTag.Parent = nyanClone

	for _, part in pairs(nyanClone:GetDescendants()) do
		if part:IsA("BasePart") then part.CanCollide = false end
	end

	local kucing = nyanClone:FindFirstChild("Kucing")
	local spawn = kucing and kucing:FindFirstChild("SpawnNemple")
	if not spawn then nyanClone:Destroy(); return end

	local offset = hrp.CFrame.LookVector * -6
	hrp.CFrame = spawn.CFrame

	local weld = Instance.new("WeldConstraint")
	weld.Part0 = spawn; weld.Part1 = hrp; weld.Parent = hrp

	task.spawn(function()
		local rekor = player.leaderstatsRekor.Rekor
		local target = rekor.Value + 25

		for i = rekor.Value + 1, target do
			local mov = MasukPartFolder:FindFirstChild("Mov" .. i)
			if not mov then break end

			local goyang = math.sin(tick() * 10) * 0.5
			local targetCF = mov.CFrame * CFrame.new(0, goyang, 0)

			local tween = TweenService:Create(nyanClone.PrimaryPart, TweenInfo.new(0.4), {
				CFrame = targetCF
			})
			tween:Play()
			tween.Completed:Wait()
			rekor.Value = i
		end

		task.wait(0.5)
		if weld then weld:Destroy() end
		if nyanClone then nyanClone:Destroy() end
	end)
end)

AngryFaceEvnt —

RedFaceGG.OnServerEvent:Connect(function(player)
	local char = player.Character
	local hrp = char and char:FindFirstChild("HumanoidRootPart")
	local hum = char and char:FindFirstChild("Humanoid")
	local batuSource = ReplicatedStorage:FindFirstChild("BATU_MERAH")
	local MasukPartFolder = workspace.Maps:WaitForChild("MasukPart")
	local rekor = player:WaitForChild("leaderstatsRekor"):WaitForChild("Rekor")

	if not hrp or not batuSource or not hum then return end


	local startValue = rekor.Value
	local targetValue = math.max(0, startValue - 10)

	ModeTurun:FireClient(player, true) 
	ResetClientGlass:FireClient(player, targetValue) 

	local targetAwal = MasukPartFolder:FindFirstChild("Mov" .. startValue)
	local arahLurus = targetAwal and (targetAwal.Position - hrp.Position).Unit or hrp.CFrame.LookVector

	local lookAtPos = hrp.Position + Vector3.new(arahLurus.X, 0, arahLurus.Z)
	local cfLurus = CFrame.lookAt(hrp.Position, lookAtPos)


	local rotasiKoreksi = CFrame.Angles(0, math.rad(90), 0)


	local finalCF = cfLurus * CFrame.new(0, 0, -5) * rotasiKoreksi

	local batu = batuSource:Clone()
	batu.Parent = workspace
	batu:PivotTo(finalCF)
	

	local rootBatu = batu.PrimaryPart or batu:FindFirstChildWhichIsA("BasePart")


	local nempelPart = batu:FindFirstChild("Nempel", true)
	if not nempelPart then 
		return 
	end


	for _, v in pairs(batu:GetDescendants()) do
		if v:IsA("BasePart") then v.CanCollide = false; v.Anchored = false end
	end
	rootBatu.Anchored = true


	local targetAwal = MasukPartFolder:FindFirstChild("Mov" .. startValue)
	local arahLurus = targetAwal and (targetAwal.Position - hrp.Position).Unit or hrp.CFrame.LookVector
	local lookAtPos = hrp.Position + Vector3.new(arahLurus.X, 0, arahLurus.Z)
	local cfLurus = CFrame.lookAt(hrp.Position, lookAtPos)
	local rotasiKoreksi = CFrame.Angles(math.rad(90), 0, 0) 

	rootBatu.CFrame = cfLurus * rotasiKoreksi

	hrp.CFrame = nempelPart.CFrame
	hum.PlatformStand = true 

	local weld = Instance.new("WeldConstraint")
	weld.Part0 = nempelPart; weld.Part1 = hrp; weld.Parent = hrp

	task.spawn(function()
		for i = startValue, targetValue + 1, -1 do
			local mov = MasukPartFolder:FindFirstChild("Mov" .. i)
			if mov then
				local targetCF = CFrame.new(mov.Position) * cfLurus.Rotation * rotasiKoreksi
				local tween = TweenService:Create(rootBatu, TweenInfo.new(0.3, Enum.EasingStyle.Linear), {
					CFrame = targetCF
				})
				tween:Play()
				tween.Completed:Wait()
				rekor.Value = i - 1
			end
		end

		task.wait(0.5)
		if hum then hum.PlatformStand = false end
		if weld then weld:Destroy() end
		if batu then batu:Destroy() end
		ModeTurun:FireClient(player, false)
	end)
end)
2 Likes

You can try to weld the items to the humanoid root part using a Motor6D (https://create.roblox.com/docs/reference/engine/classes/Motor6D), usually this does set the parts to the humanoidrootpart in a certain direction. try moving the part0/1 position and orientation to your liking.

Note: Motor6D has issues within rotating or moving the humanoidrootpart, and animations might override the Motor6D attachment, like rotating it’s attachment. if you want a static attachment without any animations, you can use normal Welds (https://create.roblox.com/docs/reference/engine/classes/Weld), or RigidConstraits (https://create.roblox.com/docs/reference/engine/classes/RigidConstraint)

1 Like


it works, thank you very much :smiling_face_with_sunglasses:

1 Like

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