Search Unity

Portal Physics

Discussion in 'Scripting' started by Pantomorphic, Nov 19, 2014.

  1. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    I'm making sort of a portal clone. When the player hits one of the portals I have a script that makes the player's transform.position equal to the other portal's transform.position. The problem is that if the player had momentum going into one of the portals, that momentum will be lost when it comes out the other. Could I get a script that would make it so that the player will come out (or teleport) with the same momentum it had going in?
     
  2. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    You could try getting the player's rigidbody velocity as it enters the portal and then add it again in the new position.

    You'd need to adjust the velocity based on any direction change, though. For example, if the player was walking straight along the Z-axis (0, 0, 1) and you wanted it to appear as though you were walking out of a portal on the same wall, the new velocity would need to be (0, 0, -1) - back in the direction you were coming from.

    That's a very simple solution. I've no doubt there would be a million and one problems doing it that way!
     
  3. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    Thats another problem though. The player's rotation is also not relative to the portal it's coming out of. If the player was facing a certain way going in, it will be facing the same way coming out.
     
  4. Cpt Chuckles

    Cpt Chuckles

    Joined:
    Dec 31, 2012
    Posts:
    86
    you could get the difference in orientation by doing
    Code (csharp):
    1. Quaternion newRotation = Quaternion.FromToRotation(player.transform.forward, portal.transform.forward);
    and use that to adjust both the orientation of the player as well as the velocity
    Code (csharp):
    1. transform.rotation *= newRotation; //turn the player's orientation
    2. rigidbody.velocity = newRotation * velocity; //transform the velocity
     
  5. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    Here is my current code:
    Code (CSharp):
    1. player.transform.position = otherPortal.transform.position;
    2. Quaternion newRotation = Quaternion.FromToRotation(player.transform.forward, otherPortal.transform.forward);
    3. player.transform.rotation *= newRotation;
    4. rigidbody.velocity = newRotation * velocity;
    It still only changes the transform.position and it gives me an error saying "the name 'velocity' does not exist in the current context. The script attached to the Portal object, not the player.
     
    Last edited: Nov 19, 2014
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I'm just brainstorming here, but it seems to me you should, upon entry, get the orientation and velocity of the object in the portal's local coordinate system. E.g., use Transform.TransformDirection on the player's velocity, forward vector, and up vector. Then on the way out, use the inverse methods (e.g. InverseTransformDirection) to convert back into world space, relative to the second portal.
     
  7. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    Alright so I found that the problem was in the player movement script. Now the player does have velocity coming out of the portal, but that velocity isn't relative to the portal. If you enter a portal with downward motion, you will still have that downward motion as you come out. If you enter a portal looking to the left, you will still be looking to the left as you come out.
     
  8. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    I've not read this thread closely, but theoretically you should just store the speed of the player (length of velocity vector) when you enter a portal, then set the players new velocity as the new portals forward facing vector * speed
     
  9. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    @Pantomorphic, if that happens then you're not following my suggestion. :) The downward motion when you enter a portal should get converted to a velocity relative to that portal, and then converted from a portal-relative velocity (with respect to the output portal) back into the proper world velocity when you come out.

    @A.Killingbeck, your approach would always have you coming straight out of the portal. That's not quite how portals are supposed to work; if you jump in at an angle, you should come out at an angle.
     
  10. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    What do you mean? A portal isn't a real thing, how do you know how it works? Or am I missing something?
     
  11. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    Not sure why you're guessing when they did several articles on how they got it to work in the game around its release...

    Try looking at Gamasutra's "Portal Demystified" article
     
    JoeStrout likes this.
  12. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    @A.Killingbeck, it sounds to me like the OP is trying to mimic the behavior of the portals in the game Portal. Maintaining your velocity relative to the input and output sides is an important feature of the portals in that game, without which many of the puzzles would be unsolvable.
     
  13. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    Oh! I didn't realise it was already a game. I didn't even read the part about it being a portal clone in OP's post. My bad. Ha.
     
  14. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    Here is my code:
    Code (CSharp):
    1. public GameObject otherPortal;
    2. public GameObject cameraObject;
    3.  
    4. void OnTriggerEnter(Collider other)
    5. {
    6. if (other.tag == "Player")
    7. {
    8. other.transform.position = otherPortal.transform.position;
    9. cameraObject.transform.rotation = otherPortal.transform.rotation;
    10. }
    11. }
    The reason I use a camera object for the rotation is because the player rigid body's rotation is locked. For some reason the rotation never changes when you walk through a portal, even if I set it to (0,0,0) As it is, I'm not sure how I would implement your code @JoeStrout
     
  15. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    OK, well I don't think I can write the whole thing out of my head, but let's start with position: you shouldn't come out the center of the portal, you should come out whatever position within the portal you popped in, so:

    Code (csharp):
    1.   Vector3 localPos = transform.InverseTransformPoint(other.transform.position);
    2.    other.transform.position = otherPortal.TransformPoint(localPos);
    So this takes the world position of the object, and converts into coordinates local to the portal. Then we convert those local coordinates back to world coordinates, relative to the other portal.

    Rotation is a little trickier. What you need to do is transform the forward and up vectors, something like:

    Code (csharp):
    1.   Vector3 localUp = transform.InverseTransformDirection(cameraObject.transform.up);
    2.    Vector3 localForward = transform.InverseTransformDirection(camera.transform.forward);
    3.    cameraObject.transform.rotation.SetLookRotation(otherPortal.TransformDirection(localForward),
    4.         otherPortal.TransformDirection(localUp));
    Hopefully this gets you going in the right direction (har har, see what I did there)!
     
  16. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    It still doesn't work for some reason. The rotation just never changes. I fiddled around and not even setting the camera's rotation to (0,0,0) works! The player object nor the camera rotate at all. Also, two errors come up. One says "UnityEngine.GameObject does not contain a definition for 'TransformPoint'" and the other says the same thing but with 'TransformDirection' instead.
     
  17. GetUpKidAK

    GetUpKidAK

    Joined:
    Apr 9, 2013
    Posts:
    84
    TransformPoint and TransformDirection are called on transforms, not gameObjects.
     
  18. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    What could be the problem with the camera not rotating at all? No matter what I put after 'cameraObject.transform.rotation =' it never rotates at all.
     
  19. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Could it be some other script that sets the rotation of the camera on every frame?
     
  20. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    Oh that could be the problem. Not sure how to fix it.
     
  21. Skorn

    Skorn

    Joined:
    Oct 31, 2014
    Posts:
    22
    What's the current script that you have/are working on? Not sure what you're trying to work on exactly. The character enters the portal but doesn't come out in the exact direction they're facing or does the camera not adjust accordingly?
     
  22. Pantomorphic

    Pantomorphic

    Joined:
    May 8, 2013
    Posts:
    53
    I have a mouse look script and a script for when the player collides with the portal. The problem is that when the player goes through the portal, the rotation and velocity it had is the same when it comes out. I need it to be relative to the rotation of the portal it comes out of. Whenever I make a script that affects the rotation of the player or the camera, nothing happens.