So, I’m making a starship flight system for my space exploration game, and I’m using align orientations and linear velocitys (although ive tried multiple methods of changing velocity, same overall result)
Code below if needed:
local plr = game:GetService("Players").LocalPlayer
local camera = workspace.CurrentCamera
local mouse = plr:GetMouse()
local summonDB = false
local replicatedStorage = game:GetService("ReplicatedStorage")
local tm = require(replicatedStorage.Modules.tweenModule)
local runService = game:GetService("RunService")
local CONTROL_TABLE = {
[Vector3.new(0,0,-1)] = Enum.KeyCode.W,
[Vector3.new(0,0,1)] = Enum.KeyCode.S,
[CFrame.Angles(0,math.rad(2),0)] = Enum.KeyCode.A,
[CFrame.Angles(0,math.rad(-2),0)] = Enum.KeyCode.D,
[Vector3.new(0,1,0)] = Enum.KeyCode.Space,
[Vector3.new(0,-1,0)] = Enum.KeyCode.C,
}
local IGNORE_NAMES = {
"Center",
"Camera",
"movePart"
}
local module = {}
local function findInTable(haystack, needle)
for i, v in pairs(haystack) do
if i == needle then
return v
elseif v == needle then
return i
end
end
end
local function setCameraMode(toggle)
local mode = toggle and Enum.CameraType.Scriptable or Enum.CameraType.Custom
repeat task.wait()
camera.CameraType = mode
until camera.CameraType == mode
end
function module.summonShip(shipName)
if summonDB == true then return nil end
print("summoning ship")
summonDB = true
local potentialShip = workspace.ships:FindFirstChild(plr.Name)
if potentialShip then
potentialShip:Destroy()
end
local potentialShadowShip = replicatedStorage.Remotes.getShadowShip:InvokeServer(shipName)
local shadowShip = potentialShadowShip and potentialShadowShip or workspace.shadowShips:WaitForChild(plr.Name)
if not shadowShip then warn("no ship, terminating") return nil end
shadowShip.PrimaryPart.Attachment:Destroy()
mouse.TargetFilter = shadowShip
for _, part in pairs(shadowShip:GetDescendants()) do
if part:IsA("BasePart") or part:IsA("UnionOperation") then
if not table.find(IGNORE_NAMES, part.Name) then
part.Transparency = .5
part.Color = Color3.new(0.113725, 0.984314, 1)
part.CanCollide = false
end
end
end
mouseLoop = runService.RenderStepped:Connect(function()
shadowShip:SetPrimaryPartCFrame(CFrame.new(mouse.Hit.Position))
end)
local function onClick()
local placeCFrame = shadowShip.PrimaryPart.CFrame
mouseLoop:Disconnect()
shadowShip:Destroy()
replicatedStorage.Remotes.summonShipEvent:FireServer(placeCFrame, shipName)
summonDB = false
end
clickDetect = mouse.Button1Down:Connect(function()
onClick()
clickDetect:Disconnect()
end)
end
function module.shipController()
local functions = {}
local ship = workspace.ships:FindFirstChild(plr.Name)
if not ship then return nil end
mouse.TargetFilter = ship
local primaryPart = ship.PrimaryPart
local cameraPart = ship:FindFirstChild("Camera")
local movePart = ship:FindFirstChild("movePart")
local controlsUnlocked = false
local movementMultiplier = 20
local cframeloop
local alignLoop
local loop
local att
local linear
local align
workspace.Gravity = 0
if not movePart then
-- movepart doesnt exist:
movePart = Instance.new("Part")
movePart.Name = "movePart"
movePart.Transparency = 0
movePart.CanCollide = false
movePart.Anchored = false
movePart.Parent = ship
movePart.CFrame = primaryPart.CFrame
-- create att:
att = Instance.new("Attachment")
att.Name = 'att'
att.Parent = movePart
att.WorldCFrame = movePart.CFrame
-- linear velocity
linear = Instance.new("LinearVelocity")
linear.Name = 'linear'
linear.Parent = att
linear.Attachment0 = att
linear.MaxForce = 10000
linear.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
-- align orientation:
align = Instance.new("AlignOrientation")
align.Name = "align"
align.Parent = att
align.Mode = Enum.OrientationAlignmentMode.OneAttachment
align.Attachment0 = att
align.Responsiveness = 12
else
att = movePart:FindFirstChild("att")
linear = att:FindFirstChild("linear")
align = att:FindFirstChild("align")
end
if not att or not linear or not align or not movePart or not cameraPart then return nil end
local function setAlignPosition(toggle)
local function setPosition()
alignLoop = runService.Heartbeat:Connect(function()
align.CFrame = CFrame.new(movePart.Position, mouse.Hit.Position)
end)
end
local function unPosition()
if alignLoop then
alignLoop:Disconnect()
end
end
local func = toggle and setPosition or unPosition
func()
end
local function setCameraCFrame(toggle)
local function setCFrame()
loop = runService.Heartbeat:Connect(function()
tm.tween(camera, 1, {
CFrame = cameraPart.CFrame
})
end)
end
local function unCFrame()
if loop then
loop:Disconnect()
end
end
local func = toggle and setCFrame or unCFrame
func()
end
local function setCenterCFrame(toggle)
local function setCFrame()
cframeloop = runService.Heartbeat:Connect(function()
primaryPart.CFrame = movePart.CFrame
end)
end
local function unCFrame()
if cframeloop then
cframeloop:Disconnect()
end
end
local func = toggle and setCFrame or unCFrame
func()
end
function functions.controlFire(keycode)
if controlsUnlocked then
local moveValue = findInTable(CONTROL_TABLE, keycode)
if moveValue then
if type(moveValue) == "vector" then
moveValue = moveValue * movementMultiplier
linear.VectorVelocity += moveValue
end
end
end
end
function functions.controlHandoff(toggle)
local function board()
setCameraMode(true)
setAlignPosition(true)
setCenterCFrame(true)
tm.tween(camera, 0.5, {CFrame = cameraPart.CFrame})
setCameraCFrame(true)
-- takeoff:
linear.VectorVelocity = Vector3.new(0,20,0)
task.wait(1)
linear.VectorVelocity = Vector3.new(0,0,0)
controlsUnlocked = true
end
local function exit()
end
local functionResult = toggle == true and board() or exit()
end
return functions
end
return module
MORE SPECIFICALLY:
function module.shipController()
local functions = {}
local ship = workspace.ships:FindFirstChild(plr.Name)
if not ship then return nil end
mouse.TargetFilter = ship
local primaryPart = ship.PrimaryPart
local cameraPart = ship:FindFirstChild("Camera")
local movePart = ship:FindFirstChild("movePart")
local controlsUnlocked = false
local movementMultiplier = 20
local cframeloop
local alignLoop
local loop
local att
local linear
local align
workspace.Gravity = 0
if not movePart then
-- movepart doesnt exist:
movePart = Instance.new("Part")
movePart.Name = "movePart"
movePart.Transparency = 0
movePart.CanCollide = false
movePart.Anchored = false
movePart.Parent = ship
movePart.CFrame = primaryPart.CFrame
-- create att:
att = Instance.new("Attachment")
att.Name = 'att'
att.Parent = movePart
att.WorldCFrame = movePart.CFrame
-- linear velocity
linear = Instance.new("LinearVelocity")
linear.Name = 'linear'
linear.Parent = att
linear.Attachment0 = att
linear.MaxForce = 10000
linear.RelativeTo = Enum.ActuatorRelativeTo.Attachment0
-- align orientation:
align = Instance.new("AlignOrientation")
align.Name = "align"
align.Parent = att
align.Mode = Enum.OrientationAlignmentMode.OneAttachment
align.Attachment0 = att
align.Responsiveness = 12
else
att = movePart:FindFirstChild("att")
linear = att:FindFirstChild("linear")
align = att:FindFirstChild("align")
end
if not att or not linear or not align or not movePart or not cameraPart then return nil end
local function setAlignPosition(toggle)
local function setPosition()
alignLoop = runService.Heartbeat:Connect(function()
align.CFrame = CFrame.new(movePart.Position, mouse.Hit.Position)
end)
end
local function unPosition()
if alignLoop then
alignLoop:Disconnect()
end
end
local func = toggle and setPosition or unPosition
func()
end
local function setCameraCFrame(toggle)
local function setCFrame()
loop = runService.Heartbeat:Connect(function()
tm.tween(camera, 1, {
CFrame = cameraPart.CFrame
})
end)
end
local function unCFrame()
if loop then
loop:Disconnect()
end
end
local func = toggle and setCFrame or unCFrame
func()
end
local function setCenterCFrame(toggle)
local function setCFrame()
cframeloop = runService.Heartbeat:Connect(function()
primaryPart.CFrame = movePart.CFrame
end)
end
local function unCFrame()
if cframeloop then
cframeloop:Disconnect()
end
end
local func = toggle and setCFrame or unCFrame
func()
end
function functions.controlFire(keycode)
if controlsUnlocked then
local moveValue = findInTable(CONTROL_TABLE, keycode)
if moveValue then
if type(moveValue) == "vector" then
moveValue = moveValue * movementMultiplier
linear.VectorVelocity += moveValue
end
end
end
end
function functions.controlHandoff(toggle)
local function board()
setCameraMode(true)
setAlignPosition(true)
setCenterCFrame(true)
tm.tween(camera, 0.5, {CFrame = cameraPart.CFrame})
setCameraCFrame(true)
-- takeoff:
linear.VectorVelocity = Vector3.new(0,20,0)
task.wait(1)
linear.VectorVelocity = Vector3.new(0,0,0)
controlsUnlocked = true
end
local function exit()
end
local functionResult = toggle == true and board() or exit()
end
return functions
end
EVERY WORKS FINE until I pass 1000 STUDS where the active properties of the velocity and constraint randomly go false. I have NO Idea why. Ive tried with both server and client ownership, where server ownership. works, but due to the gravity system of my game it is impossible for me to use the server for that. And I can’t make a force to counteract the gravitational force because I use a custom gravity solution. If there is ANY way I can fix this PLEASE TELL ME because honestly I would drink 2 gallons of coffee and have extreme constipation in severe pain then create a custom physics solution.
Video:
Thanks.