Unity3d C# 实现纯鼠标平滑控制场景摄像头(相机)实现自由旋转、移动和围绕节点移动旋转等功能(含源码工程)
相机控制前言效果漫游效果围绕节点效果实现过程功能范围搭建场景编码实现变量设置自由漫游观察节点功能使用项目工程瑕疵前言在很多情况下我们都会用到如题的功能,在一般情况下我们可以漫游场景,自由的在场景中移动旋转等,而特殊情况下我们会进行围绕某一物体查看的操作。之前的实现一般都是按需求来实现,现在做了一些整理和优化,并将实现方法和过程分享出来。效果漫游效果前进后退效果:上下左右移动:旋转效果:围绕节点效果
前言
在很多情况下我们都会用到如题的功能,在一般情况下我们可以漫游场景,自由的在场景中移动旋转等,而特殊情况下我们会进行围绕某一物体查看的操作。之前的实现一般都是按需求来实现,现在做了一些整理和优化,并将实现方法和过程分享出来。
效果
漫游效果
前进后退效果:
上下左右移动:
旋转效果:
围绕节点效果
围绕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
如果无效,说明审核未通过。
瑕疵
在旋转快结束时,程序会出现一个掉帧的情况:
如上图,在旋转快结束时有个明显的掉帧,目前没找到问题,如果有知道的可以麻烦=指点一下
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)