Unity学习-输入系统、屏幕Screen相关以及游戏的眼睛Camera

643 阅读9分钟

一.引言

游戏制作除了场景搭建,还有处理与玩家的交互,下面就主要整理和玩家交互相关的API,让游戏活起来

二.Input输入监测

Input提供了很多和输入相关的API,只要是输入监测,就一定会写在Update函数中,每帧进行监测

  1. 鼠标在屏幕位置
    屏幕坐标的原点是在屏幕的左下角,往右是X轴正方向,往上是Y轴正方向
    使用下面的API进行操作,返回值是Vector3,但是只有 x和y 有值,z一直是0,是因为屏幕本来就是2D的,不存在Z轴
    Input.mousePosition
  2. 检测鼠标输入
    鼠标按下相关检测,对于我们来说:
    1.可以做 发射子弹
    2.可以控制摄像机转动
            //鼠标按下一瞬间 进入
            //0左键 1右键 2中键
            //只要按下的这一瞬间 进入一次
            if( Input.GetMouseButtonDown(0) )
            {
                print("鼠标左键按下了");
            }
    
            //鼠标抬起一瞬间 进入
            if( Input.GetMouseButtonUp(0) )
            {
                print("鼠标左键抬起了");
            }
    
            //鼠标长按按下抬起都会进入
            //就是 当按住按键不放时 会一直进入 这个判断
            if( Input.GetMouseButton(1))
            {
                print("右键按下");
            }
    
            //中键滚动
            //返回值的 y -1往下滚  0没有滚  1往上滚
            //它的返回值 是Vector的值 我们鼠标中键滚动 会改变其中的Y值
            print(Input.mouseScrollDelta);
    
  3. 检测键盘输入
    比如说按一个键释放一个技能或者切换武器等等的操作
            //键盘按下
            if( Input.GetKeyDown(KeyCode.W) )
            {
                print("W键按下");
            }
    
            //传入字符串的重载
            //这里传入的 字符串 不能是大写的 不然会报错
            //只能传入小写字符串
            if( Input.GetKeyDown("q") )
            {
                print("q按下");
            }
    
            //键盘抬起
            if( Input.GetKeyUp(KeyCode.W) )
            {
                print("W键抬起");
            }
    
            //键盘长按
            if( Input.GetKey(KeyCode.W) )
            {
                print("W键长按");
            }
    
    键盘输入的检测,建议使用枚举,字符串只支持小写,以防写错
  4. 检测默认轴输入
    学习鼠标、键盘输入主要是用来控制玩家,比如旋转、位移等等,而Unity提供了更便捷的方法用来控制对象的位移和旋转
            //键盘AD按下时 返回 -1到1之间的变换
            //相当于 得到得这个值 就是我们的 左右方向 我们可以通过它来控制 对象左右移动 或者左右旋转
            float h = Input.GetAxis("Horizontal");
            //print(h);
    
            //键盘SW按下时 返回 -1到1之间的变换
            //得到得这个值 就是我们的 上下方向 我们可以通过它来控制 对象上下移动 或者上下旋转
            //print(Input.GetAxis("Vertical"));
    
            //鼠标横向移动时 -1 到 1 左 右
            //print(Input.GetAxis("Mouse X"));
    
            //鼠标竖向移动时  -1 到 1 下 上
            //print(Input.GetAxis("Mouse Y"));
    
            //我们默认的 GetAxis方法 是有渐变的 会总 -1~0~1之间 渐变 会出现小数
    
            //GetAxisRaw方法 和 GetAxis使用方式相同
            //只不过 它的返回值 只会是 -1 0 1 不会有中间值
    
  5. 其余检测,比如手机端的触控,暂时仅做了解
            //是否有任意键或鼠标长按
            if(Input.anyKey)
            {
                print("有一个键长按");
            }
            //是否有任意键或鼠标按下
            if(Input.anyKeyDown)
            {
                print("有一个键 按下");
                //这一帧的键盘输入
                print(Input.inputString);
            }
    
            //手柄输入相关
            //得到连接的手柄的所有按钮名字
            string[] strs = Input.GetJoystickNames();
    
            //某一个手柄键按下
            if( Input.GetButtonDown("Jump") )
            {
    
            }
    
            //某一个手柄键抬起
            if (Input.GetButtonUp("Jump"))
            {
    
            }
    
            //某一个手柄键长按
            if (Input.GetButton("Jump"))
            {
    
            }
    
            //移动设备触摸相关
            if(Input.touchCount > 0)
            {
                Touch t1 = Input.touches[0];
                //位置
                print(t1.position);
                //相对上次位置的变化
                print(t1.deltaPosition);
            }
    
            //是否启用多点触控
            Input.multiTouchEnabled = false;
    
            //陀螺仪(重力感应)
            //是否开启陀螺仪 必须开启 才能正常使用
            Input.gyro.enabled = true;
            //重力加速度向量
            print(Input.gyro.gravity);
            //旋转速度
            print(Input.gyro.rotationRate);
            //陀螺仪 当前的旋转四元数 
            //比如 用这个角度信息 来控制 场景上的一个3D物体受到重力影响
            //手机怎么动 它怎么动
            print(Input.gyro.attitude);
    

三.屏幕Screen相关配置

  1. 静态属性
    • 常用
          //当前屏幕分辨率
          Resolution r = Screen.currentResolution;
          print("当前屏幕分辨率的宽" + r.width + "高" + r.height);
      
          //屏幕窗口当前宽高
          //这得到的 是当前 窗口的 宽高 不是设备分辨率的宽高
          //一般写代码 要用窗口宽高 做计算时 就用他们
          print(Screen.width);
          print(Screen.height);
      
          //屏幕休眠模式 
          Screen.sleepTimeout = SleepTimeout.NeverSleep;
      
    • 不常用
          //运行时是否全屏模式
          Screen.fullScreen = true;
          //窗口模式
          //独占全屏FullScreenMode.ExclusiveFullScreen
          //全屏窗口FullScreenMode.FullScreenWindow
          //最大化窗口FullScreenMode.MaximizedWindow
          //窗口模式FullScreenMode.Windowed
          Screen.fullScreenMode = FullScreenMode.Windowed;
      
          //移动设备屏幕转向相关
          //允许自动旋转为左横向 Home键在左
          Screen.autorotateToLandscapeLeft = true;
          //允许自动旋转为右横向 Home键在右
          Screen.autorotateToLandscapeRight = true;
          //允许自动旋转到纵向 Home键在下
          Screen.autorotateToPortrait = true;
          //允许自动旋转到纵向倒着看 Home键在上
          Screen.autorotateToPortraitUpsideDown = true;
      
          //指定屏幕显示方向
          Screen.orientation = ScreenOrientation.Landscape;
      
  2. 静态方法
    设置分辨率,一般移动设备不使用
    Screen.SetResolution(1920, 1080, false);

四.Camera配置

摄像机参数说明.png 摄像机参数说明2.png 关于Camera的配置说明,如上图,下面依次介绍比较重要的部分

  1. Clear Flags
    如上图所示,共有四个可选项
    • 第一个天空盒适用于做3D游戏
    • 第二个纯色填充适合2D游戏,通常会选择一张图片作为背景,新版的Unity会有Background选项,就是搭配纯色填充使用
    • 第三个和多个相机叠加渲染有关,后面搭配深度Depth一起整理
    • 第四个没什么用,不清除物体移动的痕迹,了解即可,具体什么效果可以参照下图image.png
  2. Culling Mask
    选择需要进行渲染的层级(Layer)
    image.png
    可以看到只有勾选了的层级才会被渲染出来,然后才能被看到
  3. Projection
    设置摄像机的透视方式,默认是Perspective(透视模式),该模式就是用来设计3D游戏的,它能够展示出Z轴,而Orthographic(正交模式)不会展示出Z轴方向,可以理解为只有xy平面上的移动才能被看到,适合做2D设计
    • Perspective(透视模式)
      1. FOV Axis:用于判断视场角由Vertical还是Horizontal决定
      2. Field of View:视口大小,默认为60.改动效果如下图所示 FieldOfView_.gif
      3. Physical Camera:物理摄像机,模拟现实生活中的相机调参,做了解即可,勾选上就可以进行具体调参,每个参数的含义如上图所示,一般不会勾选
    • Orthographic(正交模式)
      正交模式的可调参数比较少,就一个Size,用于控制摄像机可捕捉画面的大小,默认为5.一般不修改,具体效果如何,可自行尝试
  4. Clipping Planes
    裁剪平面范围,摄像机渲染范围内有近远两个切面,近切面可以看做渲染起点,远切面为渲染终点,只有在这个范围内才能被渲染,效果如下图所示 ClippingPlanes_.gif
  5. Depth
    这个参数超级有用,它常常搭配上面提到的Depth Only模式
    先解释一下什么意思,一个场景可以有多个相机,并且它们处在不一样的Depth,这个就好像两个人站在同一直线上进行拍照,前面那个人拍一张,后面那个人拍一张,然后将两张照片进行叠加,很显然,后面那张照片会覆盖前面那张,也就是说,层级越大的相机会覆盖层级小的相机的画面,那这就产生问题了,因为每个相机都会指定渲染不同的层级(Layer),如果想让它们的渲染结果同时展示,就必须选中Depth Only模式,如此一来,后面那张照片除了它渲染的内容,其他部分都是透明的,这样再进行叠加,就不会挡住层级小的的相机的渲染结果了,下面通过一个动图来展示 Depth_.gif
  6. Target Texture
    渲染纹理,将摄像机画面渲染到一张图上,可以用来制作小地图 RenderTexture_.gif
    游戏中的小地图就是从此得来,专门用一个俯视的摄像机来管理
  7. Occlusion Culling:剔除遮挡,这个主要用来优化渲染性能,如果一个远处的物体被近处的物体挡住了,那么可以选择不渲染,反正也看不见,相机一般默认是勾选了这个
  8. Viewport Rect
    视图窗口,可以将游戏窗口分成很多等份,每个等份由不同的相机来渲染,主机游戏会用到,这里就了解即可,下面上效果图 ViewPort_.gif
    至于xy和width、height的值的调节,都是百分比的形式,上手调一调便知
  9. 其余部分一般不会动,具体含义见上面的思维导图即可,关于Target Display就是设置当前相机的渲染结果在哪个屏幕上显示,就是设置屏幕编号,在屏幕窗口中也可以选择当前屏幕编号,两者搭配使用,这里也不赘述了

五.Camera代码配置相关

上面是通过Inpector视图来修改相机相关的配置,与Camera有关的还有代码API,下面进行一个整理

  1. 重要静态成员
    • 获取摄像机
          //主摄像机的获取
          //如果想通过这种方式 快速获取摄像机 那么场景上必须有一个 tag为MainCamera的摄像机
          print(Camera.main.name);
          //获取摄像机的数量
          print(Camera.allCamerasCount);
          //得到所有摄像机
          Camera[] allCamera = Camera.allCameras;
          print(allCamera.Length);
      
    • 渲染相关委托
          //摄像机剔除前处理的委托函数
          Camera.onPreCull += (c) =>
          {
      
          };
          //摄像机 渲染前处理的委托
          Camera.onPreRender += (c) =>
          {
      
          };
          //摄像机 渲染后 处理的委托
          Camera.onPostRender += (c) =>
          {
      
          };
      
  2. 重要成员
    • 界面上的参数,都可以在Camera中获取到
          //比如 下面这句代码 就是得到主摄像机对象 上的深度 进行设置
          Camera.main.depth = 10;
      
    • 世界坐标转屏幕坐标
          //转换过后 x和y对应的就是屏幕坐标 z对应的 是 这个3D物体 里我们的摄像机有多远
          //我们会用这个来做的功能 最多的 就是头顶血条相关的功能
          Vector3 v = Camera.main.WorldToScreenPoint(this.transform.position);
          print(v);
      
    • 屏幕坐标转世界坐标
          //3.屏幕坐标转世界坐标
          //之所以改变Z轴 是因为 如果不改 Z默认为0
          //转换过去的世界坐标系的点 永远都是一个点 可以理解为 视口 相交的焦点
          //如果改变了Z 那么转换过去的 世界坐标的点 就是相对于 摄像机前方多少的单位的横截面上的世界坐标点
          Vector3 v = Input.mousePosition;
          v.z = 5;
          print(Camera.main.ScreenToWorldPoint(v));
      
      屏幕坐标转世界坐标时,注意Z坐标不能为0,因为,3D空间中物体的坐标是在一个面中的,而Z为0是和摄像机的位置重合,是一个点,自然始终都是一个点,不会有变化