1
votes

I'm trying to make a portal, but I don't understand why the code:

playerControl.transform.position = new Vector3(destination.position.x, destination.position.y, destination.position.z);

only works on certain positions and angles.

This is the set up for the code

    public class Teleport : Interactable
{
    public Transform destination;
    private GameObject playerControl;
    private PortalAnimationController portalController;

    // Start is called before the first frame update
    void Start()
    {//get the player information
        playerControl = PlayerManager.instance.player;
        portalController = PortalAnimationController.instance;
    }


    public override void interact()
    {
        //base.interact();
        //run the teleport method

        StartCoroutine("teleport");

        //Debug.Log(playerControl.GetInstanceID());

    }


    /*
     1. trigger the panel
     2. stop the time
     3. teleport the player
     */
    private IEnumerator teleport()
    {
        Time.timeScale = 0f;//stop the time
        portalController.fadeOut();
        //wait for seconds realtime can avoid stopping when timescale is 0
        yield return new WaitForSecondsRealtime(portalController.duration);//wait for the transition
        Debug.Log("wait finish");
        //after the the wait
        Debug.Log(playerControl.transform.position + "before");
        playerControl.transform.position = new Vector3(destination.position.x, destination.position.y, destination.position.z);
        if(playerControl.transform.position!= destination.position)
        {
            Debug.Log(playerControl.transform.position);
        }
        else
        {
            Debug.Log(playerControl.transform.position+"pass");
        }
        portalController.fadeOut();
        Time.timeScale = 1f;
    }
}

The interactable class only contains a "public virtual void interact()" method for teleport to override it. The way to trigger is through the code below:

void Update()
    {
        RaycastHit hit;
        if (Input.GetButtonDown("Interact"))
        {
            if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit, interactableRange))
            {
                Interactable interactable = hit.collider.GetComponent<Interactable>();
                //if the player is looking at the interactable
                //Debug.Log("Interact with " + hit.transform.name);
                if (interactable != null)
                {
                    //highlight the object
                    interactable.interact();
                    //if player press the interact key, then pick it up
                    Debug.Log("Interact with " + hit.transform.name);


                }
            }
        }
    }

It shoots a ray when the e key is pressed, then hit a collider box to retrieve the interactable component and call the interact() immediately.

I have tested it hundreds of times, and there are only 3 results. 1. player actually get teleported.(success) 2. player flashes to the destination in 1 frame then back to where it was.(failed) 3. player does not move at all.(failed)

video link

1
Just a guess. Do you have the same issue, if you not set timeScale to 0? - Mykhailo Khadzhynov
@Mykhailo Khadzhynov Yeah I still have the same problem even if I don't set timeScale to 0 - chun yin kwan
My guess is that you have a two teleportations one after another - it can be happen, if you have two-directional teleporter. If so, try to add some simple logic, which would allow you to do teleportation only once, like if (Input.GetButtonDown("Interact") && canTeleport) { canTeleport = false, Of cource, you need to press interact button only once, when you look directly to teleporter. - Mykhailo Khadzhynov
Also, check, is it works in a single frame, without coroutine. - Mykhailo Khadzhynov
Looks like you have some execution order dependent interactions happening with your player position. How are you doing player movement? - NSJacob1

1 Answers

0
votes

thank you everyone who is trying to help. I finally found out where the problem is. The reason why teleport doesn't is because my player has a component called Character Controller, and this component will override the changed position of the player, and sends it back to where it is. So, I will have the player being teleported to the correct position for one frame before it is back to the original position.

My way to fix it is simply do:

characterController.enable = false;
playerControl.transform.position = new Vector3(destination.position.x, destination.position.y, destination.position.z);
characterController.enable = true;

this way the character controller will not be called, hence teleport will function normally.

enter image description here

Again, thanks for everyone who tried to help. :D