Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Bug My Raycast stops detecting stuff even though it shouldn't

Discussion in '2D' started by unity_iOvQOrnbL4RR4Q, Jul 6, 2023.

  1. unity_iOvQOrnbL4RR4Q

    unity_iOvQOrnbL4RR4Q

    Joined:
    Apr 9, 2023
    Posts:
    6
    I'm creating a simple game to help kids learn math.
    In this project I have a singleton that stores all possible results. When a piece is created its result added to that list. However, when it detects that another block is on top of it, it removes itself from that list. The idea is that only the top results are acceble.

    The logic is: Is there a hit? If so, is this result on the list? Then, if what I hit is another block, the result is removed from the list. If there is no hit and the result is not already on the list, it gets added back.

    The problem comes with the raycast. When a block has another ontop of it, the result gets removed from the list. But then it gets immidiatly added back. As if the block no longer has another block ontop of itself. Even though it does.

    The raycast starts 0.5 away from the center of the block so that it doesn't colide with itself, since i'm checkin for tags.

    Maybe another method for checking if there is something on top would work, but I don't have any more ideas. I'd prefer not to use a trigger collider because that would mess up the way the blocks fall.
    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using TMPro;
    6. using Unity.VisualScripting;
    7. using UnityEngine;
    8.  
    9. public class Smalltetrisblock : MonoBehaviour
    10. {
    11.     public TextMeshProUGUI text;
    12.     public bool hasFallen = false;
    13.     public float fallspeed = 1.0f;
    14.     private float falltimer;
    15.     public int result;
    16.     private bool res_already_added = true;
    17.  
    18.     void Start()
    19.     {
    20.         result = UnityEngine.Random.Range(0, 100);
    21.         ExpressionControler._instance.addToList(result);
    22.         text.text = result.ToString();
    23.     }
    24.  
    25.     void Update()
    26.     {
    27.         RaycastHit2D down_hit = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.down), 1f);
    28.  
    29.         if ((Time.time - falltimer) > fallspeed && !down_hit)
    30.         {
    31.             transform.position += new Vector3(0, -1, 0);
    32.             falltimer = Time.time;
    33.         }
    34.  
    35.         if (down_hit)
    36.         {
    37.             hasFallen = true;
    38.         }
    39.  
    40.         if (hasFallen)
    41.         {
    42.             RaycastHit2D up_hit = Physics2D.Raycast(transform.position + new Vector3(0, 0.5f, 0), transform.TransformDirection(Vector2.up), 1f);
    43.  
    44.             if (up_hit)
    45.             {
    46.                 if (res_already_added)
    47.                 {        
    48.                     if (up_hit.collider.CompareTag("SmallBlock"))
    49.                     {
    50.                         Debug.Log("Remove: " + result);
    51.                         ExpressionControler._instance.removeFromList(result);
    52.                         res_already_added = false;
    53.                     }
    54.                 }
    55.             }
    56.             else
    57.             {
    58.                 if (!res_already_added)
    59.                 {
    60.                     Debug.Log("Nothing on top. Add: " + result);
    61.                     ExpressionControler._instance.addToList(result);
    62.  
    63.                     res_already_added = true;
    64.                 }
    65.             }
    66.         }
    67.     }
    68. }
    69.  
    70.  
     
    Last edited: Jul 6, 2023
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Keep debugging... find out more about what and when you are hitting with your raycasting stuff.

    Time to start debugging! Here is how you can begin your exciting new debugging adventures:

    You must find a way to get the information you need in order to reason about what the problem is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the names of the GameObjects or Components involved?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    Visit Google for how to see console output from builds. If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer for iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    "When in doubt, print it out!(tm)" - Kurt Dekker (and many others)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    The code doesn't really help much in debugging the issue. You need to also provide some images to show the context. If you cannot debug it with everything in front of you, we wont be able to help much with a code snippet. For instance, what does "When a block has another ontop of it" mean? Overlapped, stacked in 2D? Need some information.
     
  4. unity_iOvQOrnbL4RR4Q

    unity_iOvQOrnbL4RR4Q

    Joined:
    Apr 9, 2023
    Posts:
    6
    I added the whole code in the initial post. But I can't add an image there, so I'm replying here.
     

    Attached Files:

  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    I really don't follow the code logic here including the absolute time being compared to speed and the up/down raycast logic based upon you only wanting to know if a block is above you.

    To note, when you use:
    Code (CSharp):
    1. transform.TransformDirection(Vector2.down)
    you're rotating this by any transform rotation which I doubt you want so just use Vector2.down.

    Also, it's not clear why you're using raycast. If you want to know if a point is overlapped with a collider then you can use OverlapPoint (no directions needed).

    You can also ask if something IsTouching, even in specific directions using a ContactFilter2D.

    Overall though, if this is more like classic Tetris then you don't need a rigidbody simulation to do that. You'd typically used a fixed-grid of information and simply move the blocks as allowed by the grid information.
     
  6. unity_iOvQOrnbL4RR4Q

    unity_iOvQOrnbL4RR4Q

    Joined:
    Apr 9, 2023
    Posts:
    6
    It really is like classic Tetris. The raycast down is to see if the block can still fall or if it would occupy the same space as something else on the grid. And I don't use rigidBodies.

    As for the OverlapPoint and Istouching I didn't know about them. I'll try to use them instead of the raycast.

    But using raycasts, why does the block see something on top of it and them immediately thinks it has nothing on top?

    In any case. Thank you.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Oh don't use any physics for that!!!

    Tile-based / grid-based 2D games: match3, tetris, chips challenge, rogue, etc:

    For any tile-based game such as Match3 or Tetris or a grid-based Roguelike, do all the logical comparisons in your own data storage mechanism for the tiles, such as a 2D array of tiles.

    Otherwise you needlessly bind your game logic into Unity objects and the Unity API, making it about 10x more complicated than it needs to be.

    If you have no idea how to work with 2D arrays, hurry to some basic C# tutorials for the language portions of it, then look at any good tutorial that uses a 2D array.

    Here is my Match3 demo using this technique of storing data in a grid. Full source linked in game comments.

    https://kurtdekker.itch.io/match3-demo

    It stores all of its data in a 2D array:

    PieceController[,] Board;

    This allows for easy simple checking in code, not relying on anything like physics.

    You should strive to use that pattern for all logic, then only present what is happening in scene.
     
  8. unity_iOvQOrnbL4RR4Q

    unity_iOvQOrnbL4RR4Q

    Joined:
    Apr 9, 2023
    Posts:
    6
    Apparently this fixed it. Maybe a non integer value to the raycast was messing things ups? I don't know. But The point had a similar issue. Checking if what the point collided with was not "me" fixed the issue. Even though the point is outside the block and shouldn't collide with itself in the first place. Or so I thought.

    Code (CSharp):
    1. if (hasFallen)
    2.         {
    3.             Collider2D up_hit = Physics2D.OverlapPoint(transform.position + new Vector3(0, 0.6f, 0));
    4.  
    5.             if (up_hit)
    6.             {
    7.                 if (res_already_added)
    8.                 {      
    9.                     if (up_hit.CompareTag("SmallBlock") && up_hit.gameObject != this.gameObject)
    10.                     {
    11.                         Debug.Log("Colided with" + up_hit + "Remove: " + result);
    12.                         ExpressionControler._instance.removeFromList(result);
    13.                         res_already_added = false;
    14.                     }
    15.                 }
    16.             }
    17.             else
    18.             {
    19.                 if (!res_already_added)
    20.                 {
    21.                     Debug.Log("Nothing on top. Add: " + result);
    22.                     ExpressionControler._instance.addToList(result);
    23.  
    24.                     res_already_added = true;
    25.                 }
    26.             }
    27.         }
     
  9. unity_iOvQOrnbL4RR4Q

    unity_iOvQOrnbL4RR4Q

    Joined:
    Apr 9, 2023
    Posts:
    6
    Yeah, when I watched tutorials of how people made Tetris in unity I saw a bunch of stuff like that. I just didn't want to do that. I thought it would be very primitive, like I wasn't taking advantage of unity's abstractions. "If I was going to do that, might as well code in C with openGL". I thought.

    I also wanted to learn more unity, and pass some of the stuff I know to the people working with me who also wanted to lean unity.

    If there is a standard for grid control in unity I would like to know, and if it really is just an abstract data structure, than I guess I was wrong in my approach.
     
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Let me reframe your thinking slightly.

    The actual Tetris problem is simply not a physics problem.

    The benefit of Unity is (for instance) to trivially be able to do your Tetris as 3D blocks in a 2D plane, each block with rubbery jiggly jello animations and particles shooting out when a line is removed, then a sky glow and all the little block shatter in to pieces and fall off the screen.

    That's the value of Unity: quick breadth of flash and glitter and presentation, plus if you want content you can hire 256 artists, turn them loose and have 256 different block skins in a very short timeframe.

    Forcing the use of Unity Physics to solve non-physics problems isn't adding any value.

    But hey, if you got it working, more power to you!
     
  11. unity_iOvQOrnbL4RR4Q

    unity_iOvQOrnbL4RR4Q

    Joined:
    Apr 9, 2023
    Posts:
    6
    That makes sence.
     
  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,468
    No. More likely because you're not filtering what it hits or checking, it's hitting the block it's checking from. Note you increased the offset to 0.6 from 0.5. If the blocks are 1 in size then you're likely to hit the same block. Also, that altering the Up direction by the transform rotation was odd too as I mentioned.

    There's no need to guess though, it does return you the results so you could check this in seconds which is why it's important to debug it.