Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Help, I cannot get the grab right on my character.

Discussion in 'Scripting' started by AlstonA, Jan 20, 2020.

  1. AlstonA

    AlstonA

    Joined:
    Jun 13, 2013
    Posts:
    24
    I'm having a lot of trouble performing a grab similar to the game Tomba. I have two different types of grabs on my character; one standing, and the other when jumping. I keep getting "NullReferenceException: Object reference not set to an instance of an object located at PlayerGrabTrigger.TopGrab () (at Assets/Scripts/PlayerGrabTrigger.cs:44) ". When top grab is removed. The normal grab works perfectly. Please help.

    Code (CSharp):
    1. void StandGrab( )
    2.     {
    3.         if(Input.GetKeyDown(KeyCode.E) && !topGrab) {                                                                                                           // TODO: There will be a bug here that will need to be fixed later.
    4.  
    5.             if(!standGrab) {
    6.                 Physics2D.queriesStartInColliders = false;
    7.                 hit = Physics2D.Raycast(transform.position, Vector2.right * transform.localScale.x, distance);
    8.  
    9.                 if(hit.collider != null && hit.collider.tag == "Grabbed") {
    10.                     standGrab = true;
    11.  
    12.                 }
    13.             }
    14.             else if(!Physics2D.OverlapPoint(grabPoint.position, notGrabbed)) {
    15.                 standGrab = false;
    16.                 if(hit.collider.gameObject.GetComponent<Rigidbody2D>() != null) {
    17.                     hit.collider.gameObject.transform.GetComponent<Rigidbody2D>().simulated = true;
    18.                     hit.collider.gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(transform.localScale.x, 5) * standThrowForce;  //<-- This controls the throw force and direction. Add force should be replaced
    19.                 }
    20.             }
    21.         }
    22.         if(standGrab) {
    23.             topGrab = false;
    24.             hit.collider.gameObject.transform.position = grabPoint.position;
    25.             hit.collider.gameObject.transform.GetComponent<Rigidbody2D>().simulated = false;
    26.             hit.collider.gameObject.transform.GetComponent<Transform>().localRotation = Quaternion.identity;
    27.         }
    28.  
    29.     }
    30.  
    31.     public void TopGrab( )                                                                                                           // Motion is called when the enemy is in a stunned stated and the player is landing on the enemy from the top.
    32.     {
    33.  
    34.         if(!topGrab) {
    35.             Physics2D.queriesStartInColliders = false;
    36.             hit = Physics2D.Raycast(transform.position * 1, transform.position + -transform.up, downwardDistance);
    37.             if(hit.collider != null && hit.collider.tag == "Grabbed" && isConnected) {
    38.                 topGrab = true;
    39.  
    40.             }
    41.  
    42.             else if(!Physics2D.OverlapPoint(topGrabPoint.position, notGrabbed)) {
    43.                 topGrab = false;
    44.                 if(hit.collider.gameObject.GetComponent<Rigidbody2D>() != null && playerFeet.IsTouchingLayers(enemyMask)) {
    45.                     hit.collider.gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(transform.localScale.x, 5) * topThrowForce;  //<-- This controls the throw force and direction. Add force should be replaced
    46.                 }
    47.             }
    48.         }
    49.         if (topGrab && isConnected) {
    50.             standGrab = false;
    51.             hit.collider.gameObject.transform.position = topGrabPoint.position;
    52.             hit.collider.gameObject.gameObject.transform.GetComponent<Transform>().localRotation = Quaternion.identity;
    53.         }
    54.     }
    55.    
    56.  
    57.  
    58.  
    59.     void ConnectFromTop( )
    60.     {
    61.         if(playerBox.IsTouchingLayers(enemyMask) && controller.playerRigidBody.velocity.y > 0 || playerFeet.IsTouchingLayers(enemyMask) && controller.playerRigidBody.velocity.y > 0) {
    62.             isConnected = true;
    63.             //hit.collider.gameObject.transform.GetComponent<Rigidbody2D>().simulated = false;
    64.             playerRig.transform.position = hit.collider.gameObject.transform.position;
    65.             // playerRig.velocity += new Vector2(0, playerRig.velocity.y * topThrowForce);
    66.         }
    67.         if(!playerBox.IsTouchingLayers(enemyMask)) {
    68.             isConnected = false;
    69.         }
    70.         //else if(!controller.IsPlayerJumping) {
    71.         //    isTryingToConnect = false;
    72.         //}
    73.     }
     
  2. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    The logic in lines 37 and 44 is the problem. If hit.collider is null (i.e. your raycast doesn't hit anything), and there's no overlap on line 42, then hit.collider will still be null on line 44, causing the NRE.
     
  3. AlstonA

    AlstonA

    Joined:
    Jun 13, 2013
    Posts:
    24

    Sorry I am pretty new with this can you elaborate a little more.
     
  4. WallaceT_MFM

    WallaceT_MFM

    Joined:
    Sep 25, 2017
    Posts:
    394
    Ok, line 36 does a raycast and fills the 'hit' variable. The raycast might not hit something, in which case hit.collider will be null. Focus on this case. hit.collider is null, so the 'if' on line 37 sees this and does not execute because of the first condition (hit.collider != null is False). So, the else statement on 42 executes, checking for an overlap. If there is no overlap, the if executes.
    So, we are in the case where hit.collider is null, and there is no overlap for line 42. Line 43 is a simple assignment, so no problem, but then we get to line 44. We know that hit.collider is null, but the first thing this line does is try to access hit.collider.gameObject (to the call GetComponent, but we don't get there). Collider was null, so try to access the gameObject throws an exception.
     
    AlstonA likes this.
  5. AlstonA

    AlstonA

    Joined:
    Jun 13, 2013
    Posts:
    24
    Ah! I see hold on I am going to try to work on this.

    Sorry for the late reply. Thannk you I will try something different to get it to located the players rigidbody when it is in use.