Search Unity

Question Why is negative operand not working?

Discussion in 'Scripting' started by melonhead, Sep 25, 2022.

  1. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    i need the raycast to detect when it hits an object called HEX

    this works ok but i need too detect if the ray is not hitting HEX

    i am using the negation operand but it is not working

    Code (CSharp):
    1. if (hit.transform.gameObject.name != "HEX"){
    2.  
    3.                 Debug.Log("MISS");
    4.             }else{
    5. Debug.Log"HIT")
    6. }
     
  2. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,701
    The code would work. Try printing the name and see what it actually is that it hits.
     
    Bunny83 likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    There's several ways to interpret this:

    - test if I'm hitting nothing

    - test to make sure that I am hitting things, but make sure they're not named HEX

    Your code seems to be doing the latter.

    But as Dragon says, print stuff out. You know this already:

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

    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 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.

    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 or 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/

    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)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
    AlyssaFaden likes this.
  4. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    see i thought the code should work but for some reason it just isnt, it still shows the debug as hit when it hits other objects, i need it to detect when it is not hitting anything like firing at the sky, i thought that would be null but that also does not register,

    how would i detect when the ray is not hitting the HEX, say i had a gun and it could only fire if the ray was touching HEX and nothing else, how would i code it to only detect HEX, I THOUGHT THAT WOULD BE =="HEX" but that also still detects when i hit other objects, do you think this is a bug, i am using an older unity 2018 version as i can not upgrade due to some assets in my project that wont upgrade
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    Walk through your code and what you expect values to be when:

    - you hit absolutely nothing (hit.transform is likely null, right?)

    - you hit something:
    ---> it is called HEX
    ---> it is NOT called HEX

    You'll see you're not handling all cases correctly if you take it one step at a time.
     
    AlyssaFaden likes this.
  6. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    so how do i detect if the ray hits nothing at all? not another object but absolutely nothing

    i have tried
    if (hit.collider == null)

    but it does not work for some reason, it says it should in the unity docs?
     
  7. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    hit == null


    The .collider only exists if the hit happened.
     
  8. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    just found this

    if (!hit)

    will give it a go later see if it works
     
  9. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    god of course, why did i use hit.collider if i want to detect nothing hit, what a fool i am, too much coding time brain corroded thank you
     
  10. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    Hey, the brain is a delicate organ sometimes needs time to process things.
    Balance the yin and yang. Urgency creates frustration. Make sure you are well fed.
     
  11. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    It can be helpful to explain it to your dog or your houseplant.

    "This line here checks the name if I hit nothing..."

    or,

    "If I hit nothing then I check its name..."

    And it will sound wrong.

    You can see me explaining a bug to my dog in my avatar picture.
     
  12. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,008
    Wow, there seems to be a lot misinformation around here ^^. First of all, you should clear up if you talk about Physics, or Physics2D. Those are two seperate physics systems which work different. The normal 3d "Physics" Raycast method returns a bool value indicating if it hit something or not. So accessing anything from the hit structure when the method returns false should already be avoided.

    No matter which physics system you're using, the RaycastHit and RaycastHit2D types are structs and therefore can not be compared to null.

    This does only work with the RaycastHit2D struct as it implements an implicit conversion operator to bool which internally checks if
    hit.collider
    is null or not. Physics2D.Raycast works different as it does not return a bool, but directly returns a RaycastHit2D struct. Checking the collider property is the only way to know if you hit something or not, though for 2d they implemented this conversion operator as a shortcut.

    Well, this should actually work in both cases (we still don't know if you use 2d or 3d physics. Though if
    if(!hit)
    works, you're probably using Physics2D?) as the collider property of both structs simply use
    Object.FindObjectFromInstanceID
    internally by passing the internal colliderID to that method. So the only two possibilities are: the id is invalid and you get null as a result, or if the id is valid, it would return the collider instance.

    This:
    won't work as hit.transform would return null if you didn't hit anything. So trying to get the gameobject from a null reference would give you a null reference exception.

    So it seems a lot wrong conclusions has been drawn here.
     
    Last edited: Sep 26, 2022
  13. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    You’re quite right bunno

    if ray out hit

    else // I am hit null
     
  14. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    t
    tried it but get error:
    error CS0019: Operator `==' cannot be applied to operands of type `UnityEngine.RaycastHit' and `null'

    why is this so dificult, all i want to do is detect when the ray hits the object named HEX, i done that

    but then i want to do something else when the ray is not hitting HEX, so in other words when the ray is either touching or not touchng anything but HEX, tried so many ways but none seem to work, why can i not use the ! negation operator for this so it means anything other than HEX?


    using 3d not 2d
     
    Last edited: Sep 26, 2022
  15. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    Code (CSharp):
    1.  
    2.              RaycastHit2D hit = Physics2D.Raycast(transform.position, -Vector2.up);
    3.                 if (hit == false)
    4.                 {
    5.                
    6.                 }
    7.  
    8.  

    Try this one

    looks like Raycast2D's hit is a bool. Raycast3D hit is not a bool and can be checked for null or else.
     
  16. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    tried t, just gives errors
     
  17. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    Sorry can't help
     
  18. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    this is getting ridiculous, how can this be impossible?

    all i need is

    if ray hit HEX
    do this
    if ray hits anything else or nothing
    do this

    but it seems impossible to do
     
  19. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    can someone from unity explain why this does not work

    if(hit.transform.gameObject.name != "HEX"){

    Debug.Log("HIT");
    }else{
    Debug.Log("MISS");

    MISS is never called even when the ray is NOT touching the object named HEX

    how can i detect when the raycast is NOT touching the gameobject named HEX or anything else? is this really impossible too do in unity?
     
  20. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,935
    Maybe read the post by @Bunny83 which explained some crucial details you seem to have ignored.

    You also need to make sure the objects you're hitting have colliders.
     
    Kurt-Dekker and PraetorBlue like this.
  21. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    the object has a collider, it is detecting hitting the object I NEED TO DETECT WHEN IT IS NOT AS IN NOT HITTING THE OBJECT!!! can you explain why this below will not debug MISS when it is clearly not hitting the object HEX

    if(hit.transform.gameObject.name != "HEX"){

    Debug.Log("HIT");
    }else{
    Debug.Log("MISS");

    HOW THE F*** CAN THIS NOT BE WORKING IF HEX IS NOT HIT BY THE RAY WHY IS IT NOT CALLING THE MISS DEBUG
     
  22. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,935
    Calm your tits.

    You've given us hardly any context. Only some poorly formatted code followed by basically the same thing over and over that clearly, does, not, work.

    If the raycast isn't hitting anything... then there's nothing to check. You need to check that raycast hits something first before you actually check what the raycast may, or may not be hitting.

    It's not that hard.
     
    AlyssaFaden and Kurt-Dekker like this.
  23. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,008
    Yes, it kinda gets ridiculous :) Though there's no issue on the Unity side. In your first post you only posted a tiny part of your code. That's why we can't even tell if you're using 2d or 3d physics.

    That's what you just posted lately which is a tiny bit more information but you still haven't shown how you do your raycast. Have you actually read the documentation on Physics.Raycast? There is example code which shows how to use it.

    As already explained the Physics.Raycast method returns a boolean value indicating if you hit something or not. If you ignore that value and access the "hit" struct anyways, you will run into issues. So the correct way to check that you did hit an object named "HEX" is this

    Code (CSharp):
    1. if (Physics.Raycast(pos, dir, out hit) && hit.transform.gameObject.name == "HIT")
    2. {
    3.  
    4. }
    5.  
    You can use an else after that if statement to get the opposite. However if you want directly check the opposite, you just use boolean algebra and it turns into

    Code (CSharp):
    1. if (!Physics.Raycast(pos, dir, out hit) || hit.transform.gameObject.name != "HIT")
    2. {
    3.  
    4. }
    5.  
    Note that it's important that those two checks are in the same if statement. You can't do them one after the other because the second condition must only be checked, when the Raycast method returns true. So this if statement would be entered when the raycast returns false (so nothing was hit) or (if we did hit something) when the name of the object we've hit is not "HIT".

    Note that hit.transform may return a different transform depending on if the collider you hit belongs to a rigidbody or not. If the collider is part of a compound collider, hit.transform would return the transform of the rigidbody. You can use hit.collider.gameObject if you want to access the gameobject of the actual collider. Though this behaviour can be figured out from the reference source that I linked above.
     
  24. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    ok the raycast is as bunny has put, which is what i was using but i am using infinity so the ray just goes on and on
    then i put:
    if(hit.transform.gameObject.name != "HEX"){

    Debug.Log("HIT");
    }else{
    Debug.Log("MISS");

    now the debug MISS is called when the ray hits another object not called HEX, ok so thats working but how do i detect when the ray is not hitting an object at all, as in not hitting anything so like this

    if(hit.transform.gameObject.name != "HEX"){

    Debug.Log("HIT"); // hitting object named HEX
    }else{
    Debug.Log("MISS"); // hitting object not named HEX

    NOW I NEED AFTER THAT

    }else{
    Do something here when not hitting any objects?

    might be easier if i put it like this

    my player has an auto gun that can only be fired when ONLY the object called HEX is in line of the raycast, NOT ANYOTHER OBJECT...how would i detect that the object is not in line so it cannot be fired
     
    Last edited: Sep 26, 2022
  25. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,935
    Iunno... maybe...

    Code (CSharp):
    1. if (//raycast)
    2. {
    3.     //we hit something
    4. }
    5. else
    6. {
    7.     //nothing was hit
    8. }
    ???
     
  26. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    I can't stand it any longer.

    The critical logic we have been spinning about begins on line 48.

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. // @kurtdekker - for @melonhead in the thread:
    4. // https://forum.unity.com/threads/why-is-negative-operand-not-working.1340582
    5. //
    6. // To use:
    7. //    - make a scene with camera / light (default)
    8. //    - drop ONE copy of this script on ONE of the above GameObjects (doesn't matter which)
    9. //    - press PLAY
    10. //    - use left/right arrows to move the box, your "downward casting cursor"
    11. //    - read the spew in the Debug.Log() console window
    12. //
    13. // Watch the scene closely as this runs.
    14. //
    15. // You can hit:
    16. //    - nothing
    17. //    - something called HEX
    18. //    - other things NOT called HEX
    19.  
    20. public class ForMelonHead : MonoBehaviour
    21. {
    22.     GameObject box;
    23.  
    24.     private void Start()
    25.     {
    26.         // this is our marker or cursor; we will cast DOWN from it
    27.         box = GameObject.CreatePrimitive(PrimitiveType.Cube);
    28.  
    29.         // left ball
    30.         var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    31.         sphere.transform.position = new Vector3(-1, -2);
    32.  
    33.         // right ball - named HEX
    34.         sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    35.         sphere.transform.position = new Vector3(+1, -2);
    36.         sphere.name = "HEX";
    37.     }
    38.  
    39.     private void Update()
    40.     {
    41.         // input
    42.         float xm = Input.GetAxisRaw("Horizontal");
    43.  
    44.         // move
    45.         box.transform.position += Vector3.right * (3 * xm * Time.deltaTime);
    46.  
    47.         // raycast
    48.         Ray ray = new Ray(origin: box.transform.position, direction: Vector3.down);
    49.         RaycastHit hit;
    50.         if (Physics.Raycast(ray: ray, hitInfo: out hit))
    51.         {
    52.             if (hit.collider.name == "HEX")
    53.             {
    54.                 Debug.Log("Hitting a thing called HEX!");
    55.             }
    56.             else
    57.             {
    58.                 Debug.Log("Hitting SOMETHING, but its name is NOT HEX");
    59.             }
    60.         }
    61.         else
    62.         {
    63.             Debug.Log("Hitting absolutely NOTHING");
    64.         }
    65.     }
    66. }
     
    Last edited: Sep 27, 2022
    AnimalMan, Bunny83 and spiney199 like this.
  27. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    was a problem with the unity install for some reason, i reinstalled everything and is now the same script is working as it should, not sure what the problem was, looks like some sort of gremlin got into the unity install, thanks for all the above help, might use some of it as looks a bit more eficient than my original code is.

    regards
     
  28. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    A gremlin?
     
  29. melonhead

    melonhead

    Joined:
    Jun 3, 2014
    Posts:
    630
    gremlin = bug, or similar!
     
  30. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,935
    Lol yeah right.
     
  31. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,008
    Even though totally off topic: a gremlin :)
    Some may know the movie Gremlins by Steven Spielberg.

    That said, in the last 10+ years I never had any issues that has been solved by reinstalling Unity, unless I actually, literally messed something up in the installation itself which can't really happen by accident. Especially the issue like the one mentioned in this thread is extremely unlikely to be fixed by reinstalling.
     
    Kurt-Dekker likes this.
  32. AnimalMan

    AnimalMan

    Joined:
    Apr 1, 2018
    Posts:
    1,164
    Thanks guys I know what a gremlin was I was just, confirming that he actually meant a gremlin.

    Gremlin was coined in world war 2, used to explain defective machinery. Gremlin image of a furry creature similar to a raccoon or a mongoose was used in American pro war propaganda. Particularly it was used to encourage women to aid in the war effort and the preservation of foods. Keep the gremlins away from the food buy canned spam.

    One issue I had with unity that was solved by a reinstall was a fault with unity hub unable to recognize the location of a unity editor version on my HDD.
     
    DragonCoder likes this.