- Home /
How to lerp between cameras on a UI button click?
I am trying to set up a UI button that, when the user clicks it, it calls to a camera manager that will either lerp from one camera object to another, fade-in/fade-out to another camera object, or just snap to another camera object. The problem I am having is that the co-routine I am calling when the button is clicked does not seem to wait() and allow the lerp to finish. The camera moves a bit when I click but it seems to get interrupted, which is what I thought the co-routine yield would prevent. This is the OnGUI() function code that is in my HUD_mgr script:
void OnGUI(){
if(!next_Btn){
Debug.LogError("Please assign a texture on the inspector");
return;
}
if(GUI.Button(new Rect(10,10,50,50), next_Btn))
{
Debug.Log("Clicked the button. Yippee...");
camera_Mgr.SendMessage("switchCamera");
}
}
and here is the switchCamera() function code that is within my Camera_mgr script:
IEnumerator switchCamera(){ var duration = Time.deltaTime*3;
Vector3 pos = main_Camera.transform.position;
Quaternion rot = main_Camera.transform.rotation;
main_Camera.transform.position = Vector3.Lerp(pos, second_Camera.transform.position, duration);
main_Camera.transform.rotation = Quaternion.Lerp(rot, second_Camera.transform.rotation, duration);
yield return new WaitForSeconds(duration);
}
I am guessing that the fact that OnGUI() is called several times a frame is what is stomping my camera lerp just after it starts. However, if the yield does not work then what should I do? FYI, the snap-to works just fine. It's the lerp and fade-in/fade-out that do not seem to complete properly.
Answer by Tim-Michels · Nov 16, 2012 at 08:02 AM
I took a look at your code, and what you're doing wrong is, you don't set the position and rotation every frame. It only gets set once, whereafter your WaitForSecondsis called. After that WaitForSeconds, your Coroutine will stop and nothing will happen further with your camera.
You should also know that the third parameter of the Lerp function should run from 0 to 1 if you're animating something like this, but to illustrate this to you, I've re-written your coroutine. You should check if this works, but also really try to understand what's happening.
I use this technique all the time when animating stuff, and it's a really powerfull way of doing a short animation sequence.
IEnumerator switchCamera()
{
var animSpeed = 0.5f;
Vector3 pos = main_Camera.transform.position;
Quaternion rot = main_Camera.transform.rotation;
float progress = 0.0f; //This value is used for LERP
while (progress < 1.0f)
{
main_Camera.transform.position = Vector3.Lerp(pos, second_Camera.transform.position, progress);
main_Camera.transform.rotation = Quaternion.Lerp(rot, second_Camera.transform.rotation, progress);
yield return new WaitForEndOfFrame();
progress += Time.deltaTime * animSpeed;
}
//Set final transform
main_Camera.transform.position = second_Camera.transform.position;
main_Camera.transform.rotation = second_Camera.transform.rotation;
}
Please give a thumbs up/mark as answered if this helped you out. Good luck ;)
Answer by Seth-Bergman · Nov 16, 2012 at 07:57 AM
The problem here is that using WaitForSeconds does not cause the method to loop.. It just pauses within the method call:
IEnumerator Example(){
//do something
yield return new WaitForSeconds(1);
//do a second thing after one second
}// The end
In your example, the yield is pointless, since nothing happens after it..
Second, you are simply moving your main camera to the position of your other camera, not switching cameras as stated.. Let's start with the simplest possible method, to as you put it "just snap" to the other camera:
void OnGUI(){
if(!next_Btn){
Debug.LogError("Please assign a texture on the inspector");
return;
}
if(GUI.Button(new Rect(10,10,50,50), next_Btn))
{
Debug.Log("Clicked the button. Yippee...");
camera_Mgr.cameraOne = !camera_Mgr.cameraOne;
}
}
And the camera script:
public boolean cameraOne = true;
public Camera main_Camera;
public Camera second_Camera;
void Update(){
if(cameraOne){
main_Camera.enabled = true;
second_Camera.enabled = false;
}
else{
main_Camera.enabled = false;
second_Camera.enabled = true;
}
}
By toggling a variable (cameraOne) , we are making the current camera state easily available.. then we just check cameraOne and turn on the appropriate camera (based on whether it is true or false). This will also make the lerping thing easy, since we can just use Update()..
camera script version 2:
public boolean cameraOne = true;
public Transform positionA; // you could just use an empty GameObject for these
public Transform positionB; // a camera will work too, but it's less efficient
private Transform target;
public Camera main_Camera;
void Update(){
float duration = Time.deltaTime*3;
Vector3 pos = main_Camera.transform.position;
Quaternion rot = main_Camera.transform.rotation;
if(cameraOne)
target = positionA;
else
target = positionB;
main_Camera.transform.position = Vector3.Lerp(pos, target.position, duration);
main_Camera.transform.rotation = Quaternion.Lerp(rot, target.rotation, duration);
}
for fading between cameras, maybe have a look at this:
Your answer
Follow this Question
Related Questions
Customizing GUI buttons 1 Answer
ignore left mouse button click in game when clicking on gui buttons 1 Answer
How to link gui buttons to seperate scripts? 1 Answer
3D menu camera rotation issue. 0 Answers
Smooth Camera Angle Scroll 1 Answer