How do I stop my ship from going above land?

Hello! I’m working on a game where there’s landing craft that are meant to land on beaches.

Problem is, these beaches are made with a slope, so the landing craft go straight up.

Here’s the ship’s code:

local Bridge = script.Parent
local Settings = script:WaitForChild("Settings")
local CaptainSeat, Seat = Bridge:WaitForChild("CaptainSeat"), Bridge:WaitForChild("CaptainSeat")
local runservice = game:GetService("RunService")
local HDG = Bridge:WaitForChild("HeadingScreen")
local HEALTH = Bridge:WaitForChild("HealthScreen")
local SPD = Bridge:WaitForChild("ThrottleScreen")

local y = CaptainSeat.Position.Y

local alive = true

local Angler = Seat.Angler
Angler.CFrame = CaptainSeat.CFrame

local Mover = Instance.new("AlignPosition")
Mover.Parent = Seat
Mover.Mode = Enum.PositionAlignmentMode.OneAttachment
Mover.MaxForce = math.huge
Mover.Attachment0 = Seat.Attachment

local cthrottle = 0
local cturn = 0
local guh = Bridge.Health.Value
local health = Bridge.Health

local TurnSpeed = Settings.TurnSpeed.Value
local FullSpeed = Settings.FullSpeed.Value
local ReverseSpeed = Settings.ReverseSpeed.Value
local Acceleration = Settings.Acceleration.Value
Mover.MaxVelocity = FullSpeed
Mover.Responsiveness = 60

Angler.MaxAngularVelocity = TurnSpeed

function randomfire()
	local ship = Bridge.Parent
	local parts = {}
	for i,v in ipairs(ship:GetDescendants()) do
		if v:IsA("BasePart") then
			table.insert(parts, v)
		end
	end
	
	local part = parts[math.random(#parts)]
	if part ~= nil then
		local fire = game:GetService("ReplicatedStorage"):WaitForChild("Effects"):WaitForChild("Fire"):Clone()
		fire.Parent = part
		fire.Emitter.Enabled = true
	end
end

health.Changed:Connect(function()
	if health.Value < guh/4 then
		randomfire()
	end
end)

runservice.Heartbeat:Connect(function(deltaTime)
	if alive == true then
		if health.Value <= 0 then
			Angler:Destroy()
			Mover:Destroy()
		--[[	for i,v in ipairs(Bridge.Parent:GetDescendants()) do
				if v:IsA("BasePart") then
					v.Anchored = true
				end
			end]]
			CaptainSeat.Anchored = true
			local tween = game:GetService("TweenService"):Create(CaptainSeat, TweenInfo.new(40, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {CFrame = CFrame.new(Vector3.new(CaptainSeat.Position.X, -100, CaptainSeat.Position.Z)) * CFrame.Angles(math.random(), math.random(), math.random())}):Play()
			local effect = game:GetService("ReplicatedStorage"):WaitForChild("Effects"):WaitForChild("ShipDeathExplosion"):Clone()
			effect.CanCollide = false
			effect.CanQuery = false
			effect.CanTouch = false
			effect.Anchored = false
			effect.Parent = workspace
			effect.Position = CaptainSeat.Position + Vector3.new(0,Settings.ExplosionSize.Value / 4,0)
			effect.Size = Vector3.new(0.01,0.01,0.01)
			local weld = Instance.new("WeldConstraint")
			weld.Parent = effect
			weld.Part0 = CaptainSeat
			weld.Part1 = effect
			local tween2 = game:GetService("TweenService"):Create(effect, TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Size = Vector3.new(Settings.ExplosionSize.Value,Settings.ExplosionSize.Value,Settings.ExplosionSize.Value)}):Play()
			spawn(function()
				wait(1)
				local tween2 = game:GetService("TweenService"):Create(effect, TweenInfo.new(3, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut), {Transparency = 1}):Play()
			end)
			game:GetService("Debris"):AddItem(Bridge.Parent, 20)
			game:GetService("Debris"):AddItem(effect, 5)
			Bridge.Team.Value:FindFirstChild(Bridge.Parent.Name).Value = false
			workspace:WaitForChild("ShipDeath"):Play() workspace:WaitForChild("ShipDeath2"):Play()
			script:Destroy()
		end
		if cthrottle > FullSpeed / 10 then
			CaptainSeat.Wake.ParticleEmitter.Enabled = true
		else
			CaptainSeat.Wake.ParticleEmitter.Enabled = false
		end
		local throttlefloat = Seat.ThrottleFloat
		local steerfloat = -Seat.SteerFloat
		if throttlefloat == 1 then
			cthrottle = cthrottle + Acceleration
		elseif throttlefloat == -1 then
			cthrottle = cthrottle - Acceleration
		end
		cturn = steerfloat * TurnSpeed
		cthrottle = math.clamp(cthrottle, -ReverseSpeed, FullSpeed)
		Angler.CFrame = Angler.CFrame * CFrame.fromEulerAnglesXYZ(0, math.rad(cturn * cthrottle / FullSpeed),0)
		--Mover.Velocity = Vector3.new(CaptainSeat.CFrame.LookVector.X * cthrottle, 0, CaptainSeat.CFrame.LookVector.Z * cthrottle)
		--CaptainSeat.AssemblyLinearVelocity = CaptainSeat.CFrame.LookVector * cthrottle
		--Mover.Position = Vector3.new(CaptainSeat.Attachment.WorldPosition.X, 0, CaptainSeat.Attachment.WorldPosition.Z) + Vector3.new(CaptainSeat.CFrame.LookVector.X, 0, CaptainSeat.CFrame.LookVector.Z) --+ Vector3.new(0,y,0)
		Mover.Position = Vector3.new(CaptainSeat.Attachment.WorldPosition.X,0,CaptainSeat.Attachment.WorldPosition.Z) + CaptainSeat.CFrame.LookVector * cthrottle
		
		-- screens

		HEALTH.SurfaceGui.TextLabel.Text= ("HEALTH:" .. health.Value)
		SPD.SurfaceGui.TextLabel.Text = ("TSPD:" .. math.floor(cthrottle))
		HDG.SurfaceGui.TextLabel.Text = ("HDG:" .. math.floor(Seat.Orientation.Y))
	end
end)

Bridge.HornButton.ProximityPrompt.Triggered:Connect(function()
	CaptainSeat.Horn:Play()
end)

And a video of the problem:

2 Likes

No.

[character limit]dsasdffsdfsd

1 Like

Use PlaneConstraint on top of AlignPosition and AlignOrientation. Untested, so idk if it will work as desired.

1 Like

I’m still a bit confused on how I would set this up, especially considering there really isn’t any properties, nor’ any information in terms of tutorials. Care to explain?

1 Like

PlaneConstraint will attempt to keep unanchored part on the same 2D plane as the other (preferably anchored) part. All you need to have is 2 attachments, both set to 0,90,0 I believe to get the desired horizontal plane. Edit: 0,0,90 on the anchored part orientation Orientation on the Attachment1 is irrelevant.

I am unsure whether it will play nicely with the AlignPosition constraint, but I thought it is worth a try. Set it up, just like you set the Mover, but you may need to use separate attachments (because the modified orientation).

image
EDIT:
Here is more info with a nice video (scroll down to PlaneConstraint)