0
\$\begingroup\$

I want to make game-like time travel, the player has the ability to go to the future by limited time, for that, I want to add some game mechanic like save the player position.

Additional information: ignore the red text. When pressing the button the player will create a new platform and immediately teleport to the original position. After the player teleported, the player will save the new platform as the new teleport position. after 2 seconds or pressing a button. the new platform will disappear and the player will return to the platform position.

I have this _playerController Script and I already implement the save position, but I don't know how to make it like what I explain.

    public Rigidbody2D theRB;
    public float speedMovement;
    public GameObject prefabGameObject;

    [Space(10)]
    private BoxCollider2D boxCollider2D;
    [SerializeField] private LayerMask GroundMask;
    public float jumpVelocity;

    [Space(10)]
    public float past;
    public float future;

    [Space(10)]
    public float hor;


    // Start is called before the first frame update
    void Start()
    {
        theRB = gameObject.GetComponent<Rigidbody2D>();
        boxCollider2D = transform.GetComponent<BoxCollider2D>();
    }

    // Update is called once per frame
    void Update()
    {
        PlayerPosSaveLoad();
        PlayerMovement();
        PlayerJump();
    }

    public void PlayerMovement()
    {
        hor = Input.GetAxis("Horizontal");
        if (hor > 0 || hor < 0)
        {
            theRB.velocity = new Vector2(hor * speedMovement * Time.deltaTime, theRB.velocity.y);
            if (hor > 0)
            {
                transform.localScale = new Vector2(1f, transform.localScale.y);
                //Animation
                Debug.Log("ToTheright");
            }
            else
            {
                transform.localScale = new Vector2(-1f, transform.localScale.y);
                //Animation
                Debug.Log("ToTheLeft");
            }
        }
    }

    public void PlayerJump()
    {
        //animation
        if (isGrounded() && Input.GetKeyDown(KeyCode.Space))
        {
            theRB.velocity = Vector2.up * jumpVelocity;
        }
    }

    public bool isGrounded()
    {
        float extraHeighText = .1f;
        RaycastHit2D raycast2d = Physics2D.BoxCast(boxCollider2D.bounds.center, boxCollider2D.bounds.size, 0f, Vector2.down, boxCollider2D.bounds.extents.y + extraHeighText, GroundMask);
        Color raycolor;

        if (raycast2d.collider != null)
        {
            raycolor = Color.green;
        }
        else
        {
            raycolor = Color.red;
        }
        Debug.DrawRay(boxCollider2D.bounds.center, Vector2.down * (boxCollider2D.bounds.extents.y + extraHeighText), raycolor);
        return raycast2d.collider != null;
    }

    [SerializeField]
    private Vector2 saveThisPosition;

    public void PlayerPosSaveLoad()
    {
        if (Input.GetKeyDown(KeyCode.E))
        {
            saveThisPosition = transform.position;
            SpawnGameObject();
        }
        if (Input.GetKeyDown(KeyCode.Q))
        {
            SwitchWithsavedPosition();
            Destroy(prefabGameObject);
        }
    }

    private void SwitchWithsavedPosition()
    {
        Vector2 temp = transform.position;
        transform.position = saveThisPosition;
        prefabGameObject.transform.position = temp;
    }

    public void SpawnGameObject()
    {
        Instantiate(prefabGameObject, transform.position, transform.rotation);
    }

And this is the Camera Script because connected with the player.

```lang-cs
    public Transform Player;

    // Start is called before the first frame update
    void Start() { }

    // Update is called once per frame
    void Update()
    {
        transform.position = new Vector3(Mathf.Clamp(Player.position.x, -7.3f, 7.3f), Mathf.Clamp(Player.position.y, 1f, 2f), transform.position.z);
    }
\$\endgroup\$
4
  • \$\begingroup\$ 1) But in your video all you do is spawn a block that vanishes. There is never the effect that you teleport to the placed block. 2) You do not need PlayerPrefs for saving the position. PlayePrefs are for storing and accessing player preferences between game sessions. Means if you quit the game, you would want to save there. 3) So your question is: how to teleport the player after 2sec after placing that block back to the blocks position? \$\endgroup\$
    – Zibelas
    Dec 7 '20 at 8:29
  • \$\begingroup\$ 1.) Sorry for the video make this misleading that's a teleport actually 2.) I thought I have to save the position first for that. 3.) Definitely right, that what I want and the new block is a player from the past but like you said . @Zibelas \$\endgroup\$ Dec 7 '20 at 8:39
  • \$\begingroup\$ 2) You can save the position, but it is enough to save it just into a local variable. 3) Can you spawn only one block/ player at a time, more than one or is the latest spawn replacing the previously spawn? \$\endgroup\$
    – Zibelas
    Dec 7 '20 at 9:01
  • \$\begingroup\$ @Zibelas, 3.) for now, the latest spawn replacing the previous one with a time limit because if reached time limits the player back to the previous position. 2.) I thought I have to reload the scene to do that. \$\endgroup\$ Dec 7 '20 at 9:15
1
\$\begingroup\$
  1. First you need to save the position ONLY when you request it. Currently your code is spam saving the location (twice per FixedUpdate). This needs to be changed. Make a new Method for it, check if a certain key is pressed and only than save the location.
  2. Do not save those locations to playerpref. PlayerPrefs are for storing and accessing player preferences between game sessions. All you need to have is a local Vector2 in your controller that saves the position.
  3. Since you just want a teleport and not the block option as in the video, you can just display an image at the position from 2). No rigidbody/ boxcollider needed on it.
  4. https://docs.unity3d.com/ScriptReference/MonoBehaviour.Invoke.html You call in the same condition as under 2) a teleport back method. The example code even shows how to add the 2sec delay. Your teleport code just assigns the saved vector2 as the new position of your player, removes the image from 3) and should as well set the vector2 to null.
  5. As a tip, do not capture user input in Fixedupdate. Input.GetKeyDown is only true in the frame it gets captured and not afterwards. That means you might miss the keypress and your code is not working as you would expect it.

If you have are stuck on one of the points, please update your code and I will further explain the step.

A simple save can be as easy as

private Vector2 saveThisPosition;
private void PlayerPosSave() {
    saveThisPosition = transform.position;
}

Within your playerController, you can access always saveThisPosition and you have the location of the place where you pressed your key. The switch between the object that you spawned and the current Player is just switching their positions.

private void SwitchWithSavedPosition() {
    Vector2 temp = transform.position;
    transform.position = saveThisPosition;
    spawnedGameObject.transform.position = temp;
}

spawnedGameObject is the reference to the old player that you have to create when you press your saveLocation key.

\$\endgroup\$
2
  • \$\begingroup\$ Hello I've updated the scripts also information because I think we misunderstanding here sorry my bad, for 1.) I change that to when pressing keyE only. 2.) I don't understand this. 3.) we misunderstanding here because the player will spawn new gameobject as a platform so there always attached by collider. 4.) think ill add some time counter so when it's end the player returns to first pos. 5.) I put at the update because it runs once per frame \$\endgroup\$ Dec 7 '20 at 12:57
  • \$\begingroup\$ Thank you very much this helps me out \$\endgroup\$ Dec 7 '20 at 22:46
0
\$\begingroup\$

so this is my full script.

    public Rigidbody2D theRB;
    public float speedMovement;
    public GameObject prefabGameObject;
    private GameObject go;

    [Space(10)]
    private BoxCollider2D boxCollider2D;
    [SerializeField] private LayerMask GroundMask;
    public float jumpVelocity;

    [Space(10)]
    public float hor;


    // Start is called before the first frame update
    void Start()
    {
        theRB = gameObject.GetComponent<Rigidbody2D>();
        boxCollider2D = transform.GetComponent<BoxCollider2D>();
    }

    // Update is called once per frame
    void Update()
    {
        PlayerPosSaveLoad();
        PlayerMovement();
        PlayerJump();
    }

    public void PlayerMovement()
    {
        hor = Input.GetAxis("Horizontal");
        if (hor > 0 || hor < 0)
        {
            theRB.velocity = new Vector2(hor * speedMovement * Time.deltaTime, theRB.velocity.y);
            if (hor > 0)
            {
                transform.localScale = new Vector2(1f, transform.localScale.y);
                //Animation
                Debug.Log("ToTheright");
            }
            else
            {
                transform.localScale = new Vector2(-1f, transform.localScale.y);
                //Animation
                Debug.Log("ToTheLeft");
            }
        }
    }

    public void PlayerJump()
    {
        //animation
        if (isGrounded() && Input.GetKeyDown(KeyCode.Space))
        {
            theRB.velocity = Vector2.up * jumpVelocity;
        }
    }

    public bool isGrounded()
    {
        float extraHeighText = .1f;
        RaycastHit2D raycast2d = Physics2D.BoxCast(boxCollider2D.bounds.center, boxCollider2D.bounds.size, 0f, Vector2.down, boxCollider2D.bounds.extents.y + extraHeighText, GroundMask);
        Color raycolor;

        if (raycast2d.collider != null)
        {
            raycolor = Color.green;
        }
        else
        {
            raycolor = Color.red;
        }
        Debug.DrawRay(boxCollider2D.bounds.center, Vector2.down * (boxCollider2D.bounds.extents.y + extraHeighText), raycolor);
        return raycast2d.collider != null;
    }

    [SerializeField]
    private Vector2 saveThisPosition;

    public void PlayerPosSaveLoad()
    {
        if (Input.GetKeyDown(KeyCode.E))
        {
            saveThisPosition = transform.position;
            Destroy(go);
            SpawnGameObject();
        }
        if (Input.GetKeyDown(KeyCode.Q))
        {
            SwitchWithsavedPosition();
            Destroy(go);
        }
    }

    private void SwitchWithsavedPosition()
    {
        Vector2 temp = transform.position;
        transform.position = saveThisPosition;
        prefabGameObject.transform.position = temp;
    }

    public void SpawnGameObject()
    {
        go = Instantiate(prefabGameObject, transform.position, transform.rotation) as GameObject;
    }
\$\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.