Search Unity

Creating portals

Discussion in 'Physics' started by FeastSC2, May 17, 2019.

  1. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    I'm creating portals like in the game Portal where a rigidbody comes in and gets expulsed with the same speed it entered the portal out of another portal (along its normal)

    The issue is that sometimes the velocity of my object is killed before entering my portal. I believe it's because my rigidbody is about to touch the ground next frame and have its velocity killed.

    I thought using OnTriggerEnter() or OnTriggerStay would work but it seems that the teleported rigidbody can sometimes have its velocity killed before triggering those functions.

    Below is the simple script that I use for my portals. I'm trying to keep the script simple, I know I could use raycasting with each that could enter the portal but I'd rather avoid it and keep things simple with OnTriggerStay/OnTriggerEnter.

    How can I make the portals call their teleport function on a rigidbody before it touches the ground and has its velocity killed?

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [RequireComponent(typeof(BoxCollider))]
    4. public class Mirror : MonoBehaviour
    5. {
    6.     public Mirror LinkedPortal;
    7.  
    8.     public BoxCollider Col { get; private set; }
    9.     public static Vector3 BoxSize = new Vector3(2f, 2.5f, .25f);
    10.  
    11.     void Awake()
    12.     {
    13.         Col = GetComponent<BoxCollider>();
    14.     }
    15.  
    16.     void OnTriggerEnter(Collider _collider)
    17.     {
    18.  
    19.         var rb = _collider.GetComponent<Rigidbody>();
    20.         if (rb != null)
    21.         {
    22.             TeleportRigidbody(rb);
    23.         }
    24.     }
    25.  
    26.     void OnTriggerStay(Collider _collider)
    27.     {
    28.         var rb = _collider.GetComponent<Rigidbody>();
    29.         if (rb != null)
    30.         {
    31.             TeleportRigidbody(rb);
    32.         }
    33.     }
    34.  
    35.     private void OnDrawGizmos()
    36.     {
    37.         Col = GetComponent<BoxCollider>();
    38.         Gizmos.color = Color.cyan;
    39.         Gizmos.DrawWireSphere(Col.bounds.center + transform.forward, .25f);
    40.     }
    41.  
    42.     private float AdditionalForce = 0f;
    43.     private float MinimumVelocityToBeAccepted = 4f;
    44.     private Vector3 ForceMultiplier = new Vector3(1f, 1f, 1f);
    45.  
    46.     public void TeleportRigidbody(Rigidbody _rb)
    47.     {
    48.         if (LinkedPortal != null)
    49.         {
    50.             var rbVel = _rb.velocity;
    51.             var dot = Vector3.Dot(rbVel, transform.forward);
    52.             var velocityTowardsMe = Vector3.Project(rbVel, transform.forward);
    53.             if (dot >= 0 || velocityTowardsMe.magnitude < MinimumVelocityToBeAccepted)
    54.             {
    55.                 Debug.Log("Not sufficient speed or direction of speed: " + rbVel);
    56.                 return; // the object is not trying to enter me with a sufficient speed
    57.             }
    58.  
    59.             _rb.position = LinkedPortal.transform.position;
    60.             _rb.velocity = LinkedPortal.transform.forward * rbVel.magnitude;
    61.         }
    62.     }
    63. }
    A video showing the behaviour of a sphere with a rigidbody between the 2 portals. When the downspeed is too great, the sphere has its velocity killed before triggering OnTriggerEnter of the portal.
     
    Last edited: May 17, 2019