mypro334 发表于 2022-12-17 17:26

Unity 3D地图鼠标根据目标点缩放

之前要做一个以鼠标目标点进行Zoom In/Zoom Out的功能,查了一些资料,没查到- 。-
所以自己动手写了一个,造福广大和我一样没有找到这种方法的同学,加快工作速度,好好享受生活与学习。
因最近在准备各种杂七杂八的东西,所以物理流体模拟一直没更新,也请谅解~趁着有空写篇小的,也算抒发下最近的一段时间的感慨了~


效果大致如下:


https://www.zhihu.com/video/1586344044770344960
其实,步骤很简单,如果要改变相机位置而鼠标定的远距离目标点不变的话,只需要将摄像机移动以后的目标点的移动的向量反向给相机就可以,简而言之,目标点移动,鼠标点不动,相机相对于反方向运动。




如图所示,分别画了侧视图和正视图,黑色1是远离鼠标的一步,粉色是移回来的那一步。这个方法可以在有俯仰角变换的时候通用。
第一步,在摄像机的高度和俯仰角都没变的时候,发出的一根射线,计算射线打到的物体,也就是图中的兔子的某个点的世界坐标,
float sign = Input.GetAxis("Mouse ScrollWheel");
      //perform lowering down Camera
      //1.更新相机位置发出射线
      Camera.transform.position = temptransform.transform.position;
      RaycastHit hit0;
      Ray ray0 = Camera.ScreenPointToRay(Input.mousePosition);

      Vector3 point0=Vector3.zero;
      if (Physics.Raycast(ray0, out hit0, Mathf.Infinity))
      {
            point0 = hit0.point;
      }

目标点远离屏幕鼠标点发出射线检测到的点所在的世界坐标,
第二步,对摄像机做偏移动画,降低高度,俯仰角根据高度改变:
float DiveRatio = Camera.transform.position.y / CameraMaxHeight;
Vector3 temposition = temptransform.transform.position + new Vector3(0, -sign * SensityDive* DiveRatio, 0);
temposition = new Vector3(Mathf.Clamp(temposition.x, CameraXmin, CameraXMax),
             Mathf.Clamp(temposition.y, HeightMinimum+0.01f, CameraMaxHeight-0.01f),
             Mathf.Clamp(temposition.z, CameraBottomMin, CameraUpMax));
   
temptransform.transform.position = temposition;
pitchAngle = PitchRotateAnimation();
Camera.transform.rotation = Quaternion.Euler(pitchAngle, rotationY, 0);
Camera.transform.position = temposition;
第三步,再将鼠标的目标点发出射线,检测这个新的鼠标目标的位置。
RaycastHit hit1;
      Ray ray1 = Camera.ScreenPointToRay(Input.mousePosition);
   
      Vector3 point1 = Vector3.zero;
      if (Physics.Raycast(ray1, out hit1, Mathf.Infinity))
      {
            point1 = hit1.point;
      }

   
      Vector3 direction = point0 - point1;

      Vector3 offset = new Vector3(direction.x, 0, direction.z);
这个offset便是要将目标点移到原本的鼠标位置的点的反方向,也就是摄像机应该相对做出的位移
最后更新位置:
Camera.transform.position += offset;
Camera.transform.position = new Vector3(Mathf.Clamp(Camera.transform.position.x, CameraXmin, CameraXMax),
Mathf.Clamp(Camera.transform.position.y, HeightMinimum, CameraMaxHeight),
Mathf.Clamp(Camera.transform.position.z, CameraBottomMin, CameraUpMax));
temptransform.position = Camera.transform.position;
Bingo!
函数如下(大家可以放心忽略temptransform的值赋来赋去,可以直接CameraTransform)
void Zoom()
    {
      //Get Camera position beforeHeighchange
      
      //Get Camera pitch beforeHeighchange
      float pitchAngle1 = Camera.transform.rotation.eulerAngles.x;
      float sign = Input.GetAxis("Mouse ScrollWheel");
      //perform lowering down Camera
      //1.更新相机位置发出射线
      Camera.transform.position = temptransform.transform.position;
      RaycastHit hit0;
      Ray ray0 = Camera.ScreenPointToRay(Input.mousePosition);

      Vector3 point0=Vector3.zero;
      if (Physics.Raycast(ray0, out hit0, Mathf.Infinity))
      {
            point0 = hit0.point;
      }
      Debug.Log("sign" + sign);
      float DiveRatio = Camera.transform.position.y / CameraMaxHeight;
      Vector3 temposition = temptransform.transform.position + new Vector3(0, -sign * SensityDive* DiveRatio, 0);
      temposition = new Vector3(Mathf.Clamp(temposition.x, CameraXmin, CameraXMax),
             Mathf.Clamp(temposition.y, HeightMinimum+0.01f, CameraMaxHeight-0.01f),
             Mathf.Clamp(temposition.z, CameraBottomMin, CameraUpMax));
       // Debug.Log("point0" + point0);
      temptransform.transform.position = temposition;
      
         // Debug.Log(point0);

      //相机角度
      //Get Camera position after Height change
      //CameraHeight2 = Camera.transform.position.y;
       //2.更新相机位置再发出射线
      pitchAngle = PitchRotateAnimation();


      Camera.transform.rotation = Quaternion.Euler(pitchAngle, rotationY, 0);
      Camera.transform.position = temposition;

      //Get Object offsets position after Height change
      RaycastHit hit1;
      Ray ray1 = Camera.ScreenPointToRay(Input.mousePosition);
   
      Vector3 point1 = Vector3.zero;
      if (Physics.Raycast(ray1, out hit1, Mathf.Infinity))
      {
            point1 = hit1.point;
      }

   
      Vector3 direction = point0 - point1;

      Vector3 offset = new Vector3(direction.x, 0, direction.z);
       // Debug.Log(offset);
      //pitchAngle = PitchRotateAnimation();
      //Camera.transform.rotation = Quaternion.Euler(pitchAngle, rotationY, 0);
      //perform the opposite offset
      Camera.transform.position += offset;
      Camera.transform.position = new Vector3(Mathf.Clamp(Camera.transform.position.x, CameraXmin, CameraXMax),
             Mathf.Clamp(Camera.transform.position.y, HeightMinimum, CameraMaxHeight),
             Mathf.Clamp(Camera.transform.position.z, CameraBottomMin, CameraUpMax));
      temptransform.position = Camera.transform.position;


    }
好了,到此为止~祝大家工作学习愉快
页: [1]
查看完整版本: Unity 3D地图鼠标根据目标点缩放