- Home /
3d camera control
I have a camera that is used like an overhead camera and i want to be able to use it in three dimensions. I would like to be able to zoom in and out with the mouse wheel and if i click down the middel mouse button i can rotate the camera. something like a homeworld kind of camera or black and white. how can i do this?
you can add an input switch to the camera controls to detect the middle mouse button, and apply a rotation script in the case that it's depressed.
You can also have the camera move slightly along its forward axis when you move the mousewheel. I don't have time tonight to write code for it or I would have provided an example, hopefully someone can help out or if not I might be able to tomorrow.
Important question though: did you want the camera to rotate in place, or rotate around a viewpoint?
preferable around a view point. This camera is basicaly supposed to switch from a fps camera to an rts style camera. so probably start of centerd around the player and later centered on the selected unit.
Answer by Alec-Slayden · Feb 13, 2011 at 07:27 PM
What you can do is apply the preset MouseOrbit script to your camera (in Camera-control section of the components drop-down). This will give you a basis for rotating around a target. However, we don't want to use the script as is, because it will be actively rotating your view with the mouse all the time, and you can't zoom yet.
We'll add the zoom function first. I'm assuming we probably want to be able to zoom even when we're not rotating, so we'll put that separate from the rotation code (this is all javascript).
Open your mouseorbit script and add the following variables to the variable list:
var maxDist : float = 200;
var minDist : float = 30;
var zoomSpeed : float = 5;
We'll use these to prevent our players from zooming in way too close or off into space, and to control the rate of zooming. You can adjust them in the inspector to fine tune. Next, scroll down to the late update function and add the following code:
if (Input.GetAxis("Mouse ScrollWheel") < 0 && distance < maxDist){
distance += zoomSpeed;
transform.Translate(Vector3.forward * -zoomSpeed);
}
Adding the above conditions will allow us to zoom OUT with the mousewheel. The GetAxis retrieves a positive or negative number, depending on which way we're scrolling the wheel. A negative number mean's we're scrolling down. We don't want to move the camera back more if we're at our maximum distance, so we make sure distance is less than maxDist before changing it. If it is, we add the zoomspeed to distance, which is used while we're rotating, and we translate our camera backward the same amount, because we want to zoom out even when we're not rotating. If we don't adjust these the same amount, the camera will 'pop' when you start to rotate it, using whatever 'distance' is set to. This code makes sure that we'll always be at that distance before we rotate.
Next we add the similar condition to zoom IN:
if (Input.GetAxis("Mouse ScrollWheel") > 0 && distance > minDist){
distance -= zoomSpeed;
transform.Translate(Vector3.forward * zoomSpeed);
}
When the Mousewheel is moving the other direction: distance is checked against the minimum instead of the maximum, and we're lowering the distance variable and moving the camera forward this time, not backward.
Now to make sure it rotates when we want it to. The script currently is set to do its thing only when it has a target, as shown in the next line:
If (target) {
We can add the mouse button requirement here. The middle mouse is mouse button 2, so we turn this line into:
If (target && Input.GetMouseButton(2)) {
Now our camera will only rotate around an object if it has a target and the middle mouse button is down.
In the inspector you can adjust the maximum and minimum Y to make sure the camera doesn't rotate underground or too high for your game.
What I recommend now is nesting your Camera in an empty game object that you'll use as the view target. If you move this object around the map, it will move the camera with it, and you'll always be ready to rotate the camera, even without a unit to look at. You can have this parent object go to unit positions when you want to view those units, and even make the units the parent of this 'camera crane', if they're moving.
To make sure the first rotation doesn't pop into place, you should make sure that your camera is the same distance away from the viewpoint as the distance variable. There are a couple ways to do this, I find the easiest way is to run the program and allow it to pop, then look at the camera position in the inspector, and have that be the camera's start position. If you have a specific position you want the camera to start at, you'll want to detect the distance to viewpoint and adjust the 'distance' variable to match.
As you get comfortable with the script, you might consider using a form of LERP to zoom more smoothly. However, this method of zooming should do nicely for most applications.
I hope this helped!
Regarding switching to a FPS camera, you can code it to enable and disable the mouseorbit / FPS camera depending on the game mode.
Thx, can I ask you to post the full script, I am not sure whether I am placing it correct. I get an error message refering to the static function, which I have not edited.
For instace is it: "If (target) {If (target && Input.Get$$anonymous$$ouseButton(2)) {" , or just "{If (target && Input.Get$$anonymous$$ouseButton(2)) {" ?
and where do you place it?
Also can I parent light to the camera?
@BDman: You have to replace If (target)
with If (target && Input.Get$$anonymous$$ouseButton(2))
The if (Input.GetAxis("$$anonymous$$ouse ScrollWheel") < 0 && distance < maxDist){
code etc. should be placed inside the "LateUpdate" function at the end (right before the closing "}")
Answer by Edyvargas · Sep 07, 2011 at 10:33 PM
Hi friend, i try this code and works fine, ill let you the complete code here (MouseOrbit.js with changes), and thanks to the user who assist us with this code!:
// Codigo con parametros aumentados para hacer zoom in y zoom out con el scroll del mouse:
var target : Transform; var distance = 10.0;
var xSpeed = 250.0; var ySpeed = 120.0;
var yMinLimit = -20; var yMaxLimit = 80;
// Aumentado esto: var maxDist : float = 200; var minDist : float = 30; var zoomSpeed : float = 5; // hasta aca
private var x = 0.0; private var y = 0.0;
@script AddComponentMenu("Camera-Control/Mouse Orbit")
function Start () { var angles = transform.eulerAngles; x = angles.y; y = angles.x;
// Make the rigid body not change rotation
if (rigidbody)
rigidbody.freezeRotation = true;
}
function LateUpdate () { if (target && Input.GetMouseButton(2)) { x += Input.GetAxis("Mouse X") xSpeed 0.02; y -= Input.GetAxis("Mouse Y") ySpeed 0.02;
y = ClampAngle(y, yMinLimit, yMaxLimit);
var rotation = Quaternion.Euler(y, x, 0);
var position = rotation * Vector3(0.0, 0.0, -distance) + target.position;
transform.rotation = rotation;
transform.position = position;
}
// Aumentado esto:
if (Input.GetAxis("Mouse ScrollWheel") < 0 && distance < maxDist){
distance += zoomSpeed;
transform.Translate(Vector3.forward * -zoomSpeed);
}
// hasta aca
// Aumentado esto:
if (Input.GetAxis("Mouse ScrollWheel") > 0 && distance > minDist){
distance -= zoomSpeed;
transform.Translate(Vector3.forward * zoomSpeed);
} // hasta aca }
static function ClampAngle (angle : float, min : float, max : float) { if (angle < -360) angle += 360; if (angle > 360) angle -= 360; return Mathf.Clamp (angle, min, max); }
Answer by Edyvargas · Sep 07, 2011 at 11:00 PM
I need a code to make zoom in and out in the depth field, like using binoculars to see far away, anybody knows how to do this?, Thank you.
You should ask this in a separate question, it's the way the site is designed and you're more likely to get an answer :)
You are right, i will do that, thank you for the advice :).