Add score when an object passes a certain position?

Hello, to start off, I’m a beginner at Unity, Scripting etc.
I’m not looking for someone to do the script for me, I want to learn how to do it.

So, I’m making my first game, based on the popular game Flappy Bird. Right now I’m working on the scoring system.

This is my script so far:

using UnityEngine;
using System.Collections;

public class PointsScript : MonoBehaviour {

	public int score = 0;
	public Transform obstacle;

	// Use this for initialization
	void Start () 
	{

	}
	
	// Update is called once per frame
	void Update () 
	{
		guiText.text = ("Points: " + score);
		if (obstacle.position.x == -1) 
		{
			score ++;
		}
	}
}

But it’s not working. The GUItext is showing but it ain’t adding any values to score.
So I’m looking for a solution to this. I want the score to increase by 1 when the object passes the position.

I’m sorry if someone already asked this, I’ve searched around but I couldn’t find any possible solution.

You are checking if a float is exactly -1, which in reality will not happen - at least not in a reliable way. Use <= -1.

Okay that’s understandable, thanks. :stuck_out_tongue:
However, that fix didn’t change anything, I still don’t get any increase on the score value. :s

What is this script attached to?
If you set your obstacle in the inspector to have a > -1 score (using kat0r’s suggestion) then your score will go up until that value has changed.

It looks like you want to compare the transform.x with the obstacle.x and work out when one has passed the other.

It is just attached to a GUIText object. Maybe I’m doing this all wrong haha, I really have no clue to compare positions.

Basically you just take two transforms, and then compare the relevant part of the Transform.position. If you move from left to right (on the x axis) you would do:

if (playertransform.position.x > obstacletransform.position.x) 
{ 
increment score
prevent that obstacle from triggering again, by p.e. destroying it
}

how are you moving ‘obstacle’

Are you dragging the obstacle onto the gui in the inspector.

In my ‘flappy bird’ experiment I have a raycast going between the obstacle gap and when the player passes through this raycast it increases the score.

1510864--85666--$flappybirdobstacle.png

Okay thanks, I understand now and it should work imo, but nothing happends.

Could it be a problem that I use Instantiate on the obstacle? That the transform.position doesn’t apply to the clones? Just a thought.

To explain the situation I attatch a picture: 1510866--85665--$lalala.jpg

The thing is that the “player” isn’t moving with the x-axis, it’s locked on the -1 value of the x-axis. The obstacles are moving from right to left and in random heights, and when their centre position is at the players centre position (x -1), a +1 should be added to the score.

softwizz: The gameObject that functions as the obstacle is attached to the GUIText object.

May be but I would have thought you would get the dreaded ‘null reference exption’ from this line

if (obstacle.position.x == -1)

if the obstacle was not there.

Yea, maybe this method is just a stupid way to do it. I guess it would be smarter to do it with a raycast, it makes more sense.
Do you have any good tutorial on how to use raycasts?

Well it depends how your obstacle is constructed.

Mine is a prefab that is constructed like this:

Empty game object called Block
child 1 called Top, this is a plane with a box collider (set as is trigger) and the top part of the obstacle texture
child 2 called Bottom, this is a plane with a box collider (set as is trigger) and the bottom part of the obstacle texture

Now these 2 child objects are set up with a gap between them as in my previous picture.
This gap does not change.

Attached to the parent (empty game object called Block) is the script to control the obstacle.

This is the script Block.cs

using UnityEngine;
using System.Collections;

public class Block : MonoBehaviour
{
	private Transform top;
	private Transform bottom;
	private RaycastHit hit;
	private bool passed;
	// Use this for initialization
	void Start ()
	{
		top = this.transform.GetChild(0); // gets the first child
		bottom = this.transform.GetChild(1); // gets the second child
		passed = false;
	}
	
	// Update is called once per frame
	void Update ()
	{
		if(!passed)
		{
			Vector3 directionTtoB = bottom.position - top.position; // direction from top to bottom
			Ray ray = new Ray(top.transform.position,directionTtoB);
			if (Physics.Raycast (ray, out hit))
			{
				if(hit.collider.tag=="Player")
				{
					Player.Instance.score++;
					passed=true;
				}
				Debug.DrawRay (top.transform.position,hit.point - top.transform.position);
			}
		}
		if(this.transform.position.x < (Player.Instance.transform.position.x-15f))
			Destroy(this.gameObject); // destroy obstacle when so far past player
	}
}

Thank you for sharing, I will look into this and try to understand it!
I’ll come back with results! :slight_smile:

this is the raycast code

Vector3 directionTtoB = bottom.position - top.position; // direction from top to bottom
Ray ray = new Ray(top.transform.position,directionTtoB);
if (Physics.Raycast (ray, out hit))
 {
   if(hit.collider.tag=="Player")
    {
      // do whatever you want when the player hits the ray
    }
 }

you also need to declare a RaycastHit
private RaycastHit hit;

Thanks for the help softwizz!

I’ve got it working now, just one small problem left (small I hope).
So i’ve put a raycast line on my player and when it hits the obstacle the score increases. But it increases by a counting amount until the raycast isn’t hitting the object. I want the score just to increase by 1, how can I do that?

Here’s the code

	void RayCasting ()
	{
		Debug.DrawLine (sightStart.position, sightEnd.position, Color.green);

		if (Physics2D.Linecast (sightStart.position, sightEnd.position, 1 << LayerMask.NameToLayer ("Hinder"))) 
		{
			spotted = true;
			score ++;
		}

		if (!Physics2D.Linecast (sightStart.position, sightEnd.position, 1 << LayerMask.NameToLayer ("Hinder"))) 
		{
			spotted = false;
		}

	}

Well, i’m not too sure how efficient this would be, but you could always add a “cooldown” timer for when the raycasts updates your score…

Althought the way i would have gone about this, if i was making this type of game, (again, this probably isn’t efficient or correct but just the first way that came to my head :P) would have been to use colliders as “triggers” instead of raycasts to add to your score. Same principle, but i have no idea which would work better :stuck_out_tongue:

I get your point about the colliders but I think the some problem would occur, since score will added when the players hitbox is touching the collider. But I understand, that was my original thought too. :stuck_out_tongue:

That’s what the passed boolean is for, the raycast is only done until it touches the player, as soon as the ray cast hits the player you update the score and set the boolean to turn off the ray, that’s why my ray cast code is inside the if(!passed)

My ray cast is on the obstacle and as soon as the player touches it the ray gets turned off.

If you wanted to use colliers you would still need a way of turning off the collider.

I don’t think having the ray cast or collider detection on the player is the best way of doing it.

Hey Man Did you find the answer of your problem ? thanks.