前言
在很多情况下我们都会用到如题的功能,在一般情况下我们可以漫游场景,自由的在场景中移动旋转等,而特殊情况下我们会进行围绕某一物体查看的操作。之前的实现一般都是按需求来实现,现在做了一些整理和优化,并将实现方法和过程分享出来。
效果
漫游效果
前进后退效果:
上下左右移动:
旋转效果:
围绕节点效果
围绕Cube前后移动:
围绕Cube旋转:
围绕胶囊前后移动:
围绕胶囊旋转:
实现过程
交互效果的触发就是鼠标的事件,这里我们用了右键、中键和滚轮等。主要函数如下:
Input.GetMouseButton(1);
Input.GetMouseButton(2);
Input.GetAxis("Mouse ScrollWheel");
根据如上的事件进行摄像头参数的修改即可实现控制的功能,但是如果要实现平滑的效果,就需要进行插值,让它有个平滑的过渡。
功能范围
首先对旋转和移动等功能块设定开关,方便在某些情况下需要不可移动和旋转时,可以设置开关实现, 对移动位置范围进行限制,防止自由移动时跑出场景;对旋转范围进行限制,上下范围限制住不至于出现多次翻转等情况;锁定查看节点时,限制查看距离等,防止穿模查看模型;其它参数可限制,如移动速度、旋转速度,和插值系数等。 右键控制旋转,中键上下左右移动,滚轮进行前后移动。
搭建场景
如上图,进行几个简单模型搭建,方便查看效果控制效果。
编码实现
变量设置
public bool IsUseCtrl
{
set
{
if (value)
ResetCtrl();
isUseCtrl = value;
}
get
{
return isUseCtrl;
}
}
bool isUseCtrl = true;
[Header("是否限制移动范围")]
public bool IsLimitPos = true;
[Header("是否可移动")]
public bool IsMove = true;
[Header("是否可旋转")]
public bool IsRot = true;
[Header("镜头位置范围限制")]
public float PosMinX = -2;
public float PosMaxX = 2, PosMinY = 1, PosMaxY = 6, PosMinZ = -2, PosMaxZ = 2;
[Header("镜头前后移动速度")]
public float HBMoveSpeed = 20;
[Header("镜头左右移动速度")]
public float LRMoveSpeed = 1f;
[Header("镜头上下旋转限制")]
public float RotMinX = -45.0f;
public float RotMaxX = 45.0f;
[Header("镜头旋转速度")]
public float XRotSpeed = 2f;
public float YRotSpeed = 2f;
[Header("围绕的对象")]
public Transform LookAtTran = null;
[Header("距离配置")]
public float LookMinDis = 2;
public float LookMaxDis = 20;
自由漫游
在无观察节点时,自动在自由漫游状态下。
滚轮控制前进后退:
if (IsMove && Input.GetAxis("Mouse ScrollWheel") != 0)
tdirz += Input.GetAxis("Mouse ScrollWheel") * HBMoveSpeed;
dirz = Mathf.SmoothDamp(dirz, tdirz, ref zVel, 0.5f);
采集滚轮消息后,先对目标值进行更新,然后进行插值。
中键平移操作:
if (IsMove && Input.GetMouseButton(2))
{
tdirx += Input.GetAxis("Mouse X") * -LRMoveSpeed;
tdiry += Input.GetAxis("Mouse Y") * -LRMoveSpeed;
}
dirx = Mathf.SmoothDamp(dirx, tdirx, ref xVel, 0.3f);
diry = Mathf.SmoothDamp(diry, tdiry, ref yVel, 0.3f);
右键旋转操作:
if (IsRot && Input.GetMouseButton(1))
{
troty += Input.GetAxis("Mouse X") * XRotSpeed;
trotx -= Input.GetAxis("Mouse Y") * YRotSpeed;
trotx = CutAngle(trotx, RotMinX, RotMaxX);
}
rotx = Mathf.SmoothDampAngle(rotx, trotx, ref RxVel, 0.3f);
roty = Mathf.SmoothDampAngle(roty, troty, ref RyVel, 0.3f);
最后进行位置和旋转的更新:
Quaternion rotation = Quaternion.Euler(rotx, roty, 0);
Vector3 tpos = transform.position + rotation * new Vector3(tdirx - dirx, tdiry - diry, tdirz - dirz);
if (IsLimitPos)
{
if (CheckPos(tpos))
transform.position = tpos;
else{
dirx = tdirx;
diry = tdiry;
dirz = tdirz;
}
}
else
transform.position = tpos;
transform.rotation = rotation;
观察节点
这部分和自由漫游基本类似,不过少了上下左右移动,而且位置的计算是根据观察节点来进行计算的。
if (IsMove && Input.GetAxis("Mouse ScrollWheel") != 0)
{
tdis -= Input.GetAxis("Mouse ScrollWheel") * HBMoveSpeed;
tdis = Mathf.Clamp(tdis, LookMinDis, LookMaxDis);
}
dis = Mathf.SmoothDamp(dis, tdis, ref zVel, 0.5f);
if (IsRot && Input.GetMouseButton(1))
{
troty += Input.GetAxis("Mouse X") * XRotSpeed;
trotx -= Input.GetAxis("Mouse Y") * YRotSpeed;
trotx = CutAngle(trotx, RotMinX, RotMaxX);
}
rotx = Mathf.SmoothDampAngle(rotx, trotx, ref RxVel, 0.3f);
roty = Mathf.SmoothDampAngle(roty, troty, ref RyVel, 0.3f);
Quaternion rotation = Quaternion.Euler(rotx, roty, 0);
Vector3 position = rotation * new Vector3(0.0f, 0.0f, -dis) + LookAtTran.position;
transform.rotation = rotation;
transform.position = position;
功能使用
配置位置范围:
开关配置:
观察的节点配置:
按上图,将观察的节点拖入或者设置即可。
其它:
项目工程
https://download.csdn.net/download/qq_33789001/25952768 如果无效,说明审核未通过。
瑕疵
在旋转快结束时,程序会出现一个掉帧的情况:
如上图,在旋转快结束时有个明显的掉帧,目前没找到问题,如果有知道的可以麻烦=指点一下
|