My head is already ready to burst so please help. I made my camera move with W, S, A and D keys for up, down, left and right and also zoom with the mouse wheel. Everything works except for one bug: I cannot move the camera immediately after zooming, it just moves a little and drags the camera back. It only allows me to move the camera after waiting about one second or so.. wtf processing speed or what? This is the code I used: Code (csharp): private void Update () { ZoomCamera(); MoveCamera(); } private void MoveCamera() { float x = Input.GetAxis("Horizontal") * Time.deltaTime * speed; float y = Input.GetAxis("Vertical") * Time.deltaTime * speed; transform.Translate(x, y, 0); } private void ZoomCamera() { float moveY = Input.GetAxis("Mouse ScrollWheel"); if (moveY != 0) zoomDestination = transform.position + (transform.forward * moveY) * zoomSpeed; if(zoomDestination != Vector3.zero zoomDestination.y < zoomMaxY zoomDestination.y > zoomMinY) { transform.position = Vector3.Lerp(transform.position, zoomDestination, zoomTime); if (transform.position == zoomDestination) zoomDestination = Vector3.zero; } if (transform.position.y > zoomMaxY) transform.position = new Vector3(transform.position.x, zoomMaxY, transform.position.z); if (transform.position.y < zoomMinY) transform.position = new Vector3(transform.position.x, zoomMinY, transform.position.z); } Please, please help EDIT: Sorry, here are the variables: Code (csharp): public float zoomMaxY = 1; public float zoomMinY = 1; public float zoomSpeed = 0.05f; public float zoomTime = 0.25f; public Vector3 zoomDestination = Vector3.zero;
Just a guess, but the problem might have to do with the Vector3.Lerp method call on line 27. More specifically, I'm thinking it has something to do with the zoomTime variable; what is this variable and how is it calculated? Actually, now that I am looking at your code again, I'm pretty sure you also don't want to use transform.position as the first variable in the Lerp method call. The lerp should have a fixed start and end for it's cycle. You have the end part fixed, but the start is constantly changing since you're reassigning transform.position each time. Those are just some ideas, not sure if they will help you. If you don't get it figured out by tomorrow I'll try running the code myself and see if I can't figure out what's going on for sure. In the mean time, take a look at the Vector3.Lerp method in the unity docs if you haven't already! There's an example on that page that uses distance rather than time as the third variable; maybe you could do the same.
After looking at your suggestion I see that changing zoomTime to 1 the problem disappears. I only need to set my zoomSpeed so it won't go too fast/slow when zooming. The only thing I don't know is if it will zoom smoothly, but that will be a minor loss if it makes the main problem go away. So a big THANKS to you gilley033 for helping me out!
I'm glad that helped, but I'm still not completely sure what you're wanting to do. The lerp function returns a position between two points, based on a start value, an end value, and an input value between 0 and 1. If the input value is 0, the start value (in this case transform.position) is returned, and if the input value is 1, the end value (in this case zoomDestination) is returned. A value between 0 or 1 returns a position between the start and end. So when you just set zoomTime to 1, you're telling the lerp to return zoomDestination. If that's all you want, then you can replace the lerp with this instead: Code (csharp): transform.position = zoomDestination; However, I am guessing you want to smoothly zoom the camera over a short amount of time, rather than instantaneously. With that in mind, I rewrote your script. I have tested this and it should work, however I am not positive if it will produce the result you're looking for. It basically just moves the camera forward or backward via the scroll wheel. Code (csharp): public float zoomAmount = 0.05f; public float zoomSpeed = 10; public float movementSpeed = 10f; private bool zoomInProcess = false; private Vector3 zoomDestination = Vector3.zero; private Vector3 zoomStart = Vector3.zero; private float t; private float lerpStepSize; // Use this for initialization private void Start() { //The larger the zoomSpeed, the bigger the lerpStepSize, and thus the quicker the lerp lerpStepSize = 1f - 1f/zoomSpeed; if(lerpStepSize < 0f || Mathf.Approximately(0f, lerpStepSize)) lerpStepSize = .1f; else if(lerpStepSize > 1f || Mathf.Approximately(1f, lerpStepSize)) lerpStepSize = 1f; } private void Update () { ZoomCamera(); MoveCamera(); } private void MoveCamera() { float x = Input.GetAxis("Horizontal") * Time.deltaTime * movementSpeed; float y = Input.GetAxis("Vertical") * Time.deltaTime * movementSpeed; transform.Translate(x, y, 0); } private void ZoomCamera() { if(!zoomInProcess) { float moveY = Input.GetAxis("Mouse ScrollWheel"); if(moveY != 0) { zoomStart = transform.position; zoomDestination = transform.position + new Vector3(0f, 0f, moveY) * zoomAmount; zoomInProcess = true; t = 0f; //Reset lerpInterpolater back to 0 Zoom(); //Start zooming immediately } } else //Zoom in process so zoom! Zoom(); } private void Zoom() { t += lerpStepSize; //Tracks whether we should end the zooming after this method returns bool timeToEndZoom = false; //Make sure t is not greater than 1, if it is, set it to 1 and set //timeToEndZoom to true if(t > 1f) { t = 1f; timeToEndZoom = true; } //Use lerp to alter the position of the camera transform.position = Vector3.Lerp(zoomStart, zoomDestination, t); //If timeToEndZoom isn't already true, check if t == 1f. //If it is, it's time to end the zoom if(!timeToEndZoom Mathf.Approximately(1f, t)) timeToEndZoom = false; //If it's time to end the zoom, set zoomInProcess to false if(timeToEndZoom) zoomInProcess = false; } The code relating to minZoom and maxZoom was removed because I didn't know what it was being used for, but you can certainly add it back in if you want to. I used values of 100 for zoomAmount and zoomSpeed and that seemed to work well. Like I said, this will just move the camera forward and backward. If you're trying to zoom the camera without physically moving it, you may be interested in this page: http://answers.unity3d.com/questions/20693/camera-zoom-in-script.html Good luck!
I think another problem you could have is that while the Zoom is in progress, the camera position is always reassigned by the zoom function. The code posted by gilley003 ends the zoom nicely so you will be able to move your camera after the zoom is done, but won't be able to move while it's in progress. I don't have the perfect solution but if you want to move and zoom at the same time, you could store the offset from the Input.GetAxis while zooming and use it in the Lerp function. When it's done, reset the offset. Code (csharp): public float zoomAmount = 0.05f; public float zoomSpeed = 10; public float movementSpeed = 10f; private bool zoomInProcess = false; private Vector3 zoomDestination = Vector3.zero; private Vector3 zoomStart = Vector3.zero; private Vector3 zoomOffset = Vector3.zero; private float t; private float lerpStepSize; // Use this for initialization private void Start() { //The larger the zoomSpeed, the bigger the lerpStepSize, and thus the quicker the lerp lerpStepSize = 1f - 1f/zoomSpeed; if(lerpStepSize < 0f || Mathf.Approximately(0f, lerpStepSize)) lerpStepSize = .1f; else if(lerpStepSize > 1f || Mathf.Approximately(1f, lerpStepSize)) lerpStepSize = 1f; } private void Update () { ZoomCamera(); MoveCamera(); } private void MoveCamera() { float x = Input.GetAxis("Horizontal") * Time.deltaTime * movementSpeed; float y = Input.GetAxis("Vertical") * Time.deltaTime * movementSpeed; // Move immediately or store the offset to use with zoomDestination if (!zoomInProcess) transform.Translate(x, y, 0); else zoomOffset += new Vector3(x, y, 0); } private void ZoomCamera() { if(!zoomInProcess) { float moveY = Input.GetAxis("Mouse ScrollWheel"); if(moveY != 0) { zoomStart = transform.position; zoomDestination = transform.position + new Vector3(0f, 0f, moveY) * zoomAmount; zoomInProcess = true; t = 0f; //Reset lerpInterpolater back to 0 Zoom(); //Start zooming immediately } } else //Zoom in process so zoom! Zoom(); } private void Zoom() { t += lerpStepSize; //Tracks whether we should end the zooming after this method returns bool timeToEndZoom = false; //Make sure t is not greater than 1, if it is, set it to 1 and set //timeToEndZoom to true if(t > 1f) { t = 1f; timeToEndZoom = true; } //Use lerp to alter the position of the camera transform.position = Vector3.Lerp(zoomStart, zoomDestination + zoomOffset, t); //If timeToEndZoom isn't already true, check if t == 1f. //If it is, it's time to end the zoom if(!timeToEndZoom Mathf.Approximately(1f, t)) timeToEndZoom = false; //If it's time to end the zoom, set zoomInProcess to false, and reset offset if(timeToEndZoom) { zoomInProcess = false; zoomOffset = Vector3.zero; } }