Third person camera (89095)

Hello
I have a third person camera that
-when not moving a player can freely look around the character
-otherwise it goes behind the character (lookat) and on moving the mouse the character rotates,
but I try to achieve that when the player stop moving the camera remains still when it last was
here is the code:

if(target && !GuiToggled())
{

    	x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;

// y -= Input.GetAxis(“Mouse Y”) * ySpeed * 0.02f;

// y = ClampAngle(y, yMinLimit, yMaxLimit);

    	Quaternion rotation = Quaternion.Euler(0, x, 0);
		
		// calculate the desired distance 
        desiredDistance -= Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs (desiredDistance); 
        desiredDistance = Mathf.Clamp (desiredDistance, minDistance, maxDistance); 
        correctedDistance = desiredDistance; 
		
    	vTargetOffset = new Vector3 (0, -targetHeight, 0);
        Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset); 
		
		RaycastHit collisionHit; 
        Vector3 trueTargetPosition = new Vector3 (target.position.x, target.position.y + targetHeight, target.position.z); 

        // if there was a collision, correct the camera position and calculate the corrected distance 
        bool isCorrected = false; 
        if (Physics.Linecast (trueTargetPosition, position, out collisionHit, collisionLayers.value)) 
        { 
        	// calculate the distance from the original estimated position to the collision location,
        	// subtracting out a safety "offset" distance from the object we hit.  The offset will help
        	// keep the camera from being right on top of the surface we hit, which usually shows up as
        	// the surface geometry getting partially clipped by the camera's front clipping plane.
        	correctedDistance = Vector3.Distance (trueTargetPosition, collisionHit.point) - offsetFromWall; 
        	isCorrected = true;
        }

    	// For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance 
    	currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp (currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance; 

		// keep within legal limits
    	currentDistance = Mathf.Clamp (currentDistance, minDistance, maxDistance); 

   		// recalculate position based on the new currentDistance 
    	position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset); 
    	_myTransform.rotation = rotation;
    	_myTransform.position = position;
		if(moving)
		{
			RotateMovement();
    	}

private void RotateMovement()
	{
		float rotateSpeed = 5f;
		float horizontal = Input.GetAxis("Mouse X") * rotateSpeed;
        target.transform.Rotate(0, horizontal, 0);
        float desiredAngle = target.transform.eulerAngles.y;
        Quaternion rotation = Quaternion.Euler(0, desiredAngle, 0);
        transform.position = target.transform.position - (rotation * offset);
        transform.LookAt(GameObject.Find("Lookat").transform);
		lastRotation = transform.rotation;
	}

1 Answer

1

basically you want to stop the camera from Automatically moving, which is caused by an automatic angle being set.
that would be these lines here,

        public Transform target;
        public float x;
        float xSpeed = 20;
        float zoomRate = 2f;
        float desiredDistance;
        float correctedDistance;
        float targetHeight;
        float minDistance = 3;
        float maxDistance = 12;
        float offsetFromWall = .3f;
        float currentDistance;
        float zoomDampening = 0.1f;
        public Vector3 offset;
       public  float desiredAngle;
        public bool moving = true;
        Quaternion lastRotation;
    
      Vector3  vTargetOffset = Vector3.up;
    
      public void LateUpdate()
      {
    
          if (target)
          {
    
              x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
              // y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
    
              // y = ClampAngle(y, yMinLimit, yMaxLimit);
    
              Quaternion rotation = Quaternion.Euler(0, x, 0);
    
              // calculate the desired distance 
              desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
              desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
              correctedDistance = desiredDistance;
    
              vTargetOffset = new Vector3(0, -targetHeight, 0);
              Vector3 position = target.position - (rotation * Vector3.forward * desiredDistance + vTargetOffset);
    
              RaycastHit collisionHit;
              Vector3 trueTargetPosition = new Vector3(target.position.x, target.position.y + targetHeight, target.position.z);
    
              // if there was a collision, correct the camera position and calculate the corrected distance 
              bool isCorrected = false;
              if (Physics.Linecast(trueTargetPosition, position, out collisionHit))
              {
                  // calculate the distance from the original estimated position to the collision location,
                  // subtracting out a safety "offset" distance from the object we hit.  The offset will help
                  // keep the camera from being right on top of the surface we hit, which usually shows up as
                  // the surface geometry getting partially clipped by the camera's front clipping plane.
                  correctedDistance = Vector3.Distance(trueTargetPosition, collisionHit.point) - offsetFromWall;
                  isCorrected = true;
              }
    
              // For smoothing, lerp distance only if either distance wasn't corrected, or correctedDistance is more than currentDistance 
              currentDistance = !isCorrected || correctedDistance > currentDistance ? Mathf.Lerp(currentDistance, correctedDistance, Time.deltaTime * zoomDampening) : correctedDistance;
    
              // keep within legal limits
              currentDistance = Mathf.Clamp(currentDistance, minDistance, maxDistance);
    
              // recalculate position based on the new currentDistance 
              position = target.position - (rotation * Vector3.forward * currentDistance + vTargetOffset);
              transform.rotation = rotation;
              transform.position = position;
    
              RotateMovement();
            
          }
      }
    private void RotateMovement()
        {
           float rotateSpeed = 5f;
           float horizontal = Input.GetAxis("Mouse X") * rotateSpeed;
    
         
            if (moving)
            {
                x = 0;
                target.transform.Rotate(0, horizontal, 0);
                desiredAngle = target.transform.eulerAngles.y;
            }
    
            Quaternion rotation = Quaternion.Euler(0, desiredAngle + x, 0);
            transform.position = target.transform.position - (rotation * offset);
            transform.LookAt(GameObject.Find("LookAt").transform);
           lastRotation = transform.rotation;
        }
    }

then make rotation and moving a member wise variable. also removing the If(moving) in your original code that way the RotateFunction is called to apply the movements sent by the player. nice script btw.

EDIT: the whole time i thought this was an orbit script, it was really a follow.

thanks for the comment Im new to this part of unity (angles, vectors and such) so if i basicly want to set my own rotation i just use the last rotation convert it to an angle and calculate with that the not moving rotation?

yes if you want to do it that way can: if(!moving) { rotation = Quaternion.Euler(0, desiredAngle, 0); //stop this line when player is stationary } else { rotation = Quaternion.Euler(lastRotation.euler + new Vector3 (0, x, 0)); } sorry for the poor formatting, this editor hates me. also you may want to do something about that input x += , you adding 1 * speed each frame, so your camera may go spazzo, if it does let me know.

thanks so much for the help gonna try it right now :)

does it only jitter when you move the camera? does the camera move? does it only jitter when you stop moving the player? try this; float desiredAngle = target.transform.eulerAngles.y; if(!moving) { desiredAngle = 0; } rotation = Quaternion.Euler(0, desiredAngle + x, 0));

it didnt help what happens is that my camera goes like +2 or 3 above the character and when he moves it follows he instantly returns to his for position and the camera is circling around in a wierd way I think i found the reason, the if statement is invalid because this function occurs only when moving so it will always skip to the else