- Home /
3D camera smooth rotation and mouse wheel zoom
Hi All! I have a problem with a project: a cube in which a camera moves around in the three axis with the mouse. The XY axes are controlled by mouse X and mouse Y, and the zoom (not FOV) with the Mouse ScrollWheel. There is the script that moves the camera:
using UnityEngine;
using System.Collections;
public class CameraMotion2 : MonoBehaviour {
public float zoomSpeed = 4.0f;
public float rotationSpeed = 0.5f;
float lastMousePos;
void Update () {
// Wheel Zoom
transform.Translate (Vector3.forward * Input.GetAxis ("Mouse ScrollWheel") * zoomSpeed);
// Camera X Rotation
Vector2 xMouseEdge = MouseScreenEdge ((int)(Screen.width * 0.3f));
if(!(Mathf.Approximately (xMouseEdge.x, 0.0f))) {
//Move your camera depending on the sign of mouse.Edge.x
if (xMouseEdge.x > 0) {
//Move Left
transform.Rotate (new Vector3 (0, xMouseEdge.x, 0) * Time.deltaTime * rotationSpeed);
}
else if (xMouseEdge.x < 0) {
//Move right
transform.Rotate (new Vector3 (0, xMouseEdge.x, 0) * Time.deltaTime * rotationSpeed);
}
}
// Camera Y Rotation
Vector2 yMouseEdge = MouseScreenEdge ((int)(Screen.height * 0.3f));
if (!(Mathf.Approximately (yMouseEdge.y, 0.0f))) {
if (yMouseEdge.y > 0 && transform.rotation.x > -0.5f) {
transform.Rotate (new Vector3 (-yMouseEdge.y, 0, 0) * Time.deltaTime * rotationSpeed);
}
else if (yMouseEdge.y < 0 && transform.rotation.x < 0.5f) {
transform.Rotate (new Vector3 (-yMouseEdge.y, 0, 0) * Time.deltaTime * rotationSpeed);
}
}
}
void OnCollisionEnter () {
StartCoroutine (ResetPos (0.5f));
}
Vector2 MouseScreenEdge (int margin) {
//Margin is calculated in px from the edge of the screen
Vector2 half = new Vector2 (Screen.width * 0.5f, Screen.height * 0.5f);
//If mouse is dead center, (x,y) would be (0,0)
float x = Input.mousePosition.x - half.x;
float y = Input.mousePosition.y - half.y;
//If x is not within the edge margin, then x is 0;
//In another word, not close to the edge
if(Mathf.Abs (x) > half.x - margin) {
x += (half.x - margin) * ((x < 0) ? 1 : -1);
}
else {
x = 0.0f;
}
if(Mathf.Abs(y) > half.y - margin) {
y += (half.y - margin) * ((y < 0) ? 1 : -1);
}
else {
y = 0.0f;
}
return new Vector2(x, y);
}
IEnumerator ResetPos (float time) {
float elapsedTime = 0.0f;
Vector3 targetPos = new Vector3 (transform.position.x, transform.position.y, transform.position.z - 1.0f);
while (elapsedTime < time) {
elapsedTime += Time.deltaTime;
transform.position = Vector3.Lerp (transform.position, targetPos, (elapsedTime / time));
}
yield return null;
}
IEnumerator ResetRot (float time) {
float elapsedTime = 0.0f;
Quaternion targetRotation = Quaternion.Euler (new Vector3 (0, transform.rotation.y, transform.rotation.z));
while (elapsedTime < time) {
elapsedTime += Time.deltaTime;
transform.rotation = Quaternion.Lerp (transform.rotation, targetRotation, (elapsedTime / time));
}
yield return null;
}
}
But that have some problems... First of all at line 14: the wheel translation is no smooth (i need a sort of ease out) Second: The X rotation is activated by the mouse position Y the more it reaches the top or bottom borders of the screen, but I need that the X rotation returns back when the mouse Y returns near the center of the screen. Third: the two coroutines don't work (the animation is istance and not in the whole time setted). I know it's not a simple script, but i really need help.
PS The MouseScreenEdge is a function that calculates the amount of space from the borders of the screen.
Answer by areFranz · Apr 11, 2015 at 03:36 PM
After some month of other works in Unity, I upgrade my projects in Unity 5 and i keep some of theese... I finally found a way to move smoothly the MouseScroll Wheel and the two functions for rotating on X and Y axis. I've used only the motion and I moved the coroutines in another script attached to the icons that are shown in the scene... I've removed the collisions and replaced them with two Raycasts, one for the front of the camera and one for the back of the camera (that calculate the min distance from theborders and stop the motion at that distance with a nic click sound. Here is the full code:
using UnityEngine;
using System.Collections;
public class CameraMotion2 : MonoBehaviour {
// Mouse Scroll
public float speed = 100.0f;
public float maxAcceleration = 2.0f;
public float followSpeed = 10.0f;
public Vector3 translationVector = new Vector3(0, 0, 1);
public bool scrollWheelAcceleration = true;
public AudioClip touch;
private float timer;
private float translation;
private float position;
private float target;
private float falloff;
private float input;
void Update () {
// CAMERA IS IN BOUNDS?
RaycastHit frontHit;
RaycastHit backHit;
if (Physics.Raycast (transform.position, transform.forward, out frontHit)) {
if (frontHit.distance <= 20f && frontHit.collider.tag == "structure") {
FindObjectOfType <AudioSource> ().PlayOneShot (touch);
target = 0;
}
}
if (Physics.Raycast (transform.position, -transform.forward, out backHit)) {
if (backHit.distance <= 20f && backHit.collider.tag == "structure") {
FindObjectOfType <AudioSource> ().PlayOneShot (touch);
target = 0;
}
}
// WHEEL Z TRANSLATION
timer += Time.deltaTime;
input = Input.GetAxis ("Mouse ScrollWheel");
if (scrollWheelAcceleration)
{
if (input != 0)
{
target += Mathf.Clamp ((input / (timer * 100)) * speed, maxAcceleration * -1, maxAcceleration);
timer = 0;
}
}
else
{
target += Mathf.Clamp (input * speed, maxAcceleration * -1, maxAcceleration);
}
falloff = Mathf.Abs (position - target);
translation = Time.deltaTime * falloff * followSpeed;
if (position + 0.001 < target)
{
this.GetComponent <Transform> ().Translate (translationVector * translation * -1);
position += translation;
}
if (position - 0.001 > target)
{
this.GetComponent <Transform> ().Translate (translationVector * translation);
position -= translation;
}
// CAMERA HORIZONTAL ROTATION
float halfWidth = Screen.width * 0.5f;
float mouseXPos = Input.mousePosition.x;
float differenceX = mouseXPos - halfWidth;
float factorX = differenceX / halfWidth;
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.Euler (0, 90 * factorX, 0), Time.deltaTime);
// CAMERA VERTICAL ROTATION
float halfHeight = Screen.height * 0.5f;
float mouseYPos = Input.mousePosition.y;
float differenceY = mouseYPos - halfHeight;
float factorY = differenceY / halfHeight;
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.Euler (-45 * factorY, 0, 0), Time.deltaTime);
}
}
This gives me the following errors:
Assets/$$anonymous$$WZoom2.cs(6,24): error CS1519: Unexpected symbol `:' in class, struct, or interface member declaration
Assets/$$anonymous$$WZoom2.cs(6,32): error CS1519: Unexpected symbol `=' in class, struct, or interface member declaration
Assets/$$anonymous$$WZoom2.cs(7,24): error CS1519: Unexpected symbol `:' in class, struct, or interface member declaration
Assets/$$anonymous$$WZoom2.cs(7,32): error CS1519: Unexpected symbol `=' in class, struct, or interface member declaration
Assets/$$anonymous$$WZoom2.cs(8,22): error CS1519: Unexpected symbol `:' in class, struct, or interface member declaration
Assets/$$anonymous$$WZoom2.cs(8,30): error CS1519: Unexpected symbol `=' in class, struct, or interface member declaration
Answer by rams_123 · Jan 14, 2016 at 11:45 AM
if (position - 0.001f > target) { this.GetComponent ().Translate (translationVector * translation); position -= translation; }
Your answer
Follow this Question
Related Questions
Limiting vertical camera rotation 0 Answers
Top down shooter camera follow cursor 2 Answers
C# Decrease Mouse Sensitivity Camera Move 0 Answers
Why is the camera going crazy when the player moves? 0 Answers
Change from 3D to 2D 1 Answer