I’ll define things that the player can interact with as: an item that can be picked up, friendly NPCs, hostile NPCs, switches the player can flip, a shopkeeper, a container that has items inside it, etc.
I was originally going to use an Interactable base class, and have the various types of interactable objects inherit from this class, with only one level of inheritance, but I would like to know of other ways. I did think about using composition, by having one Interactable class and adding components as needed. Problem with that is every interactable object would have an Update() method, even if that interactable object does not need it. Plus, for interactable objects with an NPC component, you would have to do something like this in the Interactable class’ Update method:
You probably want to use an interface. With this approach, any object that should be interactable can implement it, and anything that wants to interact can look for this interface.
public interface IInteractable
{
void Interact();
}
Then a switch for instance:
public class Switch : IInteractable
{
public bool on = false;
public void Interact()
{
on = !on;
}
}
Then player:
public class Player
{
// assuming the player enters a trigger area in order to interact
private void OnTriggerEnter(Collider other)
{
IInteractable interactableObject = other.GetComponent<IInteractable>();
if (interactableObject != null)
{
interactableObject.Interact();
}
}
}
In this way, the implementing object is responsible for what happens when the player interacts with it, and the player only cares if something is interactable.
In a previous project I also had the methods “Focus” and “UnFocus” to highlight and unhighlight interactable objects the player was looking at, and then when the player hit a key with an object focused, I would call “Interact” on that object.
Using an interface actually could help a lot. Maybe you could help me with one more thing. Let’s say I want NPCs to be able to pick up an item on the ground and add that pick up to that NPC’s inventory. Basically, if I want to make interactable objects to be able to get interacted with characters other than the player, do you know what I could do?
I thought about making an “IInteractor” interface, that contains relevant info for an object that can interact with interactables. Going back to my example, the IInteractor class would have:
A method called InteractWith that has an IInteractable parameter.
A property that would return that NPC’s Inventory class.
So my example could look something like:
public class PickUp : IInteractable
{
public Item myItem; // Item on this PickUp
public void Interact(IInteractor interactor)
{
interactor.Inventory.AddItem( myItem );
}
}
public class NPC : IInteractable, IInteractor
{
private Inventory myInventory;
public Inventory GetInventory
{
get { return myInventory; }
}
void InteractWith( IInteractable interactable )
{
interactable.Interact( this );
}
}
public interface IInteractor
{
public Inventory GetInventory { get; }
void InteractWith( IInteractable interactable );
}
Edit: Forgot to include theoretical IInteractor interface.
That approach seems fine to me, that would allow you to add logic to either side of the interaction for filtering or conditional interaction.
The only thing I would point out is that with this approach you’re sort of limiting the ways an Interactable object can affect the Interactor based on what’s available in the interface (ie. Inventory). Hypothetically, you could have an Interactor that doesn’t have an inventory, or maybe one Interactor needs a lot more exposed, but in this approach you’ll need to keep adding to the interface for all Interactors.
You could potentially pass a GameObject reference instead of the Interactor interface instance, and that would allow the PickUp to perhaps use interactorGameObject.GetComponent<Inventory>() for that, for anything it needs to use for its interaction. That would be a very flexible way to go.
There are tons of ways you could go about structuring an interaction like this. I find it’s best to think about object responsibilities. Should the item add itself to the inventory? Or should the player handle the inventory?
My preference for personal projects is to go from a realistic view whether or not it’s optimal. The player sees the item, the player checks his bags to see if he has room, the player picks up the item and puts it in his bag. The item does nothing. The item just sits there and contains data relevant to the item and its effects if it has any.
I advise you choose the way that makes the most sense to you. If the scope of your game isn’t large, then your suggested approach would never become an issue, so just do whatever makes things easy to think about.