Search Unity

Question Interaction System Using Raycasts

Discussion in 'Scripting' started by ThickyVEVO, Mar 29, 2023.

  1. ThickyVEVO

    ThickyVEVO

    Joined:
    May 28, 2020
    Posts:
    16
    I’m currently working on an interaction system for my project but I seem to not be getting the results I’ve expected. I assumed it might’ve been my camera system at first (I assumed the ray was not shooting out from the center of my camera) but it doesn’t seem so as far as I can tell . What I’m trying to accomplish is that when I look at an object, it tells me if it’s interactable, if it was interacted with, and when you look away from said object also lets me know, but right now it doesn’t seem to be working like that. It's not displaying the messages in console as expected, which leaves me to believe there's some issue with either the Raycast or my detection code. There is also a pretty major lag spike when pressing the interact key for the first time the game is loaded into, which leads me to believe the code is running to some degree, but definitely not properly because it freezes for whole second.

    Here's the functions that run my interaction code:
    Code (CSharp):
    1. private void InteractionCheck()
    2.     {
    3.         if(Physics.Raycast(playerCam.ViewportPointToRay(interactRayPoint), out RaycastHit hit, interactDistance))
    4.         {
    5.             if (hit.collider.gameObject.layer == 9 && (currentInteractable == null || hit.collider.gameObject.GetInstanceID() != currentInteractable.GetInstanceID()))
    6.             {
    7.                 hit.collider.TryGetComponent(out currentInteractable);
    8.  
    9.                 if (currentInteractable)
    10.                     currentInteractable.OnFocus();
    11.             }
    12.         }
    13.         else if (currentInteractable)
    14.         {
    15.             currentInteractable.OnLoseFocus();
    16.             currentInteractable = null;
    17.         }
    18.     }
    19.  
    20.     private void InteractionInput()
    21.     {
    22.         if (Input.GetKeyDown(interactKey) && currentInteractable != null && Physics.Raycast(playerCam.ViewportPointToRay(interactRayPoint), out RaycastHit hit, interactDistance, interactLayer))
    23.         {
    24.             currentInteractable.OnInteract();
    25.         }
    26.     }
    Here's the class that is referenced in the first excerpt:
    Code (CSharp):
    1. public abstract class Interactable : MonoBehaviour
    2. {
    3.     public virtual void Awake()
    4.     {
    5.         gameObject.layer = 3;
    6.     }
    7.  
    8.     public abstract void OnInteract();
    9.     public abstract void OnFocus();
    10.     public abstract void OnLoseFocus();
    11. }
    And here's the messages I'm expecting to receive in console, but am not:
    Code (CSharp):
    1. public class InteractableObject : Interactable
    2. {
    3.     public override void OnFocus()
    4.     {
    5.         print("LOOKING AT " + gameObject.name);
    6.     }
    7.  
    8.     public override void OnInteract()
    9.     {
    10.         print("INTERACTED WITH " + gameObject.name);
    11.     }
    12.  
    13.     public override void OnLoseFocus()
    14.     {
    15.         print("STOPPED LOOKING AT " + gameObject.name);
    16.     }
    17. }
    18.  
    Additional Information:
    Box on interactable layer
    upload_2023-3-28_20-25-7.png
    Controller script set up to fire raycasts
    upload_2023-3-28_20-25-55.png
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    Why are you making guesses like this? You have tools like Debug.Log so you can know for sure.

    Stop guessing, start debugging. Start printing out if and what you're hitting with your raycast, etc..
     
    Bunny83 likes this.
  3. ThickyVEVO

    ThickyVEVO

    Joined:
    May 28, 2020
    Posts:
    16
    Debug.Log'ing was the literal first thing I tried, I wouldn't have said anything here if that solved my problem or gave me a direction of where the issue is. Even if I hadn't, you didn't give any clear direction of what I should be debugging either.
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,925
    You can Debug.Log whether:
    • The code is running in the first place.
    • Print out what it's hit and if they're passing your subsequent checks.
    • And can use Debug.DrawLine/Ray to ensure the raycast is actually going where you want it to.
    Few comments on your code:
    1: Probably better to set up a layer mask in the inspector and use that in your raycast, rather than check for a hard-coded layer via code.

    2: There's no point in using TryGetComponent if you aren't going to use it properly:
    Code (CSharp):
    1. if (hit.collider.TryGetComponent(out currentInteractable))
    2. {
    3.     currentInteractable.OnFocus();
    4. }
    And 3: Break down your long if statements into smaller, more readable checks:
    Code (CSharp):
    1. private void InteractionInput()
    2. {
    3.     bool interactKeyDown = Input.GetKeyDown(interactKey);
    4.     bool canInteract = currentInteractable != null;
    5.     bool interactInView = Physics.Raycast(playerCam.ViewportPointToRay(interactRayPoint), out RaycastHit hit, interactDistance, interactLayer);
    6.    
    7.     if (interactKeyDown && canInteract && interactInView)
    8.     {
    9.         currentInteractable.OnInteract();
    10.     }
    11. }
     
  5. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    yep….draw the ray. There were times I didn’t know why my code and debugging wasn’t working….drawing the ray made me see in two seconds that I wasn’t setting the distance of the ray far enough to hit anything.
     
    StarBornMoonBeam likes this.