本篇文章主要是创建一个相机控制器
功能介绍:
- 为策略游戏构建一个摄像机系统
- 保持相机集中在一点
- 增加平滑的移动、旋转、缩放
场景搭建:
- 便于观察,场景的元素很简单,一个平面,一个Cube即可
- 新建一个空对象作为相机的父物体CrameraRig,设置一个初始位置,将相机拖入这个空物体中,设置相机的Transform
3.整个场景的Hierachy的结构如下
下面开始代码部分了
代码部分(这里做了两种控制方式 ):
一、 键盘控制
- 变量声明
// 单例
public static CameraController instance;
// 当前相机
public Transform cameraTransfrom;
// 移动速度
public float movementSpeed = 2.0f;
// 移动时间
public float movementTime = 5.0f;
// 旋转速率
public float rotationAmount = 2.0f;
// 缩放速率
public Vector3 zoomAmount = Vector2.one * 2;
// 移动后的位置、旋转、缩放值
private Vector3 newPosition;
private Quaternion newRotation;
private Vector3 newZoom;
- 初始化
void Start()
{
instance = this;
newPosition = transform.position;
newRotation = transform.rotation;
newZoom = cameraTransfrom.localPosition;
}
- 键盘控制
void HanldeMovementInput()
{
//上
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
newPosition += (transform.forward * movementSpeed);
}
//下
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
newPosition += (transform.forward * -movementSpeed);
}
//左
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
newPosition += (transform.right * -movementSpeed);
}
//右
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
newPosition += (transform.right * movementSpeed);
}
//左旋转
if (Input.GetKey(KeyCode.Q))
{
newRotation *= Quaternion.Euler(Vector3.up * rotationAmount);
}
//右旋转
if (Input.GetKey(KeyCode.E))
{
newRotation *= Quaternion.Euler(Vector3.up * -rotationAmount);
}
if (Input.GetKey(KeyCode.R))
{
newZoom += zoomAmount;
}
if (Input.GetKey(KeyCode.F))
{
newZoom -= zoomAmount;
}
transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, Time.deltaTime * movementTime);
transform.position = Vector3.Lerp(transform.position, newPosition, Time.deltaTime * movementTime);
cameraTransfrom.localPosition = Vector3.Lerp(cameraTransfrom.localPosition, newZoom, Time.deltaTime * movementSpeed);
}
- Update函数监听键盘输入事件
void Update()
{
HanldeMovementInput();
}
演示效果
二、 鼠标控制
在鼠标控制部分增加了一些可控制的功能,如
- 移动范围的限制(防止跑出地图边界)
- 旋转角度限制(防止相机翻转)
- 相机远近距离的限制
- 控制相机XZ平面的角度
- 变量声明
// 单例
public static CameraController instance;
// 相机
public Transform cameraTransfrom;
// 欧拉角的值
private float x;
private float y;
// 移动速度
public float movementSpeed = 2.0f;
// 时间
public float movementTime = 5.0f;
//缩放速率
public Vector3 zoomAmount = Vector3.one * 2;
private Vector3 newPosition;
private Quaternion newRotation;
private Vector3 newZoom;
private Vector3 dragStartPosition;
private Vector3 dragCurrentPosition;
// 缩放距离
public float minDistance;
public float maxDistance;
// 旋转角度
public float xMinLimit;
public float xMaxLimit;
public float yMinLimit;
public float yMaxLimit;
// 移动距离
public float posXminLimit;
public float posXmaxLimit;
public float posZminLimit;
public float posZmaxLimit;
- Start初始化变量值
instance = this;
newPosition = transform.position;
newRotation = transform.rotation;
newZoom = cameraTransfrom.localPosition;
x = transform.eulerAngles.y;
y = transform.eulerAngles.x;
- 鼠标控制
void HandleMouseInput()
{
// 缩放
if (Input.mouseScrollDelta.y != 0)
{
newZoom -= Input.mouseScrollDelta.y * zoomAmount;
}
// 移动
if (Input.GetMouseButtonDown(0))
{
Plane plane = new Plane(Vector3.up, Vector3.zero);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float entry;
if (plane.Raycast(ray, out entry))
{
dragStartPosition = ray.GetPoint(entry);
}
}
if (Input.GetMouseButton(0))
{
Plane plane = new Plane(Vector3.up, Vector3.zero);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float entry;
if (plane.Raycast(ray, out entry))
{
dragCurrentPosition = ray.GetPoint(entry);
Vector3 tmp = transform.position + dragStartPosition - dragCurrentPosition;
//newPosition = transform.position + dragStartPosition - dragCurrentPosition;
newPosition = new Vector3(Mathf.Clamp(tmp.x, posXminLimit, posXmaxLimit), tmp.y, Mathf.Clamp(tmp.z, posZminLimit, posZmaxLimit));
}
}
if (Input.GetMouseButton(1))
{
x += Input.GetAxis("Mouse X") * movementSpeed;
y -= Input.GetAxis("Mouse Y") * movementSpeed;
x = ClampX(x, xMinLimit, xMaxLimit);
y = ClampAngle(y, yMinLimit, yMaxLimit);
}
- 移动范围、旋转角度、缩放的限制
static float ClampAngle(float angle, float min, float max)
{
if (angle < -90)
angle += 90;
if (angle > 45)
angle -= 45;
return Mathf.Clamp(angle, min, max);
}
static float ClampX(float x, float min, float max)
{
if (x < 0)
x = 360;
if (x > 360)
x = 0;
return Mathf.Clamp(x, min, max);
}
///缩放距离的限制
static Vector3 ClampDistance(float distance,float minDistance,float maxDistance)
{
distance = Mathf.Clamp(distance, minDistance, maxDistance);
return new Vector3(0, distance, -distance);
}
- Update 监听鼠标控制以及更新变量值
void Update()
{
//有UI系统时可以利用这个方法避免在UI上也控制场景的旋转
//if (!EventSystem.current.IsPointerOverGameObject())
//{
// HandleMouseInput();
//}
HandleMouseInput();
newRotation = Quaternion.Euler(y, x, 0.0f);
newZoom = ClampDistance(newZoom.y, minDistance, maxDistance);
transform.rotation = Quaternion.Lerp(transform.rotation, newRotation, Time.deltaTime * movementTime);
transform.position = Vector3.Lerp(transform.position, newPosition, Time.deltaTime * movementTime);
cameraTransfrom.localPosition = Vector3.Lerp(cameraTransfrom.localPosition, newZoom, Time.deltaTime * movementSpeed);
}
演示效果
相机移动的控制代码基本完成,比较简单就没过多的去写注释了,这篇文章也是自己记录工具库的一个内容,方便以后使用。