前言

在很多情况下我们都会用到如题的功能,在一般情况下我们可以漫游场景,自由的在场景中移动旋转等,而特殊情况下我们会进行围绕某一物体查看的操作。之前的实现一般都是按需求来实现,现在做了一些整理和优化,并将实现方法和过程分享出来。

效果

漫游效果

前进后退效果:
在这里插入图片描述

上下左右移动:
在这里插入图片描述

旋转效果:
在这里插入图片描述

围绕节点效果

围绕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
如果无效,说明审核未通过。

瑕疵

在旋转快结束时,程序会出现一个掉帧的情况:
在这里插入图片描述

如上图,在旋转快结束时有个明显的掉帧,目前没找到问题,如果有知道的可以麻烦=指点一下

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐