Search Unity

Why is this code not working?

Discussion in 'Scripting' started by NidoAnxari, Jul 25, 2017.

  1. NidoAnxari

    NidoAnxari

    Joined:
    Jan 2, 2017
    Posts:
    86
    I am making a bubble shooter like game. Now I am working on making an aim line to help player aim. I am using Line Renderer and Raycast. I am almost new to coding and can not figure out the problem. I have asked earlier but no one replied. So I am trying again in hope that someone can answer.
    So I want to Reflect the Raycast when it hits the wall but Raycast is not reflecting and Line drawn by Line Renderer is only of one segment. I am trying to solve it for three days but have no progress.
    Following is my code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class testAimLine : MonoBehaviour
    6. {
    7.     public GameObject obj;
    8.     LineRenderer lr;
    9.  
    10.     [SerializeField]
    11.     public int numberOfReglections;
    12.  
    13.     Vector3[] pos = new Vector3[5];
    14.     Vector3[] rot = new Vector3[5];
    15.  
    16.     private void Start()
    17.     {
    18.         lr = GetComponent<LineRenderer>();
    19.  
    20.         pos[0] = gameObject.transform.position;
    21.         rot[0] = gameObject.transform.eulerAngles;
    22.  
    23.         lr.SetPosition(0, pos[0]);
    24.     }
    25.    
    26.     private void Update()
    27.     {
    28.         for (int i = 1; i < numberOfReglections; i++)
    29.         {
    30.             RaycastHit2D ray = Physics2D.Raycast(pos[i - 1], rot[i - 1]);
    31.  
    32.             pos[i] = ray.point;
    33.             rot[i] = Vector3.Reflect(pos[i], ray.normal);
    34.  
    35.             lr.SetPosition(i, pos[i]);
    36.             print("position" + i);
    37.         }
    38.     }
    39. }
    40.  
     
  2. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    From what I understand, Physics2d.Raycast takes a direction vector as the second argument.
    https://docs.unity3d.com/ScriptReference/Physics2D.Raycast.html

    Your rot array stores rotations, not directions. You can get direction instead of rotation from gameObject.transform.forward in line 21.

    Though I guess this isn't what causes the problem, since you say you have at least one segment... Are you sure the ray actually hits anything else? If the ray doesn't hit anything else I guess ray.point would never have a valid value...
     
    Last edited: Jul 25, 2017
  3. johne5

    johne5

    Joined:
    Dec 4, 2011
    Posts:
    1,133
    the logic looks good. so lets see what some debugs say

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class testAimLine : MonoBehaviour
    6. {
    7.     public GameObject obj;
    8.     LineRenderer lr;
    9.  
    10.     [SerializeField]
    11.     public int numberOfReglections;
    12.  
    13.     Vector3[] pos = new Vector3[5];
    14.     Vector3[] rot = new Vector3[5];
    15.  
    16.     private void Start()
    17.     {
    18.         lr = GetComponent<LineRenderer>();
    19.  
    20.         pos[0] = gameObject.transform.position;
    21.         rot[0] = gameObject.transform.eulerAngles;
    22. //have you tried rot[0] = gameObject.transform.localrotation;
    23. //this should more of direction
    24.  
    25.         lr.SetPosition(0, pos[0]); //set the first position to this gameObject
    26.     }
    27.  
    28.     private void Update()
    29.     {
    30.         for (int i = 1; i < numberOfReglections; i++)
    31.         {
    32.         //first time i=1
    33.             RaycastHit2D ray = Physics2D.Raycast(pos[i - 1], rot[i - 1]); //start ray position = pos[0], rot ray posistion = rot[0]
    34.  
    35.             Debug.Log("ray.point : " + ray.point); // show me the ray.point
    36.             pos[i] = ray.point; //set pos[1] = a new point for the next loop
    37.             rot[i] = Vector3.Reflect(pos[i], ray.normal); // set rot[1] = a new point for the next loop
    38.             Debug.Log(rot[i]); //show me the next rot
    39.  
    40.             lr.SetPosition(i, pos[i]); //add a position (1, pos[1])
    41.             print("position" + i); //this should be 1
    42.         }
    43.     Debug.Log(lr.positionCount); //after the for loop tell me how many points there are
    44.     }
    45. }
     
    Last edited: Jul 25, 2017
  4. NidoAnxari

    NidoAnxari

    Joined:
    Jan 2, 2017
    Posts:
    86
    Actually I'm not currently on my PC but when I will, I will share a screen shot. It looks like ray is hitting something within the object.
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    @BakeMyCake is correct, the euler angles of an object is not the same as it's forward vector. In your setup, if the object is not rotated at all, the starting ray is in the direction (0, 0), which makes no sense as a direction for a ray.

    The first ray direction should be transform.forward, all the subsequent ones should be:

    Code (csharp):
    1. rot[i] = Vector3.Reflect(rot[i - 1], ray.normal)
    "rot" should also be "dir", you're defining the direction you're shooting in.
     
    JoeStrout likes this.
  6. NidoAnxari

    NidoAnxari

    Joined:
    Jan 2, 2017
    Posts:
    86
    Following is the simplified prototype script.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class testAimLine_1 : MonoBehaviour
    6. {
    7.     public GameObject testObj;
    8.  
    9.     private void Update()
    10.     {
    11.         RaycastHit2D hit0 = Physics2D.Raycast(transform.position, transform.up);
    12.         Vector2 reflection = Vector2.Reflect(hit0.point, hit0.normal);
    13.  
    14.         RaycastHit2D hit1 = Physics2D.Raycast(hit0.point, reflection);
    15.  
    16.         testObj.transform.position = hit1.point;
    17.  
    18.         Debug.DrawLine(transform.position, hit0.point, Color.red);
    19.         Debug.DrawLine(hit0.point, hit1.point, Color.blue);
    20.     }
    21. }
    22.  
    This is the screenshot:
    https://i.imgur.com/xsoKv5B.png
    Red is the first line and blue should be the reflected line which is absent.
     
  7. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    Vector2.Reflect takes a direction of the original vector, not the collision point as the first argument.
    https://docs.unity3d.com/ScriptReference/Vector2.Reflect.html

    You can confirm of deny that the problem is in variable reflection by substituting it with some predefined value you know. If it works that way, then you are doing something wrong with Vector2.Reflect.
     
  8. BakeMyCake

    BakeMyCake

    Joined:
    May 8, 2017
    Posts:
    175
    I strongly advise you to learn how to debug your own code. As an answer to your other thread:
    https://forum.unity3d.com/threads/cant-produce-lines-using-line-renderer.484576/

    I plugged your code into a test scene and the problem is that the collision point from ray 1 is on the surface of the collider. That means you're firing your second ray into the same collider point blank. A quick solution I propose is to disable the collider of the originally hit body for the duration of the ray trace. Example code with hardcoded values(change them for your testing purposes):

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class test : MonoBehaviour
    6. {
    7.     LineRenderer lr;
    8.  
    9.     private void Start()
    10.     {
    11.         lr = gameObject.AddComponent<LineRenderer>();
    12.  
    13.         Vector3 start = new Vector2(0, -3.0f);
    14.  
    15.         RaycastHit2D hit0 = Physics2D.Raycast(start, new Vector3(-1.0f, 1.0f).normalized);
    16.         Vector2 reflection = Vector2.Reflect(new Vector3(-1.0f, 1.0f).normalized, hit0.normal);
    17.  
    18.         hit0.transform.gameObject.GetComponent<BoxCollider2D>().enabled = false;
    19.         RaycastHit2D hit1 = Physics2D.Raycast(hit0.point, reflection);
    20.         hit0.transform.gameObject.GetComponent<BoxCollider2D>().enabled = true;
    21.  
    22.         lr.material = new Material(Shader.Find("Sprites/Default"));
    23.  
    24.         Vector3[] positions = new Vector3[3];
    25.         positions[0] = start;
    26.         positions[1] = hit0.point;
    27.         positions[2] = hit1.point;
    28.  
    29.         lr.positionCount = positions.Length;
    30.         lr.SetPositions(positions);
    31.         lr.startColor = Color.red;
    32.         lr.endColor = Color.red;
    33.         lr.widthMultiplier = 0.2f;
    34.     }
    35. }
    Hope it helps