# Camera control

Is there a way to know the position of any object on the screen of the main camera and convert this position to pixels so that I can control the object with the mouse?

I was trying to do this by creating a cube and setting its position to my main camera’s position and same for the eulerAngles, moved the cube a little to the Z axis ( so that I can see a tiny cube on the screen distanced from the camera ). But now I dont know if there is a math or something to convert the position of the cube (x and y) to pixels so that I can click the center of the object ( or a circle around it… ) with the mouse…

Im doing this because I wanted to make that kind of rectangle to select characters like in strategy games. If there is a better way of doing this, please let me now =D…

Oh, by the way, Im using the standard free unity. So if anyone knows how to do that but in pro version it wont do much for me ( but its cool to share so people with pro may learn something =P )

I have discovered how to do what I wanted, here is the code:

``````/*
var counter : float = 0.0;
var layer : float = 0.0;
var vector : Vector3 = Vector3.zero;
var helper : int = 0;

function Update ()
{
if (layer < 20)
{
counter += 200*Time.deltaTime;

if (counter > 1)
{
counter = 0.0;
helper += 1;

vector.y = camera.pixelHeight*0.5;
vector.z = 10 + 5*layer;
vector.x = camera.pixelWidth*0.05*helper;

var vector = camera.ScreenToWorldPoint(vector);
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

cube.transform.position = vector;

if (helper > 20)
{
layer += 1;
helper = 0;
}
}

}
}*/

var created = true;

function Update()
{
if (Input.GetButton("Fire1"))
{
if (!created)
{
var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);

cube.transform.position = camera.ScreenToWorldPoint(Input.mousePosition + Vector3(0,0,10));
//cube.transform.Translate(size.x, -size.y, 0);
created = true;
}
}
else
created = false;
}
``````

The commented part is just for testing the camera function ScreenToWorldPoint. the second adds a cube to the position Im clicking on screen.

However the current perspective camera wont place the object’s center exactly where I click. Orthographic does.

So here is my last two questions: Does anyone know if a real-time strategy game uses orthographic or perspective camera ? If perspective, is there a way to make the object’s center where I click ?

Thx!

hehehe, it seems pepole dont care about this camera thingy… So after playing around I kinda finished the basics of what I wanted…

Heres the code:

``````var created = true;
var cube 		: GameObject;
var initialPos	: Vector3 = Vector3.zero;
var finalPos	: Vector3 = Vector3.zero;

function Update()
{
if (Input.GetButton("Fire1"))
{
if (!created)
{
initialPos = Input.mousePosition;
CreateCube();
created = true;
}
finalPos = Input.mousePosition;
ResizeCube();
}
else
created = false;
}

function CreateCube()
{
cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.transform.localScale = Vector3(0.01, 0.01, 1);
cube.transform.position = camera.ScreenToWorldPoint(initialPos + Vector3(0,0,10));

var size = cube.renderer.bounds.extents;
cube.transform.Translate(size.x, -size.y, 0);
}

function ResizeCube()
{
var vIni = camera.ScreenToWorldPoint(initialPos + Vector3(0,0,10));
var vFin = camera.ScreenToWorldPoint(finalPos + Vector3(0,0,10));
var vector = vFin - vIni;

var xScale = vector.x;
var yScale = vector.y;

cube.transform.position = camera.ScreenToWorldPoint(initialPos + Vector3(0, 0, 10));
cube.transform.position += vector*0.5;

cube.transform.localScale.x = xScale;
cube.transform.localScale.y = yScale;
}
``````

CreateCube creates a cube and scale it to 0.01 on x and y axis. Then it sets its upper-left corner to the mouse position.

ResizeCube gets the current scale of both x and y axis and apply them to the cube and correct its position so that it looks like the cube is resizing towards the mouse.

It could be done with a plane… but planes are not that ease to play with since it always faces up and to face the camera you should rotate it making the axis a little wierd…

Next I think it would be wise to rescale the collider so I could use OnCollision stuff to detect if I would select a character or not… but I dont really know if that is the best way to do that…

If anyone find something better, please let us know.

actually this code needs modifications couse it wont work if the camera rotates…

I’ve discovered why the cube seemed strange when the camera rotates. It happens because the camera.ScreenToWorldPoint gives us the world coordinates, it need to be converted to local for the cube so that the scaling would work…

I have made a better code for that kinda thing, it uses the GUI.Box instead of cube…

``````var created = true;
var selection  : GameObject;
var initialPos	: Vector3 = Vector3.zero;
var finalPos	: Vector3 = Vector3.zero;

function Update()
{
if (Input.GetButton("Fire1"))
{
if (!created)
{
initialPos = Input.mousePosition;
selection = new GameObject ("SelectionCollider");
created = true;
}
finalPos = Input.mousePosition;
}
else
{
Destroy(selection);
created = false;
}
}

// Skin
var MySkin : GUISkin;

{
var worldInit = camera.ScreenToWorldPoint(initialPos + Vector3(0,0,10));
var worldEnd = camera.ScreenToWorldPoint(finalPos + Vector3(0,0,10));
var scale	= (worldEnd - worldInit);
var center	= worldInit + scale*0.5;

// Transform scale ( world ) to local
scale = selection.transform.InverseTransformDirection(scale);

selection.transform.position = center;
selection.transform.localScale = scale + Vector3(0,0,10);
selection.transform.eulerAngles = transform.eulerAngles;
}

function OnGUI()
{
GUI.skin = MySkin;

var rect = Rect(0,0,0,0);
var dx = finalPos.x - initialPos.x;
var dy = finalPos.y - initialPos.y;

if (created)
{
if (finalPos.x > initialPos.x)
{
if (finalPos.y > initialPos.y)
rect = Rect(initialPos.x,Screen.height-finalPos.y,dx,dy);
else
rect = Rect(initialPos.x,Screen.height-initialPos.y,dx,-dy);
}
else
{
if (finalPos.y > initialPos.y)
rect = Rect(finalPos.x,Screen.height-finalPos.y,-dx,dy);
else
rect = Rect(finalPos.x,Screen.height-initialPos.y,-dx,-dy);
}

GUI.Box(rect, "");
}
}
``````