Search Unity

Question Raycast DrawRay changing length based on direction

Discussion in 'Scripting' started by johnc81, Aug 2, 2020.

  1. johnc81

    johnc81

    Joined:
    Apr 24, 2019
    Posts:
    142
    Hello,

    I am building a top down game and want to implement a raycast on the player to detect enemies within a certain distance. The idea is that I can only engage the enemy in battle when they are within the distance defined for the raycast.

    The raycast points in the direction the player is facing, which is correct, but when I move my player around, the length of the ray in the DrawRay seems to change length. Also, it only detects enemies when I am moving. As soon as I stop, the raycast stops detecting them. Does anyone have any ideas how to resolve this?

    Here is the code in my update function:

    Code (CSharp):
    1.     public void Update() {
    2.         movement.x = joystick.Horizontal;
    3.         movement.y = joystick.Vertical;
    4.         movement = new Vector2(movement.x, movement.y);
    5.  
    6.         Vector2 dir = new Vector2(movement.x, movement.y);
    7.         if (dir == Vector2.zero) {
    8.             dir = movement;
    9.         } else {
    10.             movement = dir;
    11.         }
    12.  
    13.         Vector2 start = transform.position;
    14.         float distance = 4.0f;
    15.  
    16.         Debug.DrawRay(start, dir * distance, Color.green);
    17.  
    18.         RaycastHit2D hit = Physics2D.Raycast(start, dir, distance, 1 << LayerMask.NameToLayer("Enemy"));
    19.         if (hit.collider != null) {
    20.             if (hit.collider.gameObject != gameObject) {
    21.                 Debug.Log("Collider is: " + hit.collider);
    22.             }
    23.         }
    24.     }
    Many Thanks,

    J
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,914
    First, all of this code... doesn't really do anything, other than the first two lines. The rest of the code seems to be "keep copying this same vector around, to itself and to another Vector called dir".

    Code (CSharp):
    1.         movement.x = joystick.Horizontal;
    2.         movement.y = joystick.Vertical;
    3.         movement = new Vector2(movement.x, movement.y);
    4.         Vector2 dir = new Vector2(movement.x, movement.y);
    5.         if (dir == Vector2.zero) {
    6.             dir = movement;
    7.         } else {
    8.             movement = dir;
    9.         }
    I'm 99% sure you'd get the same effect with just this:

    Code (CSharp):
    1.         movement.x = joystick.Horizontal;
    2.         movement.y = joystick.Vertical;
    3.         Vector2 dir = movement;
    With that out of the way, you should try normalizing your direction vector before creating the ray:
    Code (CSharp):
    1. dir.Normalize();
    That way your ray will always be the same length, which is your distance (4)

    If you don't normalize it, the distance of the ray depends on how far you're pushing your joysticks. Additionally, there's a thing with most joystick implementations where the length of the direction will be longer on the diagonals than vertical or horizontal (this is basically just due to pythagorean theorem - the hypotenuse of the triangle is the longest side).
     
  3. johnc81

    johnc81

    Joined:
    Apr 24, 2019
    Posts:
    142
    Hi PraetorBlue,

    Thank you very much. Yes, the code is a bit messy because I was trying a few things out because I want the ray to be cast even when the player is not moving. I am now storing the XY position when the player is moving and doing a simple if statement to use that as the direction if Vector2.zero:

    Code (CSharp):
    1. if (movement == Vector2.zero) {
    2.             dir = new Vector2(lastX, lastY);
    3.             dir.Normalize();
    4.         }
    It works, but not sure if there is a better (more performant) way to do it?

    Many Thanks,

    J