Entry #2: Ship Handling

The first thing I worked on is the ship handling. Having the ship move exactly as I want it to it’s something of crucial importance in this kind of game.

The ship only has a thruster on its back, so the only way to change course is to rotate on itself and start burning in another direction. As there shouldn’t be any resistance in space, burning continuously can make the velocity of the ship skyrocket quickly if not kept under control.
Since upgrading the ship is going to be a key part of the game, just having more powerful engines as upgrade is not going to cut it as a ship can potentially reach any speed if it keeps accelerating. This is why I decided to put a maximum speed that the ship can reach using its thrusters that can be increased with upgrades.

But how do you cap the velocity of something that travels in space? After a few experiments I opted for adding a virtual resistance to the ship while its engines are thrusting. At first this may sound strange but this worked better than hoped, solving a few other problems on its way.

Image1: Ship accelerating

In Image1 we can see a ship that’s accelerating from zero. The red line represents the totality of the forces applied to the ship, starting from zero only force applied is the current thrust. This is when the virtual resistance starts kicking in. When the ship is thrusting with its engines, another force that is proportional to the current speed of the ship but facing the opposite way. This opposing force is calculated so that when the ship is standing still it will receive the full thrusting power from the engines, and when it reaches the theoretical maximum speed it perfectly opposes the engines’ thrust making the acceleration null.

        Vector2 force = transform.up;
        Vector2 velocity = _rigidBody.velocity;
        force *= _thrust;
        float velocityCoeff = Mathf.Clamp(velocity.magnitude / _maxSpeed, 0 , 1);
        //Add thrust
        _forcesToApply.Add(force);
        //Add counterforce
        _forcesToApply.Add(_thrust * velocityCoeff * -velocity.normalized);

In this code excerpt we can see exactly how this is all applied.

Image2: Ship accelerating with a speed

In Image2 we can see the counterforce in action. The ship has a certain speed (shown by the green line) and we can see that the red line, representing all the forces applied to the ship, is shorter than before. This is because there is a force opposing the engines’ thrust.

Image3: Ship at maximum speed

As you can see in Image3 the ship reached its maximum speed and, even if the engines are firing, the total forces applied to the ship equal zero as the thrusting force and the counterforce cancel out.

All this make the ship accelerate faster when it’s standing still while gradually reducing acceleration as the speed increases. But this is not the only effect of this system. The more observant of you may have noticed that with the current code, if the ships rotates 180° and starts firing in the opposite direction of the velocity to slow down, the opposing force is going to be added to the thrust of the engine as it is always opposed to the velocity, not the thrust direction. This it’s actually an indirect feature of this system. When playing games that have realistic space physics is often hard to judge when to start braking to avoid overshooting the target. The players usually want to get there as fast as possible so they start braking when it is way too late, overshooting their target and ending in frustration.
With this system the opposing force helps the ship slow down making it easier to control and harder to overshoot targets.

Image4: ship braking

In Image4 we can see the resulting force of a ship burning in the opposite direction of its speed is a force so strong that the visual gizmo goes out of the camera (compare it with the one in Image1).

Someone could argue that this may make controlling the ship while turning unintuitive because the force applied to the ship does not match the direction the player is facing.

Image5: Ship turning

As seen in Image5 the actual force applied to the ship is not in the direction the engines are thrusting. This may seem unintuitive but the end result is actually a lot closer to the expected result than many would think. The resulting force is the sum of the thrust from engines and the opposing force. the opposing force reduces the component of the thrust that is parallel to the velocity while the component that is perpendicular is left untouched. This means that the component of the thrust that should make the ship change direction is not affected by the counterforce; it actually looks stronger as can be seen by looking at the resulting force. By looking closely we can see that the resulting force points to the right of the ship (relative to the ship’s facing), and if you think about it, if a player starts burning while facing right relative to the speed it means they want to steer the ship right. As with the reasoning we made about making it easy to brake, this actually makes steering the ship easier as the ship is going to be pushed in that direction even more. This makes reaching an alignment between ship’s facing and actual velocity faster.

This concludes the analysis of the ship’s movement. In the next entry we are going to talk about the gravity model.