# weapon aiming in 3d space using the (2d) mouse

This question is very hard to explain, as seen in my previous question Rotate the player to face where the mouse is pointing - Unity Answers so bear with me.

Basically I have a 3d, 3rd person game set in space where the use controls a spaceship. To control the rotation of the ship the user moves the mouse using the following script:

``````var lookFactor = 100; //This amount indicates how far away the ship and weapons are aiming
function Update ()
{
var distance = (transform.position.z - Camera.main.transform.position.z)*lookFactor;
var position = Vector3(Input.mousePosition.x, Input.mousePosition.y, distance);
position = Camera.main.ScreenToWorldPoint(position);
transform.LookAt(position);
}
``````

This code works quite well as a mouse look code but at the moment here’s how my weapons function:
When the player clicks the left mouse button a missile prefab is instantiated directly infront of the ship with the same rotation as the ship then force is applied to its rigid body to propel it forward. But I’m trying to change this so that when the player clicks the left mouse button, a missile prefab is instantiated infront of the ship facing the mouse (instead of sharing the ships rotation). Except in 3d space using the ScreenToWorldPoint I give the mouse a fixed z co-ordinate, this is no good performing weapon aiming in 3d space. I need a way of changing the ‘fixed’ z co-ordinate to match that of the object the mouse is pointing at but never exceeding the max range of the selected weapon (hope that made sense). I’ll give an example:

The players ship has two beam cannon turrets (one on each wing) which can rotate independently from the ship. These turrets follow the mouse (with it’s annoyingly fixed z co-ordinate ;D). Lets say the player wants to shoot at a ship that’s 250m away, but the z co-ordinate is fixed at 1000m, even though the player places the cursor directly on the ship, there is a chance that 1 or even both lasers will miss because they’re aiming far behind the target ship. This, I’m sure you realise is not what is wanted, I need to know if there’s a way (and what it is) to change the z co-ordinate of the mouse depending on what it’s pointing at (wow, hope that made sense)
I also need the z co-ordinate of the mouse to change appropriately if the player aims near a ship (because they could be accounting for movement and aiming infront of the ship might hit it (if the z co-ordinate is changed properly))

like I said, to me this is very hard to explain, if you need anything clarified please just ask, also refer to the question linked at the top for (a little bit) more information. This problem has had me stuck for weeks and this question took me like 30 mins to write, trying to make it as clear as possible. Thanks in advance.

If you still don’t quite understand what I’m aiming for, look at a game like Star Conflict, I need an aiming system like that, but I just can’t think of how to change the z correctly, especially if the player is aiming not even at but near the ship to account for movement D:

EDIT:
here’s what I’m thinking so far (this is just a concept, no code at the moment):

when the mouse is over an object, we compare the objects z position to the camera’s z position, the difference becomes the z position of the mouse, is this possible? and would it work? and all objects could have an invisible sphere attached to them which counts as part of the object in terms of comparing z position (for if they aim not directly at the ship)

I’ve got it to work! But I’ve been told that OnMouseOver only logs the most forward object, so if anyone can suggest a modification to my code to allow the detection of multiple potential targets so my code can select the highest priority target. Here is code I attach to objects so they can be targeted:
static var mouseOver = null;
static var mouseOverDist : float;
static var mouseOverPriority : int = 0;
var self = gameObject;
var selfPriority = 2;

``````function Start () {
if(self.tag == "aimingSphere"){
selfPriority = 1;
}
else selfPriority = 2;

Debug.Log("Self Priority is" + selfPriority + "because self is" + gameObject);
}

function setMouseOver () {
mouseOver = self;
mouseOverPriority = selfPriority;
mouseOverDist = transform.position.z;
Debug.Log("Mouse is now over " + gameObject);
}

function OnMouseOver () {
if(mouseOver == null){
setMouseOver ();
}
else if(self == SpaceShip.Target) {
setMouseOver ();
}
else if(mouseOverPriority < selfPriority) {
setMouseOver ();
}
//else if((mouseOverPriority == selfPriority) && ((self.z - Player.z) < (mouseOver.z - SpaceShip.Player.z) {
//	setMouseOver ();
//}
}

function OnMouseExit (){
mouseOver = null;
mouseOverPriority = 0;

Debug.Log("Mouse is no longer over " + gameObject);
}
``````

and this is the code I use to shoot:

``````var bulletTest : Transform;

var cam : Transform;

public static var test = [0, 2, 15, 2, 1, 1, 1000];

var names = [];

var bulletArray = [bulletTest];

public static var weapons = [test];
//<id>, <range>, <damage>, <shots>, <cooldown(1)/overheat(0)>, <time>, <prefabBullet>

var shootForce = 1000;

public var id = 0;
public var range = 1;
public var damage = 2;
public var shots = 3;
public var cooldown = 4;
public var coolTime = 5;
public var force = 6;
//These variables are just to make it easier for me when I want to access stats of weapons

public static var equippedWeapon = 0;
public static var lastShot : float;
public static var lastShotInt : int;
public static var lastWeapon : int;
public static var cooltime : float;
public static var lastWeaponShot : int;
var distanceFromShip = 15;
private var hitdist : float = 30;

public static var weaponCooldown;
public static var currentBullet : Transform;

var ray = null;
var targetPoint = null;
var targetRotation = null;

function Start () {
}

function Update () {
lastShot += Time.deltaTime;
weaponCooldown = weapons[equippedWeapon][cooldown];
hitdist = mouseOver.mouseOverDist - cam.position.z;
Shoot ();
}

function Shoot () {
if(Input.GetButton("Fire1")) {
if(weapons[equippedWeapon][cooldown])
{
if(lastShot > weaponCooldown)
{
ray = Camera.main.ScreenPointToRay (Input.mousePosition);
targetPoint = ray.GetPoint(hitdist);
targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
lastShot = 0.0;
var equippedId = test[0];
lastWeaponShot = weapons[equippedWeapon][id];
var instanceLaser = Instantiate(bulletArray[equippedId], transform.position + transform.forward*distanceFromShip, targetRotation);