Search Unity

Finding normals of points on a trigger collider border

Discussion in '2D' started by jacktjong17, Aug 16, 2019.

  1. jacktjong17

    jacktjong17

    Joined:
    Feb 24, 2018
    Posts:
    5
    So, I'm trying to make a script that allows me to create a collider, set it to trigger, and have that be the area that my player can walk on. When he leaves the trigger he gets pushed back into the area.

    I tried to achieve this with this line of code:
    Code (CSharp):
    1. Vector2 closestPoint;
    2. closestPoint = coll.ClosestPoint(new Vector2(player.transform.position.x, player.transform.position.y));
    3.  
    4. rb2d.velocity = new Vector2((player.transform.position.x - closestPoint.x) * bounceBack, (player.transform.position.y - closestPoint.y) * bounceBack);
    This sadly doesn't work because when the player leaves the trigger the closestPoint IS the player's position. That causes the velocity to be set to 0 instead of creating a pushback effect.

    Now I wanted to find the normal of the closestPoint so that I can create a pushback effect from that, but these points don't seem to hold a normal value, and using contact points isn't an option because I'm using a trigger.

    If anyone has a way to find a useful normal here, or if anyone just has a better way of getting the outcome I'm looking for, I'd love to hear.
     
    Last edited: Aug 16, 2019
  2. jeffreyschoch

    jeffreyschoch

    Joined:
    Jan 21, 2015
    Posts:
    2,558
    This sounded like it would be fun to mess around with, so this is what I came up with:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class WalkableArea : MonoBehaviour
    4. {
    5.     public float strength;
    6.     public Rigidbody2D heldPlayerRigidbody;
    7.     public Collider2D heldPlayerCollider;
    8.     public bool playerStartsInside;
    9.  
    10.     private Collider2D _trigger;
    11.     private bool _playerInside;
    12.  
    13.     private void Awake()
    14.     {
    15.         _trigger = GetComponent<Collider2D>();
    16.     }
    17.  
    18.     private void Start()
    19.     {
    20.         _playerInside = playerStartsInside;
    21.     }
    22.  
    23.     private void FixedUpdate()
    24.     {
    25.         if(!_playerInside)
    26.         {
    27.             // get the smallest distance between this trigger and the player
    28.             ColliderDistance2D distance = _trigger.Distance(heldPlayerCollider);
    29.  
    30.             // push the player towards the closest point, increasing force as distance increases
    31.             heldPlayerRigidbody.AddForce(distance.normal * distance.distance * strength * Time.deltaTime);
    32.         }
    33.     }
    34.  
    35.     private void OnTriggerEnter2D(Collider2D other)
    36.     {
    37.         Player player = other.GetComponent<Player>();
    38.         if (player != null)
    39.         {
    40.             _playerInside = true;
    41.         }
    42.     }
    43.  
    44.     private void OnTriggerExit2D(Collider2D other)
    45.     {
    46.         Player player = other.GetComponent<Player>();
    47.         if (player != null)
    48.         {
    49.             _playerInside = false;
    50.         }
    51.     }
    52. }
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Player : MonoBehaviour
    4. {
    5.     public float acceleration;
    6.     public Rigidbody2D rb2D;
    7.  
    8.     private Vector2 input;
    9.  
    10.     private void Update()
    11.     {
    12.         input = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
    13.     }
    14.  
    15.     private void FixedUpdate()
    16.     {
    17.         rb2D.AddForce(input * acceleration * Time.deltaTime);
    18.     }
    19. }
     

    Attached Files:

  3. jacktjong17

    jacktjong17

    Joined:
    Feb 24, 2018
    Posts:
    5
    That works pretty well. It is a bit annoying that the push back only kicks in once you're quite a bit outside of the trigger, but other than that it works well. But after some more searching I actually found a solution to the problem I was trying to circumvent with this method. I wanted a solid feeling collider border that didn't rely on overlapping colliders in order to be closed up, but thanks to the composite collider I can do that now and there'll be no overlap in the end. So I'm gonna stick with the easy way of using colliders to mark the places where you're not allowed to walk after all.
     
    jeffreyschoch likes this.
  4. jeffreyschoch

    jeffreyschoch

    Joined:
    Jan 21, 2015
    Posts:
    2,558
    Just for posterity, you could shrink the trigger size so that it kicks in sooner. Glad you found a solution you're happy with!