Search Unity

Getting Rigidbody2D's vector and using its values

Discussion in '2D' started by SolarPetal, Dec 20, 2017.

  1. SolarPetal

    SolarPetal

    Joined:
    Nov 7, 2015
    Posts:
    11
    Hi,

    My problem is:
    The game I am making is a replica of Tron's Light Cycles where an object constantly moves in one direction. I already have that part covered but my problem IS if I change the Speed value with a Boost, the effect will only take place AFTER the player changes direction.

    What I am doing:
    Moving a Rigidbody2D Up Down Left and Right by getting its velocity and changing it by Vector2.up * speed, Vector2.down * speed etc... for each direction like this:
    Code (CSharp):
    1. if (Input.GetKeyDown(upKey)) {
    2.  
    3.         GetComponent<Rigidbody2D>().velocity = Vector2.up * speed;
    4.  
    5.     }
    6.  
    7.            else if (Input.GetKeyDown(downKey)) {
    8.  
    9.             GetComponent<Rigidbody2D>().velocity = -Vector2.up * speed;
    10.     }

    What I would like to do:
    Only change the Vector2 on each key press and constantly (in void Update) change the Rigidbody's velocity to the current values of Vector2 and multiply them by the speed.
    Something that would look like this :
    Code (CSharp):
    1. void Update()
    2. {
    3.       GetComponent<Rigidbody2D>().velocity = Vector2(CURRENT VALUES) * speed;
    4.  
    5.       if (Input.GetKeyDown(downKey))
    6.      {
    7.          GetComponent<Rigidbody2D>().Vector2 = -Vector2.up
    8.      }
    9. }
    So that the Vector2 direction will change and the speed will be set by the code placed outside of the "if" condition.
    I'm sorry if I don't make sense I can try to explain better English isn't my first language.

    Thank you for taking the time!
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    How about something like this, which updates the velocity any time the direction or speed is changed using properties:
    Code (CSharp):
    1. using UnityEngine;
    2. public class Example : MonoBehaviour
    3. {
    4.     [SerializeField] private float speed;
    5.     [SerializeField] private KeyCode upKey;
    6.     [SerializeField] private KeyCode downKey;
    7.     [SerializeField] private KeyCode leftKey;
    8.     [SerializeField] private KeyCode rightKey;
    9.  
    10.     private Rigidbody2D rigidbodyComponent;
    11.     private Vector2 direction;
    12.  
    13.     public float Speed
    14.     {
    15.         get { return speed; }
    16.         set
    17.         {
    18.             if(value != speed)
    19.             {
    20.                 speed = value;
    21.                 UpdateVelocity();
    22.             }
    23.         }
    24.     }
    25.  
    26.     public Vector2 Direction
    27.     {
    28.         get { return direction; }
    29.         set
    30.         {
    31.             if(value != direction)
    32.             {
    33.                 direction = value.normalized;
    34.                 UpdateVelocity();
    35.             }
    36.         }
    37.     }
    38.  
    39.     private void Awake()
    40.     {
    41.         rigidbodyComponent = GetComponent<Rigidbody2D>();
    42.     }
    43.  
    44.     private void UpdateVelocity()
    45.     {
    46.         rigidbodyComponent.velocity = direction * speed;
    47.     }
    48.  
    49.     private void Update()
    50.     {
    51.         if(Input.GetKeyDown(upKey))
    52.         {
    53.             direction = Vector2.up;
    54.         }
    55.         else if(Input.GetKeyDown(downKey))
    56.         {
    57.             direction = Vector2.down;
    58.         }
    59.         else if(Input.GetKeyDown(leftKey))
    60.         {
    61.             direction = Vector2.left;
    62.         }
    63.         else if(Input.GetKeyDown(rightKey))
    64.         {
    65.             direction = Vector2.right;
    66.         }
    67.     }
    68. }

    Your boost pickup could then change the Speed property, causing a velocity update.
     
    SolarPetal likes this.
  3. SolarPetal

    SolarPetal

    Joined:
    Nov 7, 2015
    Posts:
    11
    Thank you so much! It works perfectly, now I am quite unfamiliar with using these so would you mind explaining what exactly does the "value.normalized" in the "public Vector2 Direction" please?

    Now my second concern is that although the velocity change works great and I can change direction with the Key presses, the trail left behind the player does something quite weird :



    My full script for the player's movements and trail creation is the following, would there be a conflict between the direction vector and the player's velocity vector?
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Move : MonoBehaviour {
    6.  
    7.         //Custom controls
    8.         public KeyCode upKey, downKey, rightKey, leftKey;
    9.  
    10.         //Ligh trail
    11.         public GameObject wallPrefab;
    12.  
    13.         public Collider2D trail;
    14.  
    15.         //Postion where square wall ends
    16.         private Vector2 lastWallEnd;
    17.  
    18.         public float speed;
    19.  
    20.         public Boost hitBoost;
    21.  
    22.         public Rigidbody2D playerRigid;
    23.  
    24.         Vector2 direction;
    25.  
    26.  
    27.  
    28.     // Use this for initialization
    29.     void Start () {
    30.  
    31.         playerRigid = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody2D>();
    32.         hitBoost = GameObject.FindGameObjectWithTag("Boost").GetComponent<Boost>();
    33.         direction = Vector2.up;
    34.         spawnTrail();
    35.  
    36.     }
    37.  
    38.     IEnumerator disableBoost() {
    39.         yield return new WaitForSecondsRealtime(5);
    40.     }
    41.  
    42.     void UpdateVelocity() {
    43.  
    44.         playerRigid.velocity = direction * speed;
    45.  
    46.     }
    47.  
    48.     public float Speed {
    49.  
    50.         get { return speed; }
    51.         set {
    52.             if (value != speed) {
    53.                 speed = value;
    54.                 UpdateVelocity();
    55.             }
    56.         }
    57.     }
    58.  
    59.     public Vector2 Direction {
    60.  
    61.         get { return direction; }
    62.         set {
    63.             if (value != direction) {
    64.                 direction = value.normalized;
    65.                 UpdateVelocity();
    66.                 }
    67.             }
    68.       }
    69.  
    70.  
    71.     // Update is called once per frame
    72.         void Update() {
    73.  
    74.         print(direction);
    75.         UpdateVelocity();
    76.  
    77.         if(Input.GetKeyDown(upKey))
    78.         {
    79.             direction = Vector2.up;
    80.         }
    81.         else if(Input.GetKeyDown(downKey))
    82.         {
    83.             direction = -Vector2.up;
    84.         }
    85.         else if(Input.GetKeyDown(leftKey))
    86.         {
    87.             direction = Vector2.left;
    88.         }
    89.         else if(Input.GetKeyDown(rightKey))
    90.         {
    91.             direction = -Vector2.left;
    92.         }
    93.  
    94.         fitColliderBetween(trail, lastWallEnd, transform.position);
    95.  
    96.     }
    97.  
    98.     void OnTriggerEnter2D(Collider2D col) {
    99.  
    100.     // Not the current wall?
    101.            if (col != trail && col != hitBoost.boostCol) {
    102.  
    103.             print("Player lost:" + name);
    104.  
    105.             Destroy(gameObject);
    106.    }
    107. }
    108.  
    109.   void spawnTrail () {
    110.  
    111.     lastWallEnd = transform.position;
    112.  
    113.     GameObject g = (GameObject)Instantiate(wallPrefab, transform.position, Quaternion.identity);
    114.  
    115.     //User manually choses the trail prefab
    116.     trail = g.GetComponent<Collider2D>();
    117.  
    118.   }
    119.  
    120.     void fitColliderBetween(Collider2D col, Vector2 a, Vector2 b) {
    121.  
    122.         //Calculates the Center Position between the last 2 squares instantiated
    123.  
    124.     col.transform.position = a + (b - a) * 0.5f;
    125.  
    126.            //Scales it accordingly (horizontally or vertically)
    127.  
    128.     float dist = Vector2.Distance(a, b);
    129.  
    130.     if (a.x != b.x){
    131.         col.transform.localScale = new Vector2(dist + 1, 1);
    132.     }
    133.  
    134.     else {
    135.         col.transform.localScale = new Vector2(1, dist + 1);
    136.     }
    137.   }
    138. }
    Thank you for helping really that was quick and really helpful.
     
  4. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    If you think of a Vector as a line connecting the origin (0,0,0) and the Vector, Normalizing shortens that line until it is 1 unit long. It still points in the same direction, but being length 1 is useful for multiplication. For instance, you could multiply a "direction" by a "distance", and that will result in a point that is "distance" units away in that "direction".

    Vector3.up, Vector3.down, etc, are all normalized vectors, pointing in those directions with a length of 1.

    So to move something 100 units to the right:
    Code (CSharp):
    1. Vector3 newPosition = transform.position + (Vector3.right * 100);
    2. transform.position = newPosition;
    Any normalized vector can be used in the way I used "Vector3.right".

    So by making the property "public Vector2 Direction" I'm implying that this vector represents a direction, which is generally assumed to be normalized for use as such.

    With properties, you can write a "get" and "set" method inside them. I'm using the "set" method to enforce the normalization of the direction. The property "Direction" will always be normalized, because any time you set it the value gets normalized by "direction = value.normalized" where "value" is the new incoming vector.

    Just make sure you're using "Direction" and not "direction".


    It looks like you want to create a new trail every time you change directions. So you could add a call to "spawnTrail()" just after "UpdateVelocity" in the "Direction" property.

    However, for organization it's probably best to do something like this, where I've added methods to handle a Speed change, and another method to handle a Direction change. That way you can respond to each change as you want. In this case, you also want to spawn a new trail every time the direction changes. See if this works better:
    Code (CSharp):
    1. edited: bugs in code, see below
     
    Last edited: Dec 21, 2017
    SolarPetal likes this.
  5. SolarPetal

    SolarPetal

    Joined:
    Nov 7, 2015
    Posts:
    11
    Ah I understand now this makes a lot of sense in this case. I see what you did with the code that's much more logical and organised, thank you so much.
    My problems still persists but I've identified it more clearly. Before, every time the player would change direction a new "Light Trail" prefab would be instantiated and then rescaled accordingly depending on the player's position.
    What's happening now is only 1 instance of the light trail is created and it is not being instantiated another time after each direction change.
    I fail to understand why though because obviously the function is explicitly called "onDirectionChanged".

    Code (CSharp):
    1. void spawnTrail() {
    2.         lastWallEnd = transform.position;
    3.         GameObject g = (GameObject)Instantiate(wallPrefab, transform.position, Quaternion.identity);
    4.         //The Collider2D gets chosen from the new instantiated light trail "wall".
    5.         trail = g.GetComponent<Collider2D>();
    6.     }
    And here are the two screenshots of the player object in-editor and in-game, everything is fine:
    Screen Shot 2017-12-20 at 19.49.58.png

    Screen Shot 2017-12-20 at 19.50.05.png

    I've tried fiddling around with this and found a weird phenomenon.
    I've made each key press call the "spawnTrail" function and this is what happens now:
    Code (CSharp):
    1.    void Update() {
    2.         print(direction);
    3.         UpdateVelocity();
    4.         if(Input.GetKeyDown(upKey)) {
    5.             direction = Vector2.up;
    6.             spawnTrail();
    7.         } else if(Input.GetKeyDown(downKey)) {
    8.             direction = -Vector2.up;
    9.             spawnTrail();
    10.         } else if(Input.GetKeyDown(leftKey)) {
    11.             direction = Vector2.left;
    12.             spawnTrail();
    13.         } else if(Input.GetKeyDown(rightKey)) {
    14.             direction = -Vector2.left;
    15.             spawnTrail();
    16.         }
    17.         fitColliderBetween(trail, lastWallEnd, transform.position);
    18.     }


    What's happening in this video is the new trails are being correctly instantiated when I turn left and right.
    But when I go up and down, no trail is instantiated until I press the Up or Down key a second time.

    I'm really having a hard time figuring this one out.

    Also even if this works for turning left and right, the trail is slightly off compared to the player's pixel, and returns to the correct position on second press.

    Thank you so much for taking the time to help me on that case. I'm learning a lot from what you explained and gave me.
     
    Last edited: Dec 21, 2017
  6. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Okay, this one may be my fault. In the code I gave you, I'm using "direction" instead of "Direction". Setting the value of "Direction" will use the 'set' method of the property, thus calling "onDirectionChanged", while using "direction" will directly assign the variable. Same goes for 'speed' and "Speed".

    So try this:
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4. public class Move : MonoBehaviour {
    5.  
    6.     //Custom controls
    7.     public KeyCode upKey, downKey, rightKey, leftKey;
    8.  
    9.     //Light trail
    10.     public GameObject wallPrefab;
    11.     [SerializeField] private float speed; // keep this private because 'Speed' should be used instead
    12.     public Boost hitBoost;
    13.  
    14.     //Postion where square wall ends
    15.     private Vector2 lastWallEnd;
    16.     private Collider2D trail;
    17.     private Vector2 direction;
    18.     private Rigidbody2D playerRigid;
    19.  
    20.     public float Speed {
    21.         get { return speed; }
    22.         set {
    23.             if(value != speed) {
    24.                 speed = value;
    25.                 onSpeedChanged();
    26.             }
    27.         }
    28.     }
    29.  
    30.     public Vector2 Direction {
    31.         get { return direction; }
    32.         set {
    33.             if(value != direction) {
    34.                 direction = value.normalized;
    35.                 onDirectionChanged();
    36.             }
    37.         }
    38.     }
    39.  
    40.  
    41.     // Use this for initialization
    42.     void Start() {
    43.         playerRigid = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody2D>();
    44.         hitBoost = GameObject.FindGameObjectWithTag("Boost").GetComponent<Boost>();
    45.         Direction = Vector2.up;
    46.         spawnTrail();
    47.     }
    48.  
    49.     IEnumerator disableBoost() {
    50.         yield return new WaitForSecondsRealtime(5);
    51.     }
    52.  
    53.     void UpdateVelocity() {
    54.         playerRigid.velocity = Direction * Speed;
    55.     }
    56.  
    57.     // Update is called once per frame
    58.     void Update() {
    59.         print(Direction);
    60.  
    61.         if(Input.GetKeyDown(upKey)) {
    62.             Direction = Vector2.up;
    63.         } else if(Input.GetKeyDown(downKey)) {
    64.             Direction = Vector2.down;
    65.         } else if(Input.GetKeyDown(leftKey)) {
    66.             Direction = Vector2.left;
    67.         } else if(Input.GetKeyDown(rightKey)) {
    68.             Direction = Vector2.right;
    69.         }
    70.  
    71.         fitColliderBetween(trail, lastWallEnd, transform.position);
    72.     }
    73.  
    74.     void OnTriggerEnter2D(Collider2D col) {
    75.  
    76.         // Not the current wall?
    77.         if(col != trail && col != hitBoost.boostCol) {
    78.  
    79.             print("Player lost:" + name);
    80.  
    81.             Destroy(gameObject);
    82.         }
    83.     }
    84.  
    85.     void spawnTrail() {
    86.  
    87.         lastWallEnd = transform.position;
    88.  
    89.         GameObject g = Instantiate(wallPrefab, transform.position, Quaternion.identity);
    90.  
    91.         //User manually choses the trail prefab
    92.         trail = g.GetComponent<Collider2D>();
    93.  
    94.     }
    95.  
    96.     void fitColliderBetween(Collider2D col, Vector2 a, Vector2 b) {
    97.  
    98.         //Calculates the Center Position between the last 2 squares instantiated
    99.  
    100.         col.transform.position = Vector2.Lerp(a, b, 0.5f);
    101.  
    102.         //Scales it accordingly (horizontally or vertically)
    103.  
    104.         float dist = Vector2.Distance(a, b);
    105.  
    106.         if(a.x != b.x) {
    107.             col.transform.localScale = new Vector2(dist + 1, 1);
    108.         } else {
    109.             col.transform.localScale = new Vector2(1, dist + 1);
    110.         }
    111.     }
    112.  
    113.     private void onDirectionChanged() {
    114.         UpdateVelocity();
    115.         spawnTrail();
    116.     }
    117.  
    118.     private void onSpeedChanged() {
    119.         UpdateVelocity();
    120.     }
    121. }

    I'm happy to help. Thank you for using code tags and providing screenshots and video.
     
    SolarPetal likes this.
  7. SolarPetal

    SolarPetal

    Joined:
    Nov 7, 2015
    Posts:
    11
    Ah it works now! The trail is smoothly instantiated and the previous error doesn't happen anymore.
    I hate to say this but once again, fixing something has broken another one.
    The player can move around with the trail correctly only if I delete the part of the code taking care of the the collision with the trail.

    In other words, the player instantly dies if this part of the code exists :
    Code (CSharp):
    1.  void OnTriggerEnter2D(Collider2D col) {
    2.         // Not the current wall?
    3.         if(col != trail && col != hitBoost.boostCol) {
    4.             print("Player lost:" + name);
    5.             Destroy(gameObject);
    6.         }
    7.     }
    I tried placing this piece of code of the Trail Prefab Script instead like this :

    public Collider2D playerCol;

    void Start()
    {
    playerCol = gameObject.GetComponent<Collider2D>();
    }

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class WallDeath : MonoBehaviour {
    6.  
    7.     public Move player;
    8.  
    9.     // Use this for initialization
    10.     void Start ()
    11.    {
    12.         player = GameObject.FindGameObjectWithTag("Player").GetComponent<Move>();
    13.     }
    14.    
    15.     // Update is called once per frame
    16.     void Update () {
    17.  
    18.     }
    19.  
    20.     void OnTriggerEnter2D(Collider2D col) {
    21.         // Not the current wall?
    22.         if(col != player.playerCol) {
    23.             print("Player lost:" + player.name);
    24.          //   Destroy(player.gameObject);
    25.         }
    26.     }
    27. }
    28.  

    But the results were worse, instead of taking .5 seconds to die the player dies on the first frame.

    At this point I should simply figure it out myself but you seem to understand it way better than I do, so if it appears obvious to you I would gladly abuse of your help for a little longer but I wouldn't want to ask too much.

    Here is the full code of the Move script just because I deleted a useless IEnumerator and re-arranged some comments.
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. public class Move : MonoBehaviour {
    4.     //Custom controls
    5.     public KeyCode upKey, downKey, rightKey, leftKey;
    6.     //Light trail
    7.     public GameObject wallPrefab;
    8.     [SerializeField] private float speed; // keep this private because 'Speed' should be used instead
    9.     public Boost hitBoost;
    10.     //Postion where square wall ends
    11.     private Vector2 lastWallEnd;
    12.  
    13.     public Collider2D playerCol;
    14.     public Collider2D trail;
    15.     private Vector2 direction;
    16.     private Rigidbody2D playerRigid;
    17.     public float Speed {
    18.         get { return speed; }
    19.         set {
    20.             if(value != speed) { //If the Speed value is different than the speed, calls the following function
    21.                 speed = value;
    22.                 onSpeedChanged();
    23.             }
    24.         }
    25.     }
    26.     public Vector2 Direction {
    27.         get { return direction; }
    28.         set {
    29.             if(value != direction) { //If the direction isn't equal to Direction's value anymore, calls for the following function
    30.                 direction = value.normalized;
    31.                 onDirectionChanged();
    32.             }
    33.         }
    34.     }
    35.     // Use this for initialization
    36.     void Start() {
    37.  
    38.         playerCol = gameObject.GetComponent<Collider2D>();
    39.         playerRigid = GameObject.FindGameObjectWithTag("Player").GetComponent<Rigidbody2D>();
    40.         hitBoost = GameObject.FindGameObjectWithTag("Boost").GetComponent<Boost>();
    41.         Direction = Vector2.up;
    42.         spawnTrail();
    43.     }
    44.     void UpdateVelocity() {
    45.         playerRigid.velocity = Direction * Speed;
    46.     }
    47.     // Update is called once per frame
    48.     void Update() {
    49.  
    50.         print(Direction);
    51.         if(Input.GetKeyDown(upKey)) {
    52.             Direction = Vector2.up;
    53.         } else if(Input.GetKeyDown(downKey)) {
    54.             Direction = Vector2.down;
    55.         } else if(Input.GetKeyDown(leftKey)) {
    56.             Direction = Vector2.left;
    57.         } else if(Input.GetKeyDown(rightKey)) {
    58.             Direction = Vector2.right;
    59.         }
    60.         fitColliderBetween(trail, lastWallEnd, transform.position);
    61.     }
    62.  
    63.     void spawnTrail() {
    64.         lastWallEnd = transform.position;
    65.         GameObject g = Instantiate(wallPrefab, transform.position, Quaternion.identity);
    66.         //Trail collider gets updated with the newt instantiated one.
    67.         trail = g.GetComponent<Collider2D>();
    68.     }
    69.  
    70.     void OnTriggerEnter2D(Collider2D col) {
    71.         // Not the current wall?
    72.         if(col != trail && col != hitBoost.boostCol) {
    73.             print("Player lost:" + name);
    74.             Destroy(gameObject);
    75.         }
    76.     }
    77.     void fitColliderBetween(Collider2D col, Vector2 a, Vector2 b) {
    78.         //Calculates the Center Position between the last 2 squares instantiated
    79.         col.transform.position = Vector2.Lerp(a, b, 0.5f);
    80.         //Scales it accordingly (horizontally or vertically)
    81.         float dist = Vector2.Distance(a, b);
    82.         if(a.x != b.x) {
    83.             col.transform.localScale = new Vector2(dist + 1, 1);
    84.         } else {
    85.             col.transform.localScale = new Vector2(1, dist + 1);
    86.         }
    87.     }
    88.     private void onDirectionChanged() {
    89.         spawnTrail();
    90.         UpdateVelocity();
    91.     }
    92.     private void onSpeedChanged() {
    93.         UpdateVelocity();
    94.     }
    95. }
     
  8. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    So you're seeing "Player lost" printed into the console immediately? You should be able to debug this by first seeing why the condition in OnTriggerEnter2D is true when it shouldn't be.

    Print out some more info to the console to see which part isn't working correctly.
    Code (CSharp):
    1. void OnTriggerEnter2D(Collider2D col) {
    2.     // Not the current wall?
    3.     if(col != trail && col != hitBoost.boostCol) {
    4.         Debug.LogFormat("{0} detected {1} inside the trigger, current trail is {2}",
    5.             gameObject,
    6.             col.gameObject,
    7.             trail.gameObject);
    8.  
    9.         print("Player lost:" + name);
    10.         Destroy(gameObject);
    11.     }
    12. }
    Then also print something out when you spawn a new trail. That way you can see what order things are happening, and which pieces of data don't match what you expect.
    Code (CSharp):
    1. void spawnTrail() {
    2.     lastWallEnd = transform.position;
    3.     GameObject g = Instantiate(wallPrefab, transform.position, Quaternion.identity);
    4.  
    5.     // give the gameobject a unique name, so it's easy to identify among many trails
    6.     g.name += g.GetInstanceID();
    7.  
    8.     //Trail collider gets updated with the newt instantiated one.
    9.     trail = g.GetComponent<Collider2D>();
    10.  
    11.     Debug.LogFormat("Spawned new trail: {0}", trail.gameObject);
    12. }
     
  9. SolarPetal

    SolarPetal

    Joined:
    Nov 7, 2015
    Posts:
    11
    Ah the thing was that I was calling "spawnTrail()" in the "Start()" function right after the script gave the initial "Direction", while changing the Direction already called the spawnTrail() function therefore 2 trails were spawned and the player would collide with the one instantiated in the Start() function.
    I removed the spawnTrail() line in the Start() function and it now works.

    It's incredible how much I learn from what you give me right now. Player death on trail collision now works fine, the new issue that came up was that when I placed multiple Boosts in the game, the player would only be able to actually get the Boost with 1 of the GameObjects and would otherwise die on collision with the others.

    I am having trouble to explain with words so I will comment the following code:
    Code (CSharp):
    1. // I want to get the Boost script from a Boost object in the game in order to get its Collider2D and allow the player to stay alive on collision with a GameObject with the Boost component
    2.     public Boost hitBoost;
    3.     public Collider2D playerCol;
    4.     public Collider2D trail;
    5.  
    6.  
    7.     // Use this for initialization
    8.     void Start() {
    9. // I retrieve the Boost script from 1 GameObject with the tag "Boost" but this only chooses at random 1 of the multiple Boost GameObjects in the scene
    10.         hitBoost = GameObject.FindObjectWithTag("Boost").GetComponent<Boost>();
    11.     }
    12.     void OnTriggerEnter2D(Collider2D col) {
    13.     // If the player isn't colliding with the currently scaled trail AND the Collider2D of the 1 Boost GameObject retrieved in the Start() function, the player dies. Therefore the player would die on every Boost GameObject except 1 at random.
    14.     if(col != trail && col != hitBoost.boostCol) {
    15.         Debug.LogFormat("{0} detected {1} inside the trigger, current trail is {2}",
    16.             gameObject,
    17.             col.gameObject,
    18.             trail.gameObject);
    19.  
    20.         manager.Death();
    21.         print("Player lost:" + name);
    22.         Destroy(gameObject);
    23.     }
    24. }
    Code (CSharp):
    1. void OnTriggerEnter2D(Collider2D col) {
    2.     // I am retrieving the Collider2D from the object the player is colliding with, thus if that object doesn't have the Boost script component (and isn't the last instantiated trail) the player dies.
    3.         hitBoost = col.gameObject.GetComponent<Boost>();
    4.     if(col != trail && col != hitBoost.boostCol) {
    5.         Debug.LogFormat("{0} detected {1} inside the trigger, current trail is {2}",
    6.             gameObject,
    7.             col.gameObject,
    8.             trail.gameObject);
    9.  
    10.         manager.Death();
    11.         print("Player lost:" + name);
    12.         Destroy(gameObject);
    13.     }

    I actually found out how to fix this while writing this, explaining in correct terms what is wrong and the reason why it is happening really helps to find a solution.
    I cannot thank you enough for taking the time, I feel like everything I've just learned is going to be useful in any project as the code you gave me can be applied in multiple situations, and making debug.logs is actually crucial for understanding one's own program.

    Thank you once again, I will eventually get back to you if I'm having any other issues that I don't know how to fix but I will apply what I've learned here in future cases.

    EDIT:
    I talked too fast, this does not work at all I did not fix anything. Player doesn't die on collision with the trail anymore and the Editor gives me the error :
    "NullReferenceException: Object reference not set to an instance of an object
    Move.OnTriggerEnter2D (UnityEngine.Collider2D col) (at Assets/Scripts/Move.cs:93)"

    line 93 being of course : " if(col != trail && col != hitBoost.boostCol) {}"

    The player does get the ability to survive the Boosts and gets the speed change but collision with the trail or side barriers doesn't affect him anymore.
     
    Last edited: Dec 23, 2017
  10. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    You need to check if "hitBoost" is not null before trying to access "boostCol". Anytime you use GetComponent, it could come back null, so check it first.

    ie:
    Code (CSharp):
    1. void OnTriggerEnter2D(Collider2D col) {
    2.     hitBoost = col.GetComponent<Boost>();
    3.  
    4.     // the collider has a boost component
    5.     // the collider is not the boost component's configured "boostCol"
    6.     // the collider is not the current trail
    7.     if(hitBoost != null && col != hitBoost.boostCol && col != trail) {
    8.  
    9.         Debug.LogFormat("{0} detected {1} inside the trigger, current trail is {2}",
    10.             gameObject,
    11.             col.gameObject,
    12.             trail.gameObject);
    13.  
    14.         manager.Death();
    15.         print("Player lost:" + name);
    16.         Destroy(gameObject);
    17.     }
    18. }
     
    Last edited: Jan 2, 2018