Hi. I am a beginner. I have set a Cinemachine FreeLook camera on my top down view project. I want to smoothly rotate the camera around the X axis in 45 degree increments by using keyboard inputs Q and E . The code I attached to the camera works rotating the camera but it instantly increases to the set amount. I tried Mathf.SmoothDamp and SmoothDampAngle but i don’t understand how to make it work. I also tried increasing the Input Axis Value to a set amount and stopping it when reaching 45 degrees but could not make it work either.
Any help on implementing a smooth and accurate 45 degree movement will be appreciated.
This is the simple script i wrote:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
public class CameraRotate : MonoBehaviour
{
public CinemachineFreeLook vCam;
[SerializeField] private int rotateAmount = 45;
// Start is called before the first frame update
void Start()
{
vCam = GetComponent<CinemachineFreeLook>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
RotateCameraRight();
}
else if (Input.GetKeyDown(KeyCode.E))
{
RotateCameraLeft();
}
}
private void RotateCameraRight()
{
vCam.m_XAxis.Value += rotateAmount;
}
private void RotateCameraLeft()
{
vCam.m_XAxis.Value -= rotateAmount;
}
}
Thanks for the reply. The reason I am using freelook its because as a beginner it was really easy to set up and use the TopRig, MidRig and and BottomRig to control view distance using the Mouse ScrollWheel. I was trying to achieve a camera system very similar to the one on the game Dont StarveTogether.
When a key is pressed, store the desired destination value as a member variable. In Update(), if the current value does not match the destination, modify it to approach the destination value. Eventually, it will reach the target value.
I would use FramingTransposer in the Body for a game like that.
To position the camera, modify the X rotation value of the vcam (probably around ~70).
For zooming, you can modify the Framing Transposer’s Camera Distance parameter.
For accurate, 45 degree turns you can directly control the vcam’s Y rotation value.
Thank you so much for you reply. You got me to look at the problem in a different way than i was thinking and that led me to solve it. Like i said I am a beginner so i don’t know if i used the most effective or best way but it works. Thank you!
If anyone else is looking to solve this problem, this is how i did it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
public class FreeLookRotate : MonoBehaviour
{
public CinemachineFreeLook vCam;
[SerializeField] private float rotateAmount = 45;
[SerializeField] private float transitionTime = .3f;
private float initialPosition = 0;
private float targetPosition = 0;
private float t = 0f;
private bool canMove = true;
// Start is called before the first frame update
void Start()
{
vCam = GetComponent<CinemachineFreeLook>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Q) && canMove)
{
RotateCameraRight();
}
else if (Input.GetKeyDown(KeyCode.E) && canMove)
{
RotateCameraLeft();
}
if (initialPosition != targetPosition)
{
if (t > 1)
{
return;
}
t += Time.deltaTime / transitionTime;
float newPosition = Mathf.SmoothStep(initialPosition, targetPosition, t);
vCam.m_XAxis.Value = newPosition;
if (targetPosition == vCam.m_XAxis.Value)
{
canMove = true;
}
else
{
canMove = false;
}
}
}
private void RotateCameraRight()
{
initialPosition = vCam.m_XAxis.Value;
targetPosition = (initialPosition + rotateAmount);
t = 0;
}
private void RotateCameraLeft()
{
initialPosition = vCam.m_XAxis.Value;
targetPosition = (initialPosition - rotateAmount);
t = 0;
}
}
Thanks. I’m self taught and have a career on something that has nothing to do with computers, so i spent a few minutes searching for terms like “Unity slush” and “C# slush” with no success but I finally went searching for how to compare floats and decided this was a simple solution for me. If you think there is a better way please let me know. I really appreciate the help!
using UnityEngine;
using Cinemachine;
public class FreeLookRotate : MonoBehaviour
{
public CinemachineFreeLook vCam;
[SerializeField] private float rotateAmount = 45;
[SerializeField] private float transitionTime = .3f;
[SerializeField] private float initialPosition = 0;
[SerializeField] private float targetPosition = 0;
private float t = 0f;
private float slush = .005f;
private bool canMove = true;
// Start is called before the first frame update
void Start()
{
vCam = GetComponent<CinemachineFreeLook>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Q) && canMove)
{
RotateCameraRight();
}
else if (Input.GetKeyDown(KeyCode.E) && canMove)
{
RotateCameraLeft();
}
if (initialPosition != targetPosition)
{
if (t > 1)
{
return;
}
t += Time.deltaTime / transitionTime;
float newPosition = Mathf.SmoothStep(initialPosition, targetPosition, t);
vCam.m_XAxis.Value = newPosition;
/*if (targetPosition == vCam.m_XAxis.Value)
{
canMove = true;
}
else
{
canMove = false;
}*/
if (vCam.m_XAxis.Value >= targetPosition - slush && vCam.m_XAxis.Value <= targetPosition + slush)
{
canMove = true;
}
else
{
canMove = false;
}
}
}
private void RotateCameraRight()
{
initialPosition = vCam.m_XAxis.Value;
targetPosition = (initialPosition + rotateAmount);
t = 0;
}
private void RotateCameraLeft()
{
initialPosition = vCam.m_XAxis.Value;
targetPosition = (initialPosition - rotateAmount);
t = 0;
}
}
float tolerance = 0.0001f; // this value is arbitrary, adjust it for your precision needs
if (Math.Abs(a - b) < tolerance)
{
// float a and b are equal (within tolerance of each other)
}