the map is linear, i meant in a "god of war" map kind of way. Meaning the map in not straight, and has lots of curves in it. Actually, the world's x in the begging of the level halfway through the map increases in value, but at the finish, it is even lower than the spawn point.

How can I measure the player's progress through the level? I want to use the progress percentage to trigger certain events. Like defying an object's location, based on the percentage of the progress in the level (like setting the height of the moving light hovering above the player to y = 15, when the progress is between 20% and 30%. And when the progress goes between 30 and 40, y changes to 20).

Any ideas for my situation?

  • 2
    \$\begingroup\$ What are you trying to do? Your question doesn't make much sense. Add more details. \$\endgroup\$
    – jgallant
    Sep 25, 2016 at 14:31
  • \$\begingroup\$ Are you asking about how to show the progress to the player or would you like to send metrics to your server so you can analyze how fast your players progress? \$\endgroup\$
    – Philipp
    Sep 25, 2016 at 14:32
  • \$\begingroup\$ I want to control game objects positions in my scene, as the player progresses \$\endgroup\$
    – MrChips
    Sep 25, 2016 at 14:35
  • \$\begingroup\$ There is no single way to do something like this, try to give aa much details as possible. Start by saying what is level progress for you. Amount of coins collected? Distance from the finish line? Number of enemies killed? Etc. \$\endgroup\$
    – rlam12
    Sep 25, 2016 at 14:40
  • 1
    \$\begingroup\$ Are you really just asking how to read the position of a game object? You do that with transform.position. \$\endgroup\$
    – Philipp
    Sep 25, 2016 at 17:26

4 Answers 4


First, set a StartPosition and a EndPosition:

float StartPosition = 0;
float EndPosition = 2000;

Then, in your Update() method, you are going to want to normalize your player's position, based on these start and end points:

Update() {
    float x = transform.position.x;
    float normalized = (x - StartPosition) / EndPosition;

    Debug.Log("Percentage Completed: " + (normalized * 100).ToString());

For the door opening I would normally use triggers. Just create a collider, mark it as a trigger, and place the code for whatever you want to do inside 'OnTriggerEnter'.

You can use a simple script to hover an object above the player.

example: (in Update) transform.position = player.position + Vector3.up * hoverHeight

However, if you really want a percentage, you can do that. Start by calculating the map length (the distance between the starting point and the finish line). If your level is linear, the difference between one axis should be fine. Then, every frame (or whenever the player moves) divide the distance between the player and the finish line by the map length.


(in Start) float MapLength = finish.position.x - spawn.position.x

(in Update) float percent = 1 - (finish.position.x - player.position.x) / MapLength

If you placed the player into the map using the inspector instead of using a spawn point, you can use player.position instead of spawn.position and it should work just as well.

EDIT: For a quick approximation, you could log the distances between all of the checkpoints. Then all you have to do is add the distances up to the last checkpoint, then from the last checkpoint to the player to get the distance from the start. distanceFromStart / totalDistance = percentageComplete

  • \$\begingroup\$ The second part of your answer is exactly what I'm trying to do, but there's a problem. And is, when i said the map is linear, i meant in a "god of war" map kind of way. Meaning the map in not straight, and has lots of curves in it. Actually, the world's x in the begging of the level halfway through the map increases in value, but at the finish, it is even lower than the spawn point. Any ideas for my situation? \$\endgroup\$
    – MrChips
    Sep 26, 2016 at 2:03
  • 1
    \$\begingroup\$ You could attach a NavMeshAgent to the player, set its destination to the finish, and use NavMeshAgent.remainingDistance \$\endgroup\$ Sep 26, 2016 at 2:43
  • \$\begingroup\$ @MrChips You should have explained that when you first posted the question. That would have saved us all a lot of time. \$\endgroup\$
    – Philipp
    Sep 26, 2016 at 11:48

I'm not sure what cost there is to using the NavMesh, but if you only need increments in say... 10%, you can always just create trigger colliders across the entire walkable path at each 10% section (or 5% or whatever you want) and as the player crosses those triggers, a variable increases that holds them (and then they are destroyed so that the player doesn't walk backward, hit it again, and increment progress).

This can also allow you to create triggers at custom locations. You mentioned that you want events at certain distances into the level. Really, you wouldn't even need to track a percentage this way - you can just use a trigger at a specified location to trigger the event that you want.


Place some invisible objects along the path of your player's progress which have a Collider attached to them with the "Is Trigger" property on. Position the objects and shape their colliders in a way that the player can not move around them. This ensures that they all get triggered while the player moves through the level. Whenever the player enters such a collider, set the percent-completed to a new value:


This is how I would implement the behavior of these triggers in C#:

class CompletionTrigger : MonoBehaviour 
    public float completion; // completion when reaching this trigger
    public static float playerCompletion; // players current global completion

    OnTriggerEnter(Collider other) {
         if (/* other is the player */) {
              playerCompletion = completion;

I left out the part where you find out if the object which triggered the collier is the player and not something else. There are countless ways to do this, and the best one depends a lot on how you structured your project. So before I suggest a way which might be unnecessarily difficult in your particular case I decided to leave that to you.

Every trigger with this behavior will have a public property "Completion" which you need to manually set in the Inspector. Set it to the approximate completion at the position where you place it.

You will then have a global variable CompletionTrigger.playerCompletion which you can access from any other script whenever you need the current completion for whatever reason.

When you want certain events to happen at certain points in the level (like for example open a door when the player moves close to it), you should also use trigger colliders with attached scripts.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .