Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

First Person Teleporting?

Discussion in 'Scripting' started by BigSquare, Dec 4, 2015.

  1. BigSquare

    BigSquare

    Joined:
    Dec 2, 2015
    Posts:
    6
    Hi, I'm currently scripting a simple teleport script that when a player steps on a pad, the player is teleported to another pad. The player is first person, and I'm having difficulty getting the camera to rotate to the orientation of the exit pad. As it is right now, the player teleports successfully, but the rotation stays the same as when the player stepped on the enter pad.

    The script I have below doesn't work right now because I get compiler errors with enabling/disabling MouseLook, but any help would be appreciated.


    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityStandardAssets.CrossPlatformInput;
    5. using UnityStandardAssets.Utility;
    6.  
    7. public class StepThroughPortal : MonoBehaviour {
    8.  
    9.     public GameObject otherPortal;
    10.     GameObject attach;
    11.     Component mouse;
    12.  
    13.  
    14.     // Start object
    15.     void Start () {
    16.  
    17.     }
    18.  
    19.     void OnTriggerEnter(Collider other) {
    20.         Debug.Log ("something hit the portal");
    21.         if(other.tag == "Player") {
    22.             attach = GameObject.FindWithTag ("MainCamera");
    23.             GetComponent<AudioSource>().Play();
    24.             other.transform.position = otherPortal.transform.position + otherPortal.transform.forward * 1;
    25.             mouse = GameObject.FindWithTag ("Player").GetComponent<UnityStandardAssets.Characters.FirstPerson.MouseLook>();
    26.             mouse.enabled = false;
    27.             attach.transform.rotation = otherPortal.transform.rotation;
    28.         }
    29.     }
    30.  
    31.     void OnTriggerExit(Collider other) {
    32.         if (other.tag == "Player") {
    33.             mouse = GameObject.FindWithTag ("Player").GetComponent<UnityStandardAssets.Characters.FirstPerson.MouseLook>();
    34.             mouse.enabled = true;
    35.         }
    36.     }
    37. }
     
  2. BackwoodsGaming

    BackwoodsGaming

    Joined:
    Jan 2, 2014
    Posts:
    2,229
    For first person, I'd just move the camera to be a child of the player object. That way it always faces the way the first person player faces. I don't think I've used a first person controller yet that hasn't already been setup that way. But then, I prefer working in third person mode. The third person cameras I use have been designed already to autocorrect to face the same way as the player faces as the player moves, even the orbit ones seem to do that. Not sure how they are coded though.
     
  3. BigSquare

    BigSquare

    Joined:
    Dec 2, 2015
    Posts:
    6
    The camera is already a child object of the character controller. I think the problem is that MouseLook is always looking for input to translate into real-time camera rotation. If there was some way to disable it for a short moment and reset the input so that the camera is rotated the right way after the player warps, that would be ideal.
     
  4. 3zzerland

    3zzerland

    Joined:
    Oct 31, 2014
    Posts:
    42
    If I'm understanding you correctly, when you teleport to the new pad your character (and subsequently camera) are not facing the direction you want them to face? Every time they teleport, do you always want them facing a specific direction, regardless of how they were facing when they entered the teleporter?
     
  5. BigSquare

    BigSquare

    Joined:
    Dec 2, 2015
    Posts:
    6
    Yep. I want the player to face the direction (orientation) of the new pad. If it helps at all, I'm using a version of the Unity 5 first person character controller with some minor modifications I've made.
     
  6. 3zzerland

    3zzerland

    Joined:
    Oct 31, 2014
    Posts:
    42
    transform.eulerAngles for the game object of the other collider is what you likely want to manipulate for your desired effect.


    Irrelevant to your question:
    Other than playing your sound and setting your new position/rotation, you can probably remove the rest of the code inside your if statement (and the OnTriggerExit code all together).

    GameObject.FindWithTag and other similar functions have their use, but are 'expensive' and should be used as sparingly as possible. It's most ideal to use them in start of functions to cache references to things you may use frequently. This applies to a handful of things, such as:
    Code (CSharp):
    1. Transform _transform;
    2.  
    3. void Start() {
    4.   _transform = transform;
    5. }
    That caches a reference to the transform the script is attached to and saves you lookup calls. While this is good practice to learn, I recommend not dwelling on it until it matters and performance optimizations are actually needed.
     
    Last edited: Dec 5, 2015
    BackwoodsGaming likes this.
  7. BackwoodsGaming

    BackwoodsGaming

    Joined:
    Jan 2, 2014
    Posts:
    2,229
    Instead of rotating your camera, do your position change and rotation to the player. If the camera is a child of your player, I would think it would come in facing the same direction as the player already. I'm wondering if maybe doing things to both are somehow messing you up. I just tested my portal with the basic standard assets first person controller and everything seemed to work perfect just adjusting the position and rotation to match my portal.. well it seemed that way as I started falling through the world.. lol I guess my third person controller adjusts to stop it from doing that.. probably should adjust my Y to above the portal... lol
     
  8. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Caching transforms is not really needed anymore. From 5.0 onward unity does this automatically.

    To solve the OP, simply set the rotation of your player to the rotation of the teleporter.
     
    3zzerland and BackwoodsGaming like this.
  9. 3zzerland

    3zzerland

    Joined:
    Oct 31, 2014
    Posts:
    42
    I hadn't read up on all the changes in my absence, so I appreciate that. I recall reading about improvements to the GetComponent functionality, but did not see the update to transforms.

    That was the most trivial example I could think of (even more trivial with the update), but I am confident it is still a sufficient example of local caching. I'd probably even wager that local caching of the transform is still (somewhat) more performant than the built in method, but I'm sure its not enough to bother with.
     
  10. BigSquare

    BigSquare

    Joined:
    Dec 2, 2015
    Posts:
    6
    This is the new code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityStandardAssets.CrossPlatformInput;
    4. using UnityStandardAssets.Utility;
    5.  
    6. public class StepThroughPortal : MonoBehaviour {
    7.  
    8.     public GameObject otherPortal;
    9.  
    10.     // Start object
    11.     void Start () {
    12.  
    13.     }
    14.  
    15.     void OnTriggerEnter(Collider player) {
    16.         if(player.tag == "Player") {
    17.             GetComponent<AudioSource>().Play();
    18.             player.transform.position = otherPortal.transform.position + otherPortal.transform.forward * 1;
    19.             player.transform.rotation = otherPortal.transform.rotation;
    20.         }
    21.     }
    22.  
    23. }
    However, when testing, it still does not achieve the desired effect. To illustrate, I've built a demonstration. All you need to do is create an empty project and import the project package. The enter warp pad is the black circle, and the exit warp pad is the black triangle. The coloured squares indicate is the altering of the player rotation upon teleporting was successful.

    Here is a picture of the demonstration scene:


    I've attached the unitypackage. Any help would be greatly appreciated.
     

    Attached Files:

    Last edited: Dec 5, 2015
  11. 3zzerland

    3zzerland

    Joined:
    Oct 31, 2014
    Posts:
    42
    Your script works fine.

    The First Person Controller you are using has its own rotation method that you are fighting. What's happening is that MouseLook stores the rotation of your character and your camera and then updates them based on those values.

    The easy way to "beat it" is to give yourself the power to change those stored values.
    In your FirstPersonController script, add the following function:
    Code (CSharp):
    1. public void SetRotation (Transform other) {
    2.   m_MouseLook.Init(other,m_Camera.transform);
    3. }
    This is going to give you the ability to re-initialize those stored values in MouseLook. Now, you just need to call this function from your teleporter script:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityStandardAssets.Characters.FirstPerson;
    4.  
    5. public class StepThroughPortal : MonoBehaviour {
    6.  
    7.     public GameObject otherPortal;
    8.     AudioSource _audioSource;
    9.  
    10.  
    11.     // Start object
    12.     void Start () {
    13.         _audioSource = GetComponent<AudioSource>();
    14.     }
    15.  
    16.     void OnTriggerEnter(Collider player) {
    17.         if(player.tag == "Player") {
    18.             _audioSource.Play();
    19.             player.transform.position = otherPortal.transform.position + otherPortal.transform.forward * 1;
    20.             FirstPersonController fpc = player.gameObject.GetComponent<FirstPersonController>();
    21.             fpc.SetRotation(otherPortal.transform);
    22.         }
    23.     }
    24.  
    25. }
    Now that your troubles are solved, back to my off topic tips!

    Empty functions like Start (or especially Update) should fall under the "use it or lose it" ideal. In this case, I used it as another example of caching! ;)

    Regards,
    Rob
     
  12. BigSquare

    BigSquare

    Joined:
    Dec 2, 2015
    Posts:
    6
    Yep, I had a suspicion that it was MouseLook interfering. Thanks so much for your help!! :D:)