7
\$\begingroup\$

I'm trying to make a relatively simple elevator (which essentially teleports the player), but I don't want it to instantly teleport them. I want the player to enter the collider, wait 2-3 seconds, and then do it to take make it seem somewhat more natural.

My code thus far:

using UnityEngine;
using System.Collections;

public class Teleporter : MonoBehaviour
{
    public GameObject TeleportTo;
    //public Material NewSkybox;

    void TimerInvoke()
    {

    }

    void OnTriggerEnter(Collider other)
    {

        Vector3 displacement = other.transform.position - this.transform.position;

        other.transform.position = TeleportTo.transform.position;
        other.transform.position += displacement;

        //RenderSettings.skybox = NewSkybox;
    }
}

Also if possible I'd like to stray away from coroutines. How should I do this?

\$\endgroup\$
  • 1
    \$\begingroup\$ Possible duplicate of How to load scene after a set delay? \$\endgroup\$ – Vaillancourt Nov 12 '15 at 1:54
  • 4
    \$\begingroup\$ I'm curious as to why you would want to avoid the tool that is designed to cater to this exact scenario? \$\endgroup\$ – Shadow Nov 12 '15 at 5:28
5
\$\begingroup\$

I usually do that with Coroutines, but since you were very specific that you want to avoid them, maybe in your case you could try something quite simple like:

float delay = 0;
bool trigger = false;

public Update()
{
    if (delay > 0) delay -= Time.deltaTime;
    if (delay <= 0 && trigger) TeleportPlayer();
}

void OnTriggerEnter(Collider other)
{
    delay = 3;
    trigger = true;
}

void TeleportPlayer()
{
    Vector3 displacement = other.transform.position - this.transform.position;
    other.transform.position = TeleportTo.transform.position;
    other.transform.position += displacement;
    trigger = false;
}

Of course, adjustments can be done depending on how much time you want to wait. Also, consider that deltaTime is not the same every frame, so if you need scientific-level precision for your waiting, some tweaking would probably be required. But I think you got the idea of what the code is doing.

Finally, maybe also of your interest, see this implementation of a WaitUntil function that was created precisely to avoid Coroutines: http://theinstructionlimit.com/a-replacement-for-coroutines

EDIT: although the answer had only the intention of giving a basic idea on how to handle what the OP needed, I decided to include the bool variable "trigger" as a simple way to avoid the code to start the desired action (in this case, the fucntion "TeleporPlayer") when the code is initialized. That way, the life of future learning readers becomes easier.

\$\endgroup\$
  • \$\begingroup\$ I tried your script, but I get "the name 'other' does not exist in the current context. \$\endgroup\$ – Sie Nov 12 '15 at 6:09
  • \$\begingroup\$ @KernelPanic Oh, the reason for that is all the "TeleportPlayer" function is just a piece of the OP question for the sake of illustrating the use of the code. Instead, you should just substitute it for whatever function you want to execute after the given delay. \$\endgroup\$ – MAnd Nov 12 '15 at 17:11
  • 1
    \$\begingroup\$ Isnt this code fired instantly ad delay is = 0? \$\endgroup\$ – Leggy7 Nov 18 '15 at 6:25
  • \$\begingroup\$ @Leggy7 Sure thing, that was a simplified basic idea just for the OP to grasp. In an answer for a similar answer I took care of what you say: gamedev.stackexchange.com/questions/111275/… But in any case, I will edit this answer here to make things easier for future reader that might drop by. Thanks for your comment \$\endgroup\$ – MAnd Nov 19 '15 at 0:45
4
\$\begingroup\$

You can also use Invoke to achieve.

void OnTriggerEnter(Collider other)
{
    Invoke("TeleportPlayer", 3f);
}
 void TeleportPlayer()
{

    Vector3 displacement = other.transform.position - this.transform.position;

    other.transform.position = TeleportTo.transform.position;
    other.transform.position += displacement;

    //RenderSettings.skybox = NewSkybox;
}
\$\endgroup\$
3
\$\begingroup\$

Use Coroutines. You can see yield return new waitforseconds(3); in the TeleportPlayer method. That will wait 3 seconds before teleporting the player. Remember though, it only halts execution of the next line within the coroutine. All other methods continue to be executed.

 void OnTriggerEnter(Collider other)
        {
           StartCoRoutine("TeleportPlayer");

        }

IEnumerator TeleportPlayer()
{

            Vector3 displacement = other.transform.position - this.transform.position;
      Yield return new waitforseconds(3);

            other.transform.position = TeleportTo.transform.position;
            other.transform.position += displacement;

}
\$\endgroup\$
  • 1
    \$\begingroup\$ Just noting that the OP mentioned that if possible, Coroutines should be avoided. Not that your answer is wrong or isn't useful. \$\endgroup\$ – MAnd Nov 12 '15 at 3:55
  • \$\begingroup\$ @MAnd my bad didn't read that last line \$\endgroup\$ – SanSolo Nov 12 '15 at 4:16
2
\$\begingroup\$

Of course, you can do it in code, but my approach is a little more "natural".

On your example - elevator - I will do something as follows:

  • When player enters elevator, play animation (fe. closing doors)
  • In this animation, at the end I would place code for "teleporting" player.

So you don't need to tweak everything by code, but you would do this in animation, so it's easier and more natural way.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.