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

Surface recognition by throwing rays

Discussion in 'Editor & General Support' started by LokenGarviel, Aug 27, 2020.

?

Surface recognition by throwing rays does not work

  1. not possible in this version

    0 vote(s)
    0.0%
  2. old functions

    0 vote(s)
    0.0%
  1. LokenGarviel

    LokenGarviel

    Joined:
    Aug 25, 2020
    Posts:
    12
    I am studying the textbook "Unity in action 2 edition" and trying to make surface recognition by throwing rays.
    The code for unity 2019.4 produces:"
    NullReferenceException: Object reference not set to an instance of an object
    RelativeTarger.Update () (at Assets/RelativeTarger.cs:69"
    Anyone can follow this tutorial and understand what the problem is?
    I looked it 100 times and I can't understand


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class RelativeTarger : MonoBehaviour
    6. {
    7.     [SerializeField] private Transform target;
    8.     public float rotSpeed = 15.0f;
    9.     public float moveSpeed = 6.0f;
    10.     private CharacterController _charController;
    11.     public float jumpSpeed = 15.0f;
    12.     public float gravity = -9.8f;
    13.     public float terminalVelocity = -10.0f;
    14.     public float minFall = -1.5f;
    15.     private float _vertSpeed;
    16.     //RAY//
    17.     private ControllerColliderHit _contact;
    18.  
    19.     // Start is called before the first frame update
    20.     void Start()
    21.     {
    22.         _vertSpeed = minFall;
    23.         _charController = GetComponent<CharacterController>();
    24.  
    25.     }
    26.  
    27.     // Update is called once per frame
    28.     void Update()
    29.     {
    30.         Vector3 movement = Vector3.zero;
    31.         float horInput = Input.GetAxis("Horizontal");
    32.         float vertInput = Input.GetAxis("Vertical");
    33.         if (horInput != 0 || vertInput != 0) {
    34.             movement.x = horInput * moveSpeed;
    35.             movement.z = vertInput * moveSpeed;
    36.             movement = Vector3.ClampMagnitude(movement, moveSpeed);
    37.             Quaternion tmp = target.rotation;
    38.             target.eulerAngles = new Vector3(0, target.eulerAngles.y, 0);
    39.             movement = target.TransformDirection(movement);
    40.             target.rotation = tmp;
    41.             Quaternion direction = Quaternion.LookRotation(movement);
    42.             transform.rotation = Quaternion.Lerp(transform.rotation, direction,
    43.                 rotSpeed * Time.deltaTime);
    44.  
    45.         }
    46.  
    47.         bool hitGround = false;
    48.         RaycastHit hit;
    49.  
    50.         if (_vertSpeed < 0 && Physics.Raycast(transform.position, Vector3.down, out hit)) {
    51.             float check = (_charController.height + _charController.radius) / 1.9f;
    52.             hitGround = hit.distance <= check;  
    53.         }
    54.  
    55.  
    56.  
    57.         if (hitGround) {
    58.             if (Input.GetButtonDown("Jump")) {
    59.                 _vertSpeed = jumpSpeed;
    60.             } else {
    61.                 _vertSpeed = minFall;
    62.             }
    63.         } else {
    64.             _vertSpeed += gravity * 5 * Time.deltaTime;
    65.             if (_vertSpeed < terminalVelocity) {
    66.                 _vertSpeed = terminalVelocity;
    67.             }
    68.             if (_charController.isGrounded) {
    69.                 if (Vector3.Dot(movement, _contact.normal) < 0) {
    70.                     movement = _contact.normal * moveSpeed;
    71.                 } else {
    72.                     movement += _contact.normal * moveSpeed;
    73.                 }
    74.             }
    75.         }
    76.         movement.y = _vertSpeed;
    77.  
    78.         movement *= Time.deltaTime;
    79.         _charController.Move(movement);
    80.         }
    81.         void OnControllerColliderHit(ControllerColliderHit hit) {
    82.                 _contact = hit;
    83.         }
    84. }
     
  2. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,497
    _contact isn't assigned anything until OnControllerColliderHit, that's why it's null reference. Try changing line 68 to this:
    Code (CSharp):
    1. if (_charController.isGrounded && (_contact != null)) {
     
    LokenGarviel likes this.
  3. LokenGarviel

    LokenGarviel

    Joined:
    Aug 25, 2020
    Posts:
    12
    Thank you, now the program starts, but the jump stopped working, and the character somehow barely moves :)
     
  4. LokenGarviel

    LokenGarviel

    Joined:
    Aug 25, 2020
    Posts:
    12
    The hitGround condition does not pass, maybe something is wrong with the rays
     
  5. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,497
    This, probably:
    Code (CSharp):
    1. Physics.Raycast(transform.position, Vector3.down,
    If the position is below the surface, it will not hit. Try either clamping the position passed in so it will never be underneath the surface (if floor is linear/flat that's easy),or even just something that will make sure the position is above surface..
    Code (CSharp):
    1. Physics.Raycast(transform.position + (Vector3.up * 100), Vector3.down,
    Edit: note you will probably need to add a layerMask later to this Raycast so it's only testing what you're allowing to walk on.. you don't want it to be glitching out standing on top of projectiles flying by etc.
     
    LokenGarviel likes this.
  6. LokenGarviel

    LokenGarviel

    Joined:
    Aug 25, 2020
    Posts:
    12
    I did it as you said, but as far as I understand, it goes inside
    Code (CSharp):
    1. if (_vertSpeed <0 && Physics.Raycast (transform.position, Vector3.down, out hit))
    , but it can't get through
    Code (CSharp):
    1. float check = (_charController.height + _charController.radius) / 1.9f;
    2. hitGround = hit.distance <= check;
     
  7. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,497
    Could be that your Raycast is hitting something else (collider on the character most likely in this case, which you could fix by setting the collider .enabled = false before the Raycast then .enabled true again after), you can find out what's being hit, just add
    Debug.Log("hit: " + hit.transform.name);
    before the line starting with "float check". You can also
    Debug.Log(hit.distance + "/" + check)
    to see what the values are.
     
    LokenGarviel likes this.
  8. LokenGarviel

    LokenGarviel

    Joined:
    Aug 25, 2020
    Posts:
    12
    thanks, I will try to solve
     
    adamgolden likes this.