Basically you need two playable characters that have an on/off switch for processing inputs. This could be by disabling the components, or some coded boolean, etc.
Then all you have to do is turn one on, and turn the other one off, making sure to update which player your camera is following if necessary.
This can be done a thousand different ways, some more extensible and maintainable than others.
A strong design to do this is having the user represented by a Controller class, which then can Possess and Unpossess one or many characters in the game. You can imagine the scenario of a character running around, then getting into a car. The PlayerController remains the same, but the player is unpossessed, and the car is possessed. Then the car begins updating and receiving inputs until you press the button to get out, which is when the player becomes possessed again, and the car becomes unpossessed.
Using that design, you can have things like the MainCamera automatically follow the PlayerController’s currently possessed character, and other convenient functions.
Here’s an example of one way to implement something like that using a simple Interface:
// defines a contract that objects can agree to
// objects with this interface are guaranteed to contain the defined functions
public interface IPossessable
{
void Possess();
void UnPossess();
}
using UnityEngine;
// controller that handles possessing and unpossessing
// operates only on objects that implement the IPossessable interface
public class Controller : MonoBehaviour
{
public IPossessable controlledObject;
public void Possess(IPossessable obj)
{
if(obj != null)
{
// unpossess the current object
if(controlledObject != null)
{
controlledObject.UnPossess();
}
// possess the new object
controlledObject = obj;
controlledObject.Possess();
}
}
public void UnPossess()
{
// unpossess the current object
if(controlledObject != null)
{
controlledObject.UnPossess();
}
}
}
using UnityEngine;
// example of a character that implements the interface
public class Character : MonoBehaviour, IPossessable
{
public float speed = 10;
// required by the interface
void IPossessable.Possess()
{
enabled = true; // turning on the component makes Update start ticking
}
// required by the interface
void IPossessable.UnPossess()
{
enabled = false; // turning off the component makes Update stop ticking
}
// just some example behavior
private void Update()
{
// follows pointer while the component is enabled
transform.position = Vector3.MoveTowards(transform.position, Camera.main.ScreenToWorldPoint(Input.mousePosition), speed * Time.deltaTime);
}
}