# 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)
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).

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