Search Unity

The Ray doesn't work like I expect.

Discussion in 'Scripting' started by denis-andreevich, Mar 17, 2019.

  1. denis-andreevich

    denis-andreevich

    Joined:
    Aug 21, 2016
    Posts:
    50
    According to my idea, the Minotaur should turn and go to the side of the character, when the character was in the "field of view" of the Minotaur through the Ray. The code below:
    Code (CSharp):
    1. RaycastHit2D RayLeft;
    2. RaycastHit2D RayRigth;
    3.  
    4. void OnDrawGizmos()
    5.     {
    6.         Gizmos.color = Color.green;
    7.         Gizmos.DrawLine(transform.position,transform.position+Vector3.right*transform.localScale.x*distRigth);
    8. Gizmos.DrawLine(transform.position,transform.position+Vector3.left*transform.localScale.x*DistLeft);
    9. }
    10. void Update()
    11. {
    12.         Physics2D.queriesStartInColliders=false;
    13. // Рисуем лучи
    14. RayLeft = Physics2D.Raycast(transform.position,Vector2.left*transform.localScale.x,DistLeft);
    15. RayRigth = Physics2D.Raycast(transform.position,Vector2.right*transform.localScale.x,distRigth);
    16. //Что делаем, если в луч попал игрок.
    17. // Идём в сторону игрока
    18. if (RayLeft.collider!=null && RayLeft.collider.tag == "Player")
    19. {
    20. State = CharStateMin.Walk;
    21. rb.velocity = new Vector2 (dirX * -speed, 0);
    22. }
    23. else
    24. {
    25.             State = CharStateMin.idle;
    26.         }
    27. if (RayRigth.collider!=null && RayRigth.collider.tag == "Player")
    28. {
    29. State = CharStateMin.Walk;
    30. rb.velocity = new Vector2 (dirX * speed, 0);
    31. }
    32. else
    33. {
    34.             State = CharStateMin.idle;
    35.         }
    36.      
    37.         if (health <= 0)
    38.         {
    39.             State = CharStateMin.Die;
    40.             GOMinotaur.isTrigger = true;
    41.         }
    42.      
    43.         Collider2D[] DamagePlayer = Physics2D.OverlapCircleAll(attackPos.position, attackRange, Player);
    44.         for (int i= 0; i < DamagePlayer.Length; i++)
    45. {
    46.             DamagePlayer[i].GetComponent<HeroHealth>().HeroTakeDamage(damage);
    47.         }
    48. }
    But in fact, the Minotaur goes towards the player only when the player's BoxCollider2D comes into contact with the Minotaur's BoxCollider2D. And not when the player was in the "field of view"

    What other way to determine that the hero came to the Minotaur?
    upload_2019-3-17_15-10-1.png
     
  2. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    What if you update your gizmos to draw the ray as well, do you see the red lines appear over your green gizmo lines?
    Code (CSharp):
    1.     void OnDrawGizmos()
    2.     {
    3.         // Draw "line of sight" in green.
    4.         Gizmos.color = Color.green;
    5.         Gizmos.DrawLine(transform.position, transform.position + Vector3.right * transform.localScale.x * distRigth);
    6.         Gizmos.DrawLine(transform.position, transform.position + Vector3.left * transform.localScale.x * DistLeft);
    7.  
    8.         if(RayLeft && RayRigth)
    9.         {
    10.             // Draw raycast "line of sight" in red.
    11.             Gizmos.color = Color.red;
    12.             Gizmos.DrawLine(transform.position, RayRigth.transform.position);
    13.             Gizmos.DrawLine(transform.position, RayLeft.transform.position);
    14.         }
    15.     }
     
  3. denis-andreevich

    denis-andreevich

    Joined:
    Aug 21, 2016
    Posts:
    50
    Lets do make script very simple:
    Code (CSharp):
    1. public class minotaur : MonoBehaviour
    2. {
    3.     private Animator animator; // переменная для записи анимации
    4.     [SerializeField]
    5.     private float distance;
    6.     RaycastHit2D hit;
    7.  
    8.     private void Start()
    9.     {
    10.         animator = GetComponent<Animator>();
    11.     }
    12.    
    13.     void OnDrawGizmos()
    14.     {
    15.         Gizmos.color = Color.green;
    16.         Gizmos.DrawLine(transform.position,transform.position+Vector3.left*transform.localScale.x*distance);
    17.     }
    18.  
    19.     void Update()
    20.     {
    21.         Physics2D.queriesStartInColliders=false;
    22.         hit = Physics2D.Raycast(transform.position,Vector2.left*transform.localScale.x,distance);
    23.         if(hit.collider!=null && hit.collider.tag=="Player")
    24.         {
    25.             Debug.LogWarning("Player detected!");
    26.         }
    27.     }
    28. }
    The meaning of the script is to start to display a message to the console, if the hero was in the Ray. But what I can't understand is that the message is shown when the hero almost came close to the Minotaur.

    Judging by the scene window, the hero has already hit the Ray , but the message is not received in the console.
    upload_2019-3-19_10-49-42.png

    The message begins to flow when the hero fits pretty close. The red circle that is on the hero determines whether the life of the monsters that are in the circle will be taken away. In this case, I can turn it off at all but the message will appear later.

    upload_2019-3-19_11-26-24.png
     
  4. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Yes, I see the problem. In the screen shots, the green gizmo line is a projection of how the ray should be acting and clearly it makes contact with the player sprite.

    The reason for the code I pasted was to superimpose the actual raycast line (in red) on top of the green line. Does it completely cover the green line (as required), or does it do something else?

    If the red line covers the green line, then the problem most probably lies with the raycast collision setup (layer mask, inactive collider etc.) If the red line does not cover the green, then the problem may be with the firing of the ray (direction, distance etc.)

    Actually, having said all that, have you checked that the raycast is actually returning null - is the tag on the player actually "Player", or is it, for example "player"? Or the collider could be on a child object with a different tag or something like that?
     
  5. denis-andreevich

    denis-andreevich

    Joined:
    Aug 21, 2016
    Posts:
    50
    I don't want to seem like a noob (which I probably am :) ), but when I copy and paste your code, then everything stops working for me. I'm just passing the Minotaur, that's all.

    Let's test my actions with collective intelligence. I wanted to implement the following simple actions:
    • when a player gets into the green ray that the Minotaur starts moving towards the player
    • when the player hits the yellow ray, the Minotaur attacks the player and takes one life
    To do this, I created a game object named Minotaur which hung the script code which I published above. But without the yellow Ray, because it did not deal with the green. Like all correctly?
    To be sure, I disabled the player's other two colliders and left only one, but it did not help.
     
  6. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Hmm, that seems odd. I didn't test the code, but it was really only one
    if
    and two draw lines.

    Yes, that seems perfectly fine.

    Given that you have simplified the problem down (which is a great start), maybe the next thing is to determine if the ray is actually hitting something.

    In your code in post #3 above, after line 22, can you add:
    Code (CSharp):
    1. Debug.Log("Ray hit: " + (null == hit.collider) ? "TRUE" : "false");
    What gets logged out when the green line hits the player?
     
  7. denis-andreevich

    denis-andreevich

    Joined:
    Aug 21, 2016
    Posts:
    50
  8. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    It does look like the ray is working correctly. I would recommend that you try and add the actual ray cast line in red to your OnDrawGizmos rather than just relying on the green approximation line.

    It may be, for example, that the scale factors are giving you the inconsistency that you are seeing.