I am currently attempting to create some planes and helicopters into my game, I have most of the controls working, but now Im stuck trying to make the vehicle move.
I tried using LinearVelocity, and the ApplyImpulse() methods, both of which as soon as the vehicle gets in the air, it proceeds to drop, or just spin out of control, I could just update the CFrame to make it go forwards, but then that would require me to do raycasts and stuff to account for physics and what not, and it loses that feel that physics based vehicles have.
So I was wondering, how can I go about make physics for flying based vehicles?
I’m not good at scripting, but from what I know, one clean way for flying vehicles is to use VectorForce or BodyForce instead of just messing with LinearVelocity or raw CFrame.
That way you can simulate lift more naturally like pushing up against gravity while also controlling forward movement without it spinning out instantly.
You can also attach an Attachment to your plane and apply forces based on the orientation you want it to move in.
Hi there.
Each frame, Roblox runs a physics simulation on all unanchored parts. This includes accelerating them downwards due to the force of gravity. If you want to make a part (or assembly of parts) float as if they are unaffected by or opposing gravity, you need to calculate the amount of force required to cancel out or overpower the acceleration of gravity.
This can be easily determined by using Newton’s second law
F = m * a
Where m is the mass of the part’s assembly and a is the acceleration due to gravity. In code, it would look something like this:
-- F = m*a
local part = script.Parent
-- In this case, gravity is our acceleration.
-- Standard workspace gravity is 196.2 along the vector (0, -1, 0)
local gravity = workspace.Gravity
-- Get mass of part so we can correctly calculate force.
local mass = part.AssemblyMass
-- Opposite direction that gravity accelerates the part.
local forceVector = Vector3.new(0, 1, 0)
game["Run Service"].PostSimulation:Connect(function(deltaTime)
-- Force value needed to fully oppose gravity for this part.
local force = mass * gravity
-- We multiply the force by the direction the force should be applied in. (0, 1, 0) in this case.
-- Remember that Run Service runs code each frame, so we need to multiply the applied force by deltaTime.
part:ApplyImpulse( forceVector * force * deltaTime)
end)
Try parenting this script to an unanchored part in your workspace. I will float as if it is anchored, but still be able to be moved by collisions/other forces. Any amount of force applied in excess of the force calculated in the script will cause the part to start moving upwards.
So, to make your vehicle go into the sky, you must apply an upward force that is in excess of the force applied by gravity. In practice, this may take the form of your vehicle having a unit ‘lift vector’ and multiplying the force generated by the vehicle by that vector.
I made a spaceship that uses LookVectors and UpVectors. If that’s what you’re looking for I can provide some code. (ignore the part with the cylinder, that was for my own time travel testing)
So I tried this out, and I notcied that bumping a part that has this applied to it, depending on its direction will usually start moving upwards, and forwards, something like that.
When trying to do this with my game, the vehicle instantly starting flipping around the place, and going upwards, downwards, etc.
Yes, that would be the expected behavior. Since the part is completely counteracting gravity (the only force acting on it) it is extremely susceptible to influence from outside forces (player walking into it, getting hit by another part, etc).
In your case it seems you are multiplying the final force vector with 5 times the length of the LookVector. That may be the reason things are flipping out. Try removing (Vehicle.Root.CFrame.LookVector * 5) from the impulse and see if you can get the vehicle to have the same behavior as the single part for a start (floating in place). Then, start experimenting with the effect applying additional forces to the vehicle has and think about how you can use that to control the vehicle’s movement.
yeah it behaves like the the part when I dont have this: (Vehicle.Root.CFrame.LookVector * 5)
That was my attempt at making it move forwards, I just tried adding them together and it got some silly results.
Physics are really not my specialty at all, so Im a little lost on what to do, I might try making ground vehicles first and then come back to this, or until I think of something lol.
No problem! Sometimes when I get stuck on a problem it helps to sleep on it and come back with fresh eyes.
You were actually really close, though. The reason things weren’t working is because you multiplied the two vectors instead of added. When you tried to add them instead, the error was likely that you didn’t multiply the complete sum by the deltaTime, only the upward force vector (think about operator precedence).
Vectors represent direction and magnitude. Instance:ApplyImpulse() takes a vector as an argument. It applies force on the x, y, and z axes accordingly.
When you multiplied the look vector with the force vector, it upset the balance the created by the initial force equation because it scaled the force vector by crazy amounts. Similarly, with when you tried adding the two vectors, since the forward vector was not being multiplied by deltaTime, its full force was being applied every frame.
Each direction of force can be thought of as independent, meaning they don’t influence each other’s calculation. That being said, you can sum up the forces acting on an object and simply add them together like so:
local part = script.Parent
-- lookVector example, as if your vehicle was oriented equally in the Y and Z directions.
local lookVector = Vector3.new(0, math.sqrt(2)/2, math.sqrt(2)/2)
-- Opposite of gravity
local upwardForceVector = Vector3.new(0, 1, 0)
-- Run every frame
game["Run Service"].PostSimulation:Connect(function(deltaTime)
-- force from gravity
local force = part.AssemblyMass * workspace.Gravity
-- adding the forces
local compositeForceVector = (upwardForceVector * force) + (lookVector * 5) -- I used 5 here as an example. But recall that F = m * a, so you can decide how fast you want the part to move forward!
part:ApplyImpulse(compositeForceVector * deltaTime)
end)
Once again, try parenting this to a part to see what it does, then applying it to your vehicle. I hope this helps.