This site uses strictly necessary cookies. More Information

X- Home /

# Crosshair Targeting System

I'm making a space sim, and I need a targeting cursor in front of an enemy so the player can aim. Since when you fire a bullet, you need to fire ahead so the bullet actually hits it's target. It's hard at the moment to judge where to shoot based off your speed, the bullet's speed, and your distance from the target. So essentially there would be a little crosshair in front of the target where the player needs to shoot in order to hit it. Here's an example (What I'm talking about doesn't actually start till 2:35). I know I need to do some math to calculate where to place the GUI crosshair based off that target's distance, the target's speed, your speed, and the bullet's speed. I just don't know where to start. Any help would be appreciated.

**Answer** by aldonaletto
·
Dec 30, 2011 at 03:04 AM

Actually, that game doesn't seem to do that - it seems to just draw a crosshair at some distance in the airplane's forward direction.

But if you want to find the position where to shoot taking into account the target velocity, there exists a "mathmagic" to do that: the function HitTime below calculates the time needed to a projectile with velocity *speed* to reach the target *targ* moving at velocity *vel* (if the target is moving away too fast to be reached, the function returns -1). Once the time is calculated, you can find the position to shoot using the target velocity, draw the crosshair and shoot in its direction.

In most cases you don't know the target velocity, but you can calculate it from the target positions over time. The calculated velocity is somewhat jerky, thus you must filter it in order to have a smooth behaviour - but this also makes the aim unreliable until the calculated velocity reaches a stable value.

You must fire the projectile by setting its rigidbody.velocity to bulletSpeed * direction.normalized (forget about AddForce - you will never get the correct speed).

// targ is the target transform, vel is its velocity vector, // and speed is the projectile speed. Returns the time needed // to reach the target, or -1 if it's not possible

function HitTime(targ: Transform, vel: Vector3, speed: float): float {
var dist = targ.position - transform.position;
var a = Vector3.Dot(vel, vel) - speed * speed;
var b = 2 * Vector3.Dot(vel, dist);
var c = Vector3.Dot(dist, dist);
var det = b * b - 4 * a * c;
if (det >= 0)
return 2 * c / (Mathf.Sqrt(det) - b);
else
return -1;
}

// that's an example code to test this function:

var guiCross: GUITexture; // drag the GUITexture crosshair here var target: Transform; // target transform var bulletSpeed: float = 10; // projectile speed

private var targetVel: Vector3; private var lastPos: Vector3;

function Update(){ if (target){ // if some target locked... // if you don't know the target velocity, calculate it var vel = (target.position - lastPos)/Time.deltaTime; lastPos = target.position; // filter the velocity to avoid a shaking crosshair targetVel = Vector3.Lerp(targetVel, vel, Time.deltaTime);

```
// calculate the hit position:
var t = HitTime(target, targetVel, bulletSpeed);
if (t < 0){
// target moving away too fast to be reached
guiCross.enabled = false;
} else {
// target may be hit:
guiCross.enabled = true;
// calculate the position where the target will be hit
var hitPos = target.position + t * targetVel;
// calculate the crosshair position
var crossPos = Camera.main.WorldToViewportPoint(hitPos);
guiCross.transform.position = crossPos;
}
if (Input.GetButtonDown("Fire1")){
var missile = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Destroy(missile, 20); // kill the missile after 20s
missile.AddComponent(Rigidbody);
missile.rigidbody.position = transform.position;
missile.rigidbody.useGravity = false;
// use this to shoot at the calculated point:
var dir = hitPos - transform.position;
missile.rigidbody.velocity = dir.normalized * bulletSpeed;
}
```

} } CREDITS: I based the HitTime function in an interesting article about this subject, *Leading a target*.

**Answer** by asafsitner
·
Dec 29, 2011 at 11:01 AM

Start with `Camera.WorldToScreenPoint();` Calculate the necessary targeting crosshair's position in 3D, then use the `WorldToScreenPoint`

method to transfer it's position to a point on the screen.

How to calculate the crosshair's position, though?

Algorithm should be something like:

Determine projectile's travel time from weapon position to enemy position through division of distance by speed and then again by average FPS

Predict enemy's position by calculating it's position in the next frame, multiplied by the projectile's travel time (to predict rotation have a look at this answer - it's working great)

Call

`Camera.WorldToScreenPoint(predictedPosition);`

Draw the crosshair through GUI

"Average FPS" being average frames-per-second or average feet-per-second (speed of bullet)? And also, how would I predict it's location in the next frame? Current location * speed / FPS?

And as for drawing the texture, how do I put it's position based off the predicted position, because I tried this :

```
GUI.DrawTexture(new Rect(cursorScreenLocation), bulletTargetingCrosshair, Scale$$anonymous$$ode.ScaleToFit, true, 10.0F);
```

And this :

```
GUI.DrawTexture(cursorScreenLocation, bulletTargetingCrosshair, Scale$$anonymous$$ode.ScaleToFit, true, 10.0F);
```

But I got errors both times.

Well, nighthawx349, you could use Pythagoras Theorem on that one. You would need the measure the distance between you and the target object, then calculate the travel time of the projectile, then multiply that value with the velocity of the target and there you would have the distance where you would need to place the "crosshair"... Something like this:

var TargetSpeed; var ProjSpeed; var TargetDist; var CrossDist;

CrossDist = (TargetDist/ProjSpeed) * TargetSpeed;

Hope I've helped =)

Well this is what I have here :

```
//Component Check
Combat other = plane.GetComponent<Combat>();
PaperPlaneAI planeAI = target.GetComponent<PaperPlaneAI>();
//Variable Check
target = other.targetHit;
targetSpeed = planeAI.speed;
targetDistance = Vector3.Distance(target.transform.position, plane.position);
Vector3 fwd = target.TransformDirection(Vector3.forward);
//Next Steps
bulletTravelTime = targetDistance/bulletVelocity;
targetsNextLoc = fwd * targetSpeed/70;
//Final Step
cursorLocation = bulletTravelTime * targetsNextLoc;
cursorScreenLocation = camera.WorldToScreenPoint(cursorLocation);
```

Average FPS as is Frames Per Second, as you're calculating positions from one frame to the next. It's basically Pythagoras's theorem, but the tricky part is predicting enemy's position. Luckily, a prediction solution already exists for networking lag compensation which you can probably dig and reuse (basically in both cases you're trying to extrapolate the Transform's movement).

A better example of what you're trying to achieve can be found in Black Prophecy

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.