Objective: Uses same keys to control player and car with different movement.
Previous set up Unity Input System to move the Player around using its Player action map. This article describes how to set up a second action map, Car, with unique controls for driving a vehicle. Create a new action map, Car, to control movement of a vehicle. Setup this action map as shown below, noting that it uses alternative control schemes, Keyboard and Xbox Controller.
Next create a new action map called Map which will be used to enter and exit the car. This Map is separate from Player and Car so that the SwitchControls action can be used independent of Player and Car. Assign the X button from Xbox Controller and the T key on the Keyboard.
Now add the car to our scene. Start with an empty game object and name it Car, then add a box collider with is trigger checked. Note that the Size of X is larger than the width of the vehicle to allow the player to enter at the doors. Tag Car as Car.
To this Car add two cubes, frame and passenger, then create four tires, or spheres as children. The scale of frame is adjusted to X 1.6, Y 0.8 and Z 4.2. The passenger scale is X 1.6, Y 1.4 and Z 1.7 with the Y position roughly 0.31. The tires are shown below, adjusting the position of each to the four wheel wells of the vehicle.
The hierarchy should appear as below, noting the Cylinders have been added to provide a reference point when moving.
Modify the PlayerInput script previously describe to include four variables shown below. First declare an enum State for two states Walking and Driving then declare _playerState as a State variable. Use bool _nearCar to track when the Player is close enough to a door to enter the Car and _vehicle stores a triggering GameObject.
Modify void Start() to set the _playerState to State.Walking and enable _input.Map. Assign methods to _input.Car.Drive for both performed and canceled and to _input.Map.SwitchControls.performed. Other actions/methods are described in a previous article.
The SwitchControls_performed method toggles between the Walking and Driving state when T on keyboard or X on Xbox controller is pressed, but will only switch State if _nearCar is true. If the _playerState is Walking then the Player action map is disabled, otherwise Car action map is enabled and _playerState set to State.Driving. In addition, the _renderer is disabled and rotation and position of the Player set to that of the _vehicle to appear as if the player entered the vehicle. The _vehicle is then parented to the Player so which causes it to follow player input. If _nearCar is false these steps are reversed and the Player is positioned to the left of the _vehicle, on the drivers side, with its current rotation.
In order to detect if the player is _nearCar, PlayerInput has a void OnTriggerEnter() method which detects if other object triggered is tagged Car is nearby the player, in which case _nearCar is true and _vehicle is set to the triggering gameObject. OnTriggerExit() sets _nearCar to false and _vehicle to null.
The Drive_performed and Drive_canceled modify _driveInput, a global Vector2 variable, but only called when the _input.Car is enabled.
The _driveInput variable is used in the Movement() method to modify rotation and position, depending on the input source. If the _input.Player is enabled then _driveInput will be (0, 0) and the upper portion of the if statement is used; otherwise, _input.Car is enabled and the lower else statement is used. Notice that the Player action map can Move in any direction based on _moveInput, and has independent rotation control, _rotateInput. The Car action map rotation is controlled by Drive action using the _driveInput.x axis and translation by _driveInput.y but on the direction’s z axis.
The Car was built along the z-axis, so to drive the car the forward movement must be along the same axis. Action maps allow the same keys to be bound to provide control from a different perspective with different implementation.