[SOLVED] Smoothly and slowly move Camera Point A to B??

What I’m aiming to achieve here is:

When you hit the V key, the camera smoothly and slowly moves from a first person view(fpv) to a third person view(tpv).

I want to be able to control the smoothness of the movement, and length of time it takes to go from point A to point B.

Here’s my code, so far I have the camera moving from fpvPoint to tpvPoint just fine, but it snaps instantly into position with no smooth/slow transition at all.

I’ve been stuck on this for four days now so if you’ve any idea let me know, I’ve tried many different methods.

if (Input.GetButtonDown ("View"))
	{
	//Toggle First/Third Person View Positions
		fpCam = !fpCam;
	}  
	
	var smooth : float = 10.0;
	var vel : float = 0.00;
	if (Input.GetButtonDown ("View"))
	{  
	//If First Person View = True, then move camera from FPVPoint and resolve crosshairs
		if (fpCam == true)
		{
			var moveCamFromX = Mathf.SmoothDamp(fpvPoint.transform.position.x, tpvPoint.transform.position.x, vel, smooth);
			var moveCamFromY = Mathf.SmoothDamp(fpvPoint.transform.position.y, tpvPoint.transform.position.y, vel, smooth);
			var moveCamFromZ = Mathf.SmoothDamp(fpvPoint.transform.position.z, tpvPoint.transform.position.z, vel, smooth);
			
			fpCamera.transform.position.x = moveCamFromX;
			fpCamera.transform.position.y = moveCamFromY;
			fpCamera.transform.position.z = moveCamFromZ;
			
			fpcrosshair.active = false;
			tpcrosshair.active = true;		
		}
	//If First Person View = False, then move camera to FPVPoint and resolve crosshairs
		else
		{
			var moveCamToX = Mathf.SmoothDamp(tpvPoint.transform.position.x, fpvPoint.transform.position.x, vel, smooth);   
			var moveCamToY = Mathf.SmoothDamp(tpvPoint.transform.position.y, fpvPoint.transform.position.y, vel, smooth);   
			var moveCamToZ = Mathf.SmoothDamp(tpvPoint.transform.position.z, fpvPoint.transform.position.z, vel, smooth);   
			
			fpCamera.transform.position.x = moveCamToX;
			fpCamera.transform.position.y = moveCamToY;
			fpCamera.transform.position.z = moveCamToZ;
			
			tpcrosshair.active = false;
			fpcrosshair.active = true;
		}
	}

Thanks for reading :]

This should help you out:

I did actually try using a Lerp before and either got error messages like “Cannot convert float to Vector3” or I just got the same results as above.

Could you maybe give me an example of how a lerp would be used in this situation?

http://www.unifycommunity.com/wiki/index.php?title=Scripts#Animation_Controllers

–Eric

A simple one I did was to use some trigonometry like Sin or Cos to calculate values from one side of a curve to another, then scale it to fit into a 0 to 1.0 range, then multiply that by the position along a straight line between the two points. Thus it starts out very smoothly, speeds up, slows down, and ends smoothly.

Some code (untested, but based on something I did in 2D in another language):

		EndX=StartX+((EndX-StartX)*((Cos((TweenPosition*180)+181))+1.0)/2.0)	'Return the tweened X coordinate
		EndY=StartY+((EndY-StartY)*((Cos((TweenPosition*180)+181))+1.0)/2.0)	'Return the tweened Y coordinate
		EndZ=StartZ+((EndZ-StartZ)*((Cos((TweenPosition*180)+181))+1.0)/2.0)	'Return the tweened Z coordinate

Use the same start and end coords each time and just modify TweenPosition 0…1 which you can increment with equal-sized steps each frame. The above code is from the BlitzMax basic language. Once you’ve calculated EndX,EndY you need to set your camera’s transform.position to it.

If you need to transition between two rotations of the camera, you could use similar code and use rotation degrees for Start and End variables.

Cos is the Cosine function, not sure what Unity’s syntax is, maybe like Mathf.Cos or something?

Thanks for the replies guys, I decided to go with the iTween method as it gives you a lot of control over the movement, and also it seemed simpler.

Although, for some reason it doesn’t seem to work in an if statement.

I have this short script attached to a cube as a test.

function update()
{
	if (Input.GetButtonDown ("View"))
	{
		iTween.moveTo(gameObject, {"y" : 3.5});
	}
}

I’ve double checked the View input, and even tried using GetKeyDown, but for some reason it’s just not working.

This code works fine

function Start()
{
	iTween.moveTo(gameObject, {"y" : 3.5});
}

Am I missing something obvious here or can you just not do this with iTween?

You don’t want to fire a moveTo in an Update loop. Will moveToUpdate work for you? If not set a variable to false when you fire that iTween that won’t allow it to refire that iTween until iTween can fire an onComplete callback that will reset the variable to true. Vague I know but I hope it helps some.

Thanks for your reply! Great to see you guys are active on the forums :]

I’m going to try your method, but to be honest I’m not experienced with callbacks, nor do I really know what function types to use, and when. I’m still quite new to this. :stuck_out_tongue:

Answered this for someone a little while ago. Any chance it helps some?

var aimDistance : float = 5.6; 
var prevAimDistance : float; 
var tweening : boolean; 

function Update () { 
   if(!tweening  aimDistance != prevAimDistance){ 
      if(aimDistance > 5.5){ 
         iTween.colorTo(gameObject,{"color":Color.red, "onStart":"tweenStarted", "onComplete":"tweenCompleted"}); 
      }else if(aimDistance < 5.0  aimDistance > 3.5){ 
         iTween.colorTo(gameObject,{"color":Color.yellow, "onStart":"tweenStarted", "onComplete":"tweenCompleted"}); 
      }else if(aimDistance < 3.5){ 
         iTween.colorTo(gameObject,{"color":Color.green, "onStart":"tweenStarted", "onComplete":"tweenCompleted"}); 
      } 
   }    
} 

function tweenStarted(){ 
   tweening=true; 
   prevAimDistance=aimDistance; 
} 

function tweenCompleted(){ 
   tweening=false; 
}

Good luck!

Ok, got it to work, iTween really is awesome, the results are better than I had hoped for.

If you drop this script on a cube with a transform of 0,0,0 and setup the input for the “View” button (I have it mapped to V), when you hit the View key the cube will smoothly move up 1 unit, and when you hit it again it will smoothly move down one unit.

private var moveCube : boolean;
moveCube = false;

function Update()
{
	if (Input.GetButtonDown ("View"))
	{
		moveCube = !moveCube;
	}
	if (moveCube == true)
	{
		if (Input.GetButtonDown ("View"))
		{
			iTween.moveTo(this.gameObject, {"y" : 1.0});
		}
	}
	else
	{
		if (Input.GetButtonDown ("View"))
		{
			iTween.moveTo(this.gameObject, {"y" : 0.0});
		}
	}
}

You will need iTween for this to work http://itween.pixelplacement.com/

The way to do this without the help of the iTween library is not as straight forward as I would have hoped, but does use the Lerp function.

For simplification, I’ll use the Mathf.Lerp function to demonstrate.

float result;
float t = 0.0F;
float speed = 30.0F;

public void Update(){
    t += Time.deltaTime;
    result = Mathf.Lerp( 0, 100, t / speed );

}

This will increment result from 0 to 100 over 30 seconds. The same method can be used for the Vector3.Lerp, replacing the appropriate values with Vector3’s instead of floats.

3 Likes