I'm trying to create a kind of interactables system, where you can have collectible elements and interactable elements, where the collectible elements simply adds to your inventory once entered a collider, and the interactable elements need to have some feedback (user input) to be added
Here is the BaseInteractable class:
using System;
using UnityEngine;
[RequireComponent(typeof(SphereCollider))]
public abstract class BaseInteractable : MonoBehaviour, IInteractable
{
public enum Collectiblestate
{
Collected,
NotCollected
}
protected Collectiblestate _collectibleState = Collectiblestate.NotCollected;
public static event Action<IInteractable> OnInteractedItem;
private void OnTriggerEnter(Collider other) => OnItemInteracted();
// This this function comes from the interface
public virtual void OnItemInteracted() => OnInteractedItem?.Invoke(this);
}
Here is the StandardCollectible class:
using UnityEngine;
public class StandardCollectible : BaseInteractable
{
[SerializeField] private GameObject _collectibleImage = default;
public override void OnItemInteracted()
{
base.OnItemInteracted();
_collectibleState = Collectiblestate.Collected;
_collectibleImage.SetActive(false);
}
}
And here the StandardInteractable class:
using System;
using UnityEngine;
public class StandardInteractable : BaseInteractable
{
public static event Action OnInteractThresholdReached;
[SerializeField] private KeyCode _interactKey = KeyCode.L;
[SerializeField] private GameObject _collectibleImage = default;
public override void OnItemInteracted()
{
//this is a notice for the canvas, to display a UI showing the interaction key
OnInteractThresholdReached?.Invoke();
if(Input.GetKeyDown(_interactKey))
{
// Here I am trying to call the interact item action
base.OnInteractedItem?.Invoke(this);
_collectibleState = Collectiblestate.Collected;
_collectibleImage.SetActive(false);
}
}
}
The problem is with this line right here on the StandardInteractable class:
base.OnInteractedItem?.Invoke(this);
I can't seem to invoke the Action from the parent class, and I'm not really finding any helpful information about it, because I don't want to subscribe StandardInteractable to the event, I want to Invoke it when the button is pressed.
Is this actually possible?
Thanks in advance for your help guys!
CodePudding user response:
Calling a class event in a derived class is not possible like that in C#. There is a common workaround for that by raising the base class event.
Simply create a method in BaseInteractable
and invoke the event there. Then you can call this method from the derived class.
Here is the official MS explanation for that: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-raise-base-class-events-in-derived-classes
Update (added code example): BaseInteractable.cs
protected void RaiseOnInteractedItem(StandardInteractable standardInteractable)
{
OnInteractedItem?.Invoke(this);
}
StandardInteractable.cs
if(Input.GetKeyDown(_interactKey))
{
// Here I am trying to call the interact item action
RaiseOnInteractedItem(this);
_collectibleState = Collectiblestate.Collected;
_collectibleImage.SetActive(false);
}