Unity XR C# System Locomotion

XR Teleportation

A technical showcase of a VR locomotion and teleportation system built in Unity, featuring fuel constraints, character controller safety, and custom cooldown management.

About the Project

● LIVE MECHANIC DEMO Teleportation Mechanic Demonstration

Developed for a collaborative group project, this teleportation mechanic prevents player motion sickness while adding tactical depth. The system requires fuel activation and enforces a custom cooldown timer before subsequent teleportation jumps can occur.

Teleport Manager Singleton

The TeleportManager operates as a central Singleton script that maintains the global teleportation state, managing fuel reserves, cooldown status, and player target transforms.

TeleportManager.cs
C#
public class TeleportManager : MonoBehaviour
{
    public static TeleportManager Instance;

    // Checks if the player can teleport or not
    public bool isFueled   = false;
    public bool isCooldown = false;

    /// 
    /// Controls the cooldown time between teleportation jumps.
    /// 
    public float       cooldownTime;

    /// 
    /// Reference to the player GameObject
    /// 
    public GameObject  player;
    
    public Transform[] otherTeleportations;

    private void Awake()
    {
        // Enforces Singleton pattern across the scene
        if (Instance == null) { Instance = this; }
        else { Destroy(gameObject); }
    }
}

Teleporter Pad Script

Attached to individual teleportation pads, the TeleporterScript handles trigger detection, fuel cell collision checks, and safely toggles the CharacterController during position updates to prevent physics glitches.

TeleporterScript.cs
C#
public class TeleporterScript : MonoBehaviour
{
    public bool isStandingOn = false;

    [SerializeField] private int teleportNumber;

    private void Update()
    {
        if (TeleportManager.Instance != null)
        {
            if (TeleportManager.Instance.isFueled && isStandingOn && !TeleportManager.Instance.isCooldown && Input.GetKeyDown(KeyCode.T))
            {
                TeleportPlayer(teleportNumber);
            }
        }

        if (!TeleportManager.Instance.isFueled && Input.GetKeyDown(KeyCode.T))
        {
            TextManager.Instance.WhatToDisplay(TextManager.Instance.dialogueCell2[4]);
        }
    }

    private void TeleportPlayer(int numberToTeleport)
    {
        // Disable CharacterController to prevent physics collision bugs
        TeleportManager.Instance.player.GetComponent().enabled = false;

        TeleportManager.Instance.player.transform.position = TeleportManager.Instance.otherTeleportations[numberToTeleport].position;
        StartCoroutine(Cooldown());

        TeleportManager.Instance.player.GetComponent().enabled = true;
    }

    private IEnumerator Cooldown()
    {
        TeleportManager.Instance.isCooldown = true;
        yield return new WaitForSeconds(TeleportManager.Instance.cooldownTime);
        TeleportManager.Instance.isCooldown = false;
    }

    private void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.CompareTag("FuelCell"))
        {
            TeleportManager.Instance.isFueled = true;
            Destroy(other.gameObject);
        }
    }
}