Check for inherited class in overlaped Collider2D and execute functions (I think?)
Working on making a character controller for a 2d side scroller, and I want to keep as many functionalities things as possible in it. Disclaimer - I am not very good at coding and mainly rely on brute force to make things work.
Currently trying to get the ability to interact working, but I'm getting stuck.
What I want to do: I made a class which all interactables inherits from. The player should be able to walk up to the interactable. From the array that I get from the OverlapCircleAll I wish to then grab the currentInteractable and perform the appropriate function.
Problem is: It ain't doing it... Seems that it isn't finding the currentInteractable, or it isn't able to execute the function. Anyone who's better at code that can help me out?
//Interactable Script, in a separate script and inherits all functions from another class as you can see
public class CubeInteractable : Interactable
{
public override void OnRange()
{
Debug.Log("Can Interact");
}
public override void OnInteract()
{
Debug.Log("Interacted");
}
public override void OnLoseRange()
{
Debug.Log("No Interact");
}
}
Character Controller in a separate script
[Header("Interaction")]
public bool canInteract = true;
[SerializeField] private float interactionRadius = 2;
[SerializeField] public LayerMask whatIsInteractable = default; //=7
private Interactable currentInteractable;
private void Update()
{
if (canInteract)
HandleInteraction();
{
private void HandleInteraction()
{
Collider2D[] hitInteractable = Physics2D.OverlapCircleAll(transform.position, interactionRadius, whatIsInteractable);
foreach (Collider2D interactable in hitInteractable)
{
interactable.gameObject.TryGetComponent(out currentInteractable);
if (currentInteractable)
{
currentInteractable.OnRange();
}
else
{
currentInteractable.OnLoseRange();
currentInteractable = null;
}
}
if (Input.GetKeyDown(KeyCode.E))
{
foreach(Collider2D interactable in hitInteractable)
{
if (currentInteractable != null)
currentInteractable.OnInteract();
else
return;
}
}
}
Answer by inget-namn · Mar 27 at 11:39 PM
First of all, I don't think I made any actual changes... But after a reboot of the computer the script worked.
Realized some other problems however - the OnRange(); would get called every update, and the OnLoseRange(); would not get called at all. Not what I intended. Took a walk with the dog and got back with a refreshed mind and figuered out the solution. If anyone is looking for a solution for 2D interaction, then maybe this will help! Didn't change the Interactable script, and below you can see the other changes made. Note, this is not the entire script.
[Header("Interaction Parameters")]
[SerializeField] private float interactionRadius = 2;
[SerializeField] public LayerMask whatIsInteractable = default;
private Interactable currentInteractable;
private bool couldInteract = false;
private bool isInteractable = false;
public bool canInteract =true;
private void Update()
{
if (canInteract)
HandleInteraction();
}
//interaction radius visualized
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, interactionRadius);
}
private void HandleInteraction()
{
Collider2D[] hitInteractable = Physics2D.OverlapCircleAll(transform.position, interactionRadius, whatIsInteractable);
isInteractable = Physics2D.OverlapCircle(transform.position, interactionRadius, whatIsInteractable);
foreach (Collider2D interactable in hitInteractable)
{
if(currentInteractable == null)
couldInteract = true;
if (isInteractable == true)
{
interactable.gameObject.TryGetComponent(out currentInteractable);
if (currentInteractable && couldInteract == true)
{
currentInteractable.OnRange();
couldInteract = false;
}
}
if (Input.GetKeyDown(KeyCode.E) && currentInteractable != null)
{
currentInteractable.OnInteract();
}
}
if (currentInteractable && isInteractable == false)
{
currentInteractable.OnLoseRange();
currentInteractable = null;
}
}