Best approach to communicating between player and interactive objects (doors, lightswitches, switches)

I have a simple premise: that typical ‘press ‘e’ to use’ function. You use it to open doors, turn on light switches and interact with things in the world.

I wanted to know if anyone had found a solid approach to this.
Right now I have my player with a FPS camera and an object I want to interact with (pressing e starts an animation on the object). The script and code for this is attached to the object.
The setup I have has the object checking the proximity of the player (vector3.distance) and activating the animation if the user presses ‘e’ when the distance is less than x.

The object uses a public Gameobject variable to gain access to the vector3 data of the player (i drag the player gameobject into the slot on the object I interact with).

This means that for every object i want to make interactive will need to have a script and a reference to the player gameobject.

Is there a more efficient means of communication? I have read that “sendmessage” is not ideal (and im also not 100 per cent clear on the implementation)

I prefer to do the opposite. Add an script to the player that detects when the user press E. Then looks for objects in the proximity of the player and checks if the object is “interactable”, for example with a tag, a layer or just trying to get a component from the object.

Attach the same script to all the interactable objects and get that script from the player script with GetComponent< InteractionScript>(). In the script, add a public Interact() function that starts the animation or whatever.

I see the problem that every different kind of object can have a different interaction result. Then, the Interact() function will need to deal with this.

I don’t know if there is a better approach. I just don’t like the idea of objects checking if the user has pressed a key.