Note: Each function in this article is implemented using cinemachine and camera components respectively, please extract as needed. If you have any questions, please leave a message below and I will answer them. In addition, it is not a loss to add attention to you, is it? . This article will update other functions on January 5, 2021
1. Smooth switching of multiple cameras
When there are multiple virtual cameras in the scene, closing the current main virtual camera will smoothly switch to all cameras with higher priority values in the open state. That is to say, when a camera is turned off and a camera is turned on at the same time, the lens will pan smoothly.
Implementation of FreeLocckCam and Camera
//先停再开,可以在权值相同且同时开启的情况下切换相机
//FreeLocckCam、Camera都可以使用这种方式
camerObject.SetActive (false)
camerObject.SetActive (true)
Switching speed and smooth curve can be set in the inspector
2. Reset the camera
Resetting the camera includes resetting the position, viewing angle, and viewing distance
Camera component implementation
public void ResetCamera(){
// 重置视距
this.Camera.main.OrthographicSize = this.defaultViewScale;
this.Camera.main.FieldOfView = this.defaultViewScale;
// 重置位置
this.Camera.main.tansform.position = this.defaultPos;
this.Camera.main.tansform.rotation = this.defaultRot;
}
Implementation of FreeLookCam component
Since freelook has its own look-around coordinate system, it is necessary to reset not only the camera but also the related parameters of the freelook component
public void ResetCamera(){
// 重置角度
//将binding mode改为LockToTargetWithWorldUp
freeLookCam.PreviousStateIsValid = false;
freeLookCam.m_XAxis.Value = 0;
freeLookCam.m_YAxis.Value = 0.5f;
//如果X轴位置有问题,请查看heading>bias值
// 重置视距
this.mainCineCamera.m_Lens.OrthographicSize = this.defaultViewScale;
this.mainCineCamera.m_Lens.FieldOfView = this.defaultViewScale;
// 重置位置
this.mainCineCamera.LookAt.tansform = this.LookAtDefaultPos;
this.mainCineCamera.Follow.transform = this.followDefalutPos;
}
3. Rotation Angle of View
There are two ways to rotate the viewing angle, one is to look around the camera itself as the center. The other is centered on the target, and the camera rotates around the target.
Rotate around a target with FreeLookCam
First add the freelookCam component in the scene, and then set the follow object and lookat object in the inspector. The follow object refers to the origin of the camera as it rotates around the object. Lookat refers to the position where the lens is focused. No matter how you rotate it, the camera will always face the object.
The height and radius of this rotation range can be set in the top, middle, and buttom of the inspector
public float rotateAxisSpeed_x = 3f;
public float rotateAxisSpeed_y = 3f;
public void RotateAxis(float x, float y)
{
mainCineCamera.m_XAxis.m_InputAxisValue = x * rotateAxisSpeed_x;
mainCineCamera.m_YAxis.m_InputAxisValue = y * rotateAxisSpeed_y;
}
void Update(){
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
this.RotateAxis(h,v);
}
4. Pan perspective
The so-called panning angle of view is to perform a relative panning operation on the camera under the current angle of view of the camera.
Camera component implementation
public float moveSpeedXY = 10f;
// 以前后移动速度
public float moveSpeedZ = 60f;
void Update()
{
// 获取水平及滚轮按键值 区间为 0-1f
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
float mouse = Input.GetAxis("Mouse ScrollWheel");
//调用平移的方法
transform.Translate(new Vector3(h * moveSpeedXY, v * moveSpeedXY, mouse * moveSpeedZ) * Time.deltaTime, Space.Self);
}
Implementation of FreeLocckCam component
There are two situations to consider when using this component:
1 There is a situation where there is no target to follow
This implementation is relatively simple, similar to the implementation using the Camera component above, only that it is not the camera itself that needs to be moved, but the Follow object.
2 There is a situation of following and having a target
Having a follow target means that the look-around function and the pan function need to coexist. Since the camera always faces the target when rotating the camera, if you simply move the Follow object, the angle of view will still be facing the target direction. So it is necessary to ensure that the follow object and the lookat object are at the same time convenient. Since our requirement is to "translate according to the camera's perspective", in order to avoid an infinite loop, it is necessary to establish a tracking relationship for these objects. There are also many ways to realize this function, two of which are introduced below
The first implementation method:
When panning, move the parent object of the follow and lookat targets, close the freecamera component while moving, and open it after the movement is over.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
public class CameraController: MonoBehaviour
{
// 上下左右的移动速度
public float moveSpeedXY = 10f;
// 以前后移动速度
public float moveSpeedZ = 60f;
public CinemachineFreeLook freeLook;
private bool isCameraMoving = false;
Vector3 defaultPos;
Vector3 defaultRot;
void Update()
{
// 获取水平及滚轮按键值 区间为 0-1f
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
float mouse = Input.GetAxis("Mouse ScrollWheel");
if (h + v != 0f)
{
//调用平移的方法
if (!isCameraMoving)
{
// 获取移动前的偏移
defaultPos = Camera.main.transform.position - transform.position;
defaultRot = Camera.main.transform.rotation.eulerAngles - transform.rotation.eulerAngles;
// 关闭组件避免死循环
freeLook.gameObject.SetActive(false);
isCameraMoving = true;
}
// 平移镜头
Camera.main.transform.Translate(new Vector3(h * moveSpeedXY, v * moveSpeedXY, mouse * moveSpeedZ) * Time.deltaTime, Space.Self);
}
else
{
if (isCameraMoving)
{
// 重置跟随和瞄准目标位置与主摄像机对齐
transform.position = Camera.main.transform.position - defaultPos;
transform.eulerAngles = Camera.main.transform.rotation.eulerAngles - defaultRot;
// 启动freelook
freeLook.gameObject.SetActive(true);
isCameraMoving = false;
}
}
}
}
The second way (recommended):
Keep the lookat target in line with the direction of the camera, and then let the camera's follow target follow the lookat target. When panning, just move the lookat target object. This method is more recommended, simple and reasonable.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;
public class CameraController: MonoBehaviour
{
// 上下左右的移动速度
public float moveSpeedXY = 10f;
// 以前后移动速度
public float moveSpeedZ = 60f;
public CinemachineFreeLook freeLook;
void Update()
{
//
freeLook.LookAt.transform.eulerAngles = new Vector3(0f, Camera.main.transform.rotation.eulerAngles.y, 0f);
// 获取水平及滚轮按键值 区间为 0-1f
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
float mouse = Input.GetAxis("Mouse ScrollWheel");
if (h + v != 0f)
{
freeLook.LookAt.transform.Translate(new Vector3(h * moveSpeedXY, mouse * moveSpeedZ, v * moveSpeedXY) * Time.deltaTime, Space.Self);
}
}
}
pay attention
Special attention needs to be paid when you perform a translation operation and you will find that the camera may rotate accordingly. This is not caused by our code, but caused by a function designed by cinecamera for the smooth transition of the camera. Just do the following settings:
- Find Orbits->Binding Mode in the inspector window of the freelookcam component and change it to Lock to target with world up
- Find the bady in top, middle, and buttom respectively, and set the related Damping to 0.
- Please pay attention to this point. If the above settings are invalid and there is still a certain axis shaking, then it may be that the object followed by the camera uses rigid body movement. You need to find the interpolate in the rigidbody component, and try those options to set the difference to solve the problem~! !
5. Zoom perspective
Viewing zoom is achieved by modifying the camera's FieldOfView and orthographic.
Camera component implementation
private float currentViewScale;
public float scaleSpeed = 10.0f;
public float scaleMinScale = 1.0f;
public float scaleMaxScale = 150.0f;
void Start() {
// for camera view scale
this.currentViewScale = Camera.main.orthographic?Camera.main.OrthographicSize:Camera.main.FieldOfView;
}
void Update(){
this.currentViewScale += Input.GetAxis("Mouse ScrollWheel") * this.scaleSpeed;
this.currentViewScale = Mathf.Clamp(this.currentViewScale, this.minScale, this.maxScale);
if (Camera.main.orthographic)
{
Camera.main.OrthographicSize = this.currentViewScale;
}
else
{
Camera.main.FieldOfView = this.currentViewScale;
}
}
cinemachine component implementation
private float currentViewScale;
public float scaleSpeed = 10.0f;
public float scaleMinScale = 1.0f;
public float scaleMaxScale = 150.0f;
void Start() {
// for camera view scale
this.currentViewScale = Camera.main.orthographic? mainCineCamera.m_Lens.OrthographicSize:this.currentViewScale = mainCineCamera.m_Lens.FieldOfView;
}
void Update(){
this.currentViewScale += Input.GetAxis("Mouse ScrollWheel") * this.scaleSpeed;
this.currentViewScale = Mathf.Clamp(this.currentViewScale, this.minScale, this.maxScale);
if (Camera.main.orthographic == true)
{
this.mainCineCamera.m_Lens.OrthographicSize = this.currentViewScale;
}
else
{
this.mainCineCamera.m_Lens.FieldOfView = this.currentViewScale;
}
}
6. Automatically bypass obstacles
This function is only implemented using FreeLocckCam
- The virtual camera needs to add the cinemachine collider component
- Set the action layer in the cinemachine collider
- In the cinemachine collider, you can set the way the lens surrounds the object, the distance, the number, and the smoothness, etc.