提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
日常开发中,模型的展示需要使摄像机画面聚焦在模型上,分享下鼠标控制的方法。代码中用到了DoTween插件的功能,大家自行下载导入。
一、控制代码
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraControlObj : MonoBehaviour
{
public bool isControl=false;
private Vector3 v3init;
public float xMinLimit = -360f;
public float xMaxLimit = 360f;
public float yMinLimit = 0f;
public float yMaxLimit = 80f;
public float xSpeed = 50.0f;
public Transform target;
public float distance = 10.0f;
public float nearLimit = 1.0f;
public float farLimit = 80.0f;
public float movSpeedScroll = 5.0f;
public float movSpeed = 0.005f;
public float x;
public float y;
public float z;
Vector3 v3Pos;
float v3Distance;
Quaternion rotation;
Vector3 position;
// Use this for initialization
void Start()
{
ParamInit();
}
private bool bFstTouch;
private Vector3 vCurPos;
private Vector3 vOrgPos;
private float yDis;
private float xDis;
private Touch touch1;
private Touch touch2;
private Touch touch3;
private float touchDistance;
private float lastTouchDistance;
private float deltaDistance;
public void ParamInit()
{
//v3init = target.position;
//v3Pos = new Vector3(x, y, z);
//v3Distance = distance;
}
// Update is called once per frame
public void Update()
{
if (target==null|| !isControl)
{
return;
}
//if (Input.GetMouseButtonDown(0))
//{
// target.position= v3init;
// distance = v3Distance;
// x = v3Pos.x;
// y = v3Pos.y;
// z = v3Pos.z;
//}
if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WebGLPlayer || Application.platform == RuntimePlatform.WindowsPlayer)
{
if (Input.GetMouseButton(1))
{
x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
x = ClampAngle(x, xMinLimit, xMaxLimit);
y -= Input.GetAxis("Mouse Y") * xSpeed * 0.02f;
y = ClampAngle(y, yMinLimit, yMaxLimit);
}
else if (Input.GetMouseButton(0))
{
}
else if (Input.GetMouseButton(2))
{
vCurPos = Input.mousePosition;
if (!bFstTouch)
{
vOrgPos = vCurPos;
bFstTouch = true;
return;
}
if (vOrgPos != vCurPos)
{
yDis = (vCurPos.y - vOrgPos.y) * movSpeed;
xDis = (vCurPos.x - vOrgPos.x) * movSpeed;
vOrgPos = vCurPos;//Record last mouseposition
//Change target's position,acording' its rotation and the distance mouse moved
Quaternion rot = Quaternion.Euler(y, x, 0);
Vector3 pos = rot * new Vector3(-xDis, -yDis, 0) + target.position;
target.position = pos;
}
}
if (Input.GetMouseButtonUp(2))
{
bFstTouch = false;
}
if (Input.GetAxis("Mouse ScrollWheel") != 0)
{
distance -= Input.GetAxis("Mouse ScrollWheel") * movSpeedScroll;
distance = Mathf.Clamp(distance, nearLimit, farLimit);
}
}
else
{
int iTouchCount = Input.touchCount;
switch (iTouchCount)
{
case 1:
touch1 = Input.GetTouch(0);
if (touch1.phase == TouchPhase.Moved)
{
x += (Input.GetTouch(0).deltaPosition.x) * xSpeed * 0.02f;
x = ClampAngle(x, xMinLimit, xMaxLimit);
y -= (Input.GetTouch(0).deltaPosition.y) * xSpeed * 0.02f;
y = ClampAngle(y, yMinLimit, yMaxLimit);
}
break;
case 2:
touch1 = Input.GetTouch(0);
touch2 = Input.GetTouch(1);
if (touch1.phase == TouchPhase.Moved || touch2.phase == TouchPhase.Moved)
{
touchDistance = (touch1.position - touch2.position).magnitude;
lastTouchDistance = ((touch1.position - touch1.deltaPosition) - (touch2.position - touch2.deltaPosition)).magnitude;
deltaDistance = lastTouchDistance - touchDistance;
distance += deltaDistance * movSpeedScroll;
distance = Mathf.Clamp(distance, nearLimit, farLimit);
}
break;
case 3:
touch1 = Input.GetTouch(0);
touch2 = Input.GetTouch(1);
touch3 = Input.GetTouch(2);
if (touch1.phase == TouchPhase.Moved && touch1.phase == TouchPhase.Moved && touch3.phase == TouchPhase.Moved)
{
vCurPos = touch3.position;
if (!bFstTouch)
{
vOrgPos = vCurPos;
bFstTouch = true;
return;
}
if (vOrgPos != vCurPos)
{
yDis = (vCurPos.y - vOrgPos.y) * movSpeed;
xDis = (vCurPos.x - vOrgPos.x) * movSpeed;
vOrgPos = vCurPos;//Record last mouseposition
//Change target's position,acording' its rotation and the distance mouse moved
Quaternion rot = Quaternion.Euler(y, x, 0);
Vector3 pos = rot * new Vector3(-xDis, -yDis, 0) + target.position;
target.position = pos;
}
}
break;
case 0:
bFstTouch = false;
break;
}
}
rotation = Quaternion.Euler(y, x, z);
position = rotation * new Vector3(0f, 0f, -distance) + target.position;
transform.position = Vector3.Lerp(transform.position, position, Time.deltaTime * 10);
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * 10);
}
static float ClampAngle(float angle, float min, float max)
{
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp(angle, min, max);
}
/// <summary>
/// 设定相机角度
/// </summary>
/// <param name="dis"></param>
/// <param name="posx"></param>
/// <param name="posy"></param>
public void setPos(float dis, float posx, float posy)
{
distance = dis;
x = posx;
y = posy;
}
/// <summary>
/// 目标点移动
/// </summary>
public void TargetMove(Transform t)
{
target.DOMove(t.position,1f);
}
float DifferenceDistance;
/// <summary>
/// 相机复原位置
/// </summary>
public void CamMoveInitPos()
{
isControl = false;
DifferenceDistance = distance;
this.transform.DORotate(Vector3.zero, 1f).
OnUpdate(() =>
{
x = this.transform.eulerAngles.y;
y = this.transform.eulerAngles.x;
rotation = Quaternion.Euler(y, x, z);
position = rotation * new Vector3(0f, 0f, -distance) + target.position;
transform.position = position;
transform.rotation = rotation;
distance += (nearLimit + 5f - DifferenceDistance)*Time.deltaTime;
}).OnComplete
(
() =>
{
x = 0;
y = 0;
isControl = true;
}
);
}
[ContextMenu("相机视角复位")]
public void CameraViewInit()
{
CamMoveInitPos();
}
}
二、使用方法
2.1 首先将脚本挂载到相机物体上
2.2 将观察物体拖到脚本定义物体中;
2.3 在镜头切换后,可以通过图中功能按钮进行视角的复位;
三、键盘移动相机方法
public class CameraMoveAndRotate : MonoBehaviour
{
public GameObject target;
public float sensitivity = 2f;
public float speed = 0.1f;
/// <summary>
/// 相机可移动区域 (限制围绕中心点和相机的 x ,z)
/// </summary>
public Bounds aroundPosBounds = new Bounds();
// Start is called before the first frame update
void Start()
{
if (target==null)
{
target = Camera.main.gameObject;
}
}
旋转速度
//public float rotationSpeed = 5f;
上下旋转角度限制
//public float maxVerticalAngle = 90f;
//public float minVerticalAngle = -90f;
旋转缓冲速度
//public float lerpSpeed = 10f;
//private float targetRotationX = 0f;
//private float targetRotationY = 0f;
// Update is called once per frame
void Update()
{
Move();
if (Input.GetMouseButton(1))
{
Rotate();
//if (Input.GetMouseButton(1))
//{
// // 获取鼠标输入的旋转增量
// float rotationXInput = -Input.GetAxis("Mouse Y");
// float rotationYInput = Input.GetAxis("Mouse X");
// // 根据旋转速度进行摄像机的旋转
// targetRotationX += rotationXInput * rotationSpeed;
// targetRotationY += rotationYInput * rotationSpeed;
// // 对上下旋转角度进行限制
// targetRotationX = Mathf.Clamp(targetRotationX, minVerticalAngle, maxVerticalAngle);
// // 根据旋转角度更新摄像机的欧拉角,Quaternion.Lerp可以使摄像机旋转更加平滑
// Quaternion targetRotation = Quaternion.Euler(targetRotationX, targetRotationY, 0f);
// transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, lerpSpeed * Time.deltaTime);
//}
}
moveInput = ClampVector3(target.transform.position, aroundPosBounds.min, aroundPosBounds.max);
target.transform.position = moveInput;
}
public Vector3 ClampVector3(Vector3 v, Vector3 min, Vector3 max)
{
v.x = Mathf.Clamp(v.x, min.x, max.x);
v.y = Mathf.Clamp(v.y, min.y, max.y);
v.z = Mathf.Clamp(v.z, min.z, max.z);
return v;
}
private Vector3 moveInput;
private void Move()
{
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W))
{
transform.Translate(Vector3.forward * Time.deltaTime * speed);
}
if (Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S))
{
transform.Translate(Vector3.back * Time.deltaTime * speed);
}
if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A))
{
transform.Translate(Vector3.left * Time.deltaTime * speed);
}
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
{
transform.Translate(Vector3.right * Time.deltaTime * speed);
}
if (Input.GetKey(KeyCode.E))
{
transform.Translate(Vector3.up * Time.deltaTime * speed);
}
if (Input.GetKey(KeyCode.Q))
{
transform.Translate(Vector3.down * Time.deltaTime * speed);
}
/*Vector3 vertMove = transform.forward * Input.GetAxis("Vertical");
Vector3 horiMove = transform.right * Input.GetAxis("Horizontal");
moveInput = vertMove + horiMove;
moveInput.Normalize();
transform.Translate(moveInput * Time.deltaTime * speed);*/
}
private void Rotate()
{
Vector2 mouseInput = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")) * sensitivity;
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y + mouseInput.x, transform.rotation.eulerAngles.z); //水平方向旋转
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles + new Vector3(-mouseInput.y, 0f, 0f));//摄像头垂直旋转
}
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了摄像机画面的控制及镜头复位,对于简单的功能制作比较有帮助。