使用UnityRTS怎么实现一个相机移动缩放功能
本篇文章为大家展示了使用UnityRTS怎么实现一个相机移动缩放功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
相机的层级关系(移动的操作是对父物体进行操作,而缩放是对子物体主相机的操作):
以此场景为例,自己设置的一些参数,主要是移动速度,边界、缩放限制等。
代码如下(挂载到相机的父物体上)。有两种鼠标的控制方式,一种是边界检测,一种是鼠标拖动。这个代码是完整版的,也就是键盘也可以控制相机移动缩放的,如果只需要鼠标控制的,请往下看:
usingUnityEngine; ///<summary> /// ///*Writer:June ///* ///*Data:2021.3.9 ///* ///*Function:RTS模式的相机移动 ///* ///*Remarks: /// ///</summary> publicclassCameraMoveControl:MonoBehaviour { #region移动 ///<summary> ///移动速度 ///</summary> privatefloatpanSpeed; ///<summary> ///正常速度 ///</summary> [SerializeField]privatefloatnormalSpeed; ///<summary> ///按shift加速 ///</summary> [SerializeField]privatefloatspeedUp; ///<summary> ///缓冲时间 ///</summary> [SerializeField]privatefloatmoveTime; privateVector3newPos; ///<summary> ///边界限制 ///</summary> [SerializeField]privatefloatxLimMin,xLimMax; ///<summary> ///这里的Y是指屏幕上下平移的限制 ///</summary> [SerializeField]privatefloatyLimMin,yLimMax; //-----------------------------------------------鼠标拖动操作相关字段---------------------------------------------------- privateCameramainCamrea; privateVector3startPoint,currentPoint; #endregion #region缩放 ///<summary> ///主摄像机的位置组件 ///</summary> privateTransformmainCamreaTF; ///<summary> ///缩放向量 ///tips:相机的放大缩小改变的是相机自身坐标的yz值 ///</summary> [SerializeField]privateVector3zoomV3; /* *需要注意的是缩放限制: *x轴与y轴限制后的缩放比值要一致,不然会出现缩放不平滑的现象 * */ ///<summary> ///缩放最大最小值 ///</summary> [SerializeField]privateVector3zoomMin,zoomMax; privateVector3newMainCamreaPos; ///<summary> ///缩放时间 ///</summary> [SerializeField]privatefloatzoomTime; #endregion privatevoidStart() { //判断是否有子物体 mainCamreaTF=transform.childCount>0?transform.GetChild(0):null; if(mainCamreaTF)newMainCamreaPos=mainCamreaTF.localPosition; mainCamrea=Camera.main; } privatevoidUpdate() { //按左shift加速 panSpeed=Input.GetKey(KeyCode.LeftShift)?speedUp:normalSpeed; //移动 ControlCamreaMove(); //缩放 ControlCamreaZoom(); } ///<summary> ///控制相机缩放 ///</summary> privatevoidControlCamreaZoom() { if(mainCamreaTF) { if(Input.GetKey(KeyCode.R))newMainCamreaPos+=zoomV3*Time.deltaTime;//放大 if(Input.GetKey(KeyCode.F))newMainCamreaPos-=zoomV3*Time.deltaTime;//缩小 newMainCamreaPos+=Input.GetAxis("MouseScrollWheel")*zoomV3; ZoomLimit(refnewMainCamreaPos); //刷新最终位置 mainCamreaTF.localPosition=Vector3.Lerp(mainCamreaTF.localPosition,newMainCamreaPos,zoomTime*Time.deltaTime); } } ///<summary> ///控制相机移动 ///</summary> privatevoidControlCamreaMove() { Vector3movePos=transform.position; newPos.Set(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")); #region鼠标操作 #region方式1(鼠标到达边缘,检测后操作相机移动) //Vector2mousePos=Input.mousePosition; //鼠标在四个边缘检测 //if(mousePos.x>Screen.width*0.9f&&mousePos.x<Screen.width)newPos.x=1; //if(mousePos.x<Screen.width*0.1f&&mousePos.x>0)newPos.x=-1; //if(mousePos.y>Screen.height*0.9f&&mousePos.y<Screen.height)newPos.z=1; //if(mousePos.y<Screen.height*0.1f&&mousePos.y>0)newPos.z=-1; movePos+=newPos.normalized*panSpeed*Time.deltaTime; #endregion #region方式2(鼠标右键拖动控制相机移动) //首先判断相机是否为空 if(mainCamrea) { //鼠标右键按下时记录起始位置 if(Input.GetMouseButtonDown(1)) { //新建的世界坐标系下的平面,用于检测射线 Planeplane=newPlane(Vector3.up,Vector3.zero); Rayray=mainCamrea.ScreenPointToRay(Input.mousePosition); floatdistance; if(plane.Raycast(ray,outdistance)) { //获取碰撞位置 startPoint=ray.GetPoint(distance); } } //鼠标右键一直按下时记录当前点位置 if(Input.GetMouseButton(1)) { Planeplane=newPlane(Vector3.up,Vector3.zero); Rayray=mainCamrea.ScreenPointToRay(Input.mousePosition); floatdistance; if(plane.Raycast(ray,outdistance)) { currentPoint=ray.GetPoint(distance); } movePos+=(startPoint-currentPoint); } } #endregion #endregion BoundaryLimit(refmovePos); transform.position=Vector3.Lerp(transform.position,movePos,moveTime); } ///<summary> ///边界限制 ///</summary> ///<paramname="_pos">要限制的目标向量</param> privatevoidBoundaryLimit(refVector3_pos) { _pos.x=Mathf.Clamp(_pos.x,xLimMin,xLimMax); _pos.z=Mathf.Clamp(_pos.z,yLimMin,yLimMax); } ///<summary> ///缩放限制 ///</summary> ///<paramname="_v3">要限制的目标向量</param> privatevoidZoomLimit(refVector3_v3) { _v3.y=Mathf.Clamp(_v3.y,zoomMin.y,zoomMax.y); _v3.z=Mathf.Clamp(_v3.z,zoomMin.z,zoomMax.z); } }
这个代码是后来我觉得其实没必要用键盘来操控相机,根据我玩过的一些类似游戏,比较多都是鼠标操作的,所以删了键盘操作的部分:
usingUnityEngine; ///<summary> /// ///*Writer:June ///* ///*Data:2021.3.9 ///* ///*Function:RTS模式的相机移动 ///* ///*Remarks: /// ///</summary> publicclassCameraMoveControl:MonoBehaviour { #region移动 ///<summary> ///移动速度 ///</summary> privatefloatpanSpeed; ///<summary> ///正常速度 ///</summary> [SerializeField]privatefloatnormalSpeed; ///<summary> ///按shift加速 ///</summary> [SerializeField]privatefloatspeedUp; ///<summary> ///缓冲时间 ///</summary> [SerializeField]privatefloatmoveTime; privateVector3newPos; ///<summary> ///边界限制 ///</summary> [SerializeField]privatefloatxLimMin,xLimMax; ///<summary> ///这里的Y是指屏幕上下平移的限制 ///</summary> [SerializeField]privatefloatyLimMin,yLimMax; //-----------------------------------------------鼠标拖动操作相关字段---------------------------------------------------- privateCameramainCamrea; privateVector3startPoint,currentPoint; #endregion #region缩放 ///<summary> ///主摄像机的位置组件 ///</summary> privateTransformmainCamreaTF; ///<summary> ///缩放向量 ///tips:相机的放大缩小改变的是相机自身坐标的yz值 ///</summary> [SerializeField]privateVector3zoomV3; /* *需要注意的是缩放限制: *x轴与y轴限制后的缩放比值要一致,不然会出现缩放不平滑的现象 * */ ///<summary> ///缩放最大最小值 ///</summary> [SerializeField]privateVector3zoomMin,zoomMax; privateVector3newMainCamreaPos; ///<summary> ///缩放时间 ///</summary> [SerializeField]privatefloatzoomTime; #endregion privatevoidStart() { //判断是否有子物体 mainCamreaTF=transform.childCount>0?transform.GetChild(0):null; if(mainCamreaTF)newMainCamreaPos=mainCamreaTF.localPosition; mainCamrea=Camera.main; } privatevoidUpdate() { //按左shift加速 panSpeed=Input.GetKey(KeyCode.LeftShift)?speedUp:normalSpeed; //移动 ControlCamreaMove(); //缩放 ControlCamreaZoom(); } ///<summary> ///控制相机缩放 ///</summary> privatevoidControlCamreaZoom() { if(mainCamreaTF) { newMainCamreaPos+=Input.GetAxis("MouseScrollWheel")*zoomV3; ZoomLimit(refnewMainCamreaPos); //刷新最终位置 mainCamreaTF.localPosition=Vector3.Lerp(mainCamreaTF.localPosition,newMainCamreaPos,zoomTime*Time.deltaTime); } } ///<summary> ///控制相机移动 ///</summary> privatevoidControlCamreaMove() { Vector3movePos=transform.position; newPos=Vector3.zero; #region鼠标操作 #region方式1(鼠标到达边缘,检测后操作相机移动) Vector2mousePos=Input.mousePosition; //鼠标在四个边缘检测 if(mousePos.x>Screen.width*0.9f&&mousePos.x<Screen.width)newPos.x=1; if(mousePos.x<Screen.width*0.1f&&mousePos.x>0)newPos.x=-1; if(mousePos.y>Screen.height*0.9f&&mousePos.y<Screen.height)newPos.z=1; if(mousePos.y<Screen.height*0.1f&&mousePos.y>0)newPos.z=-1; movePos+=newPos.normalized*panSpeed*Time.deltaTime; #endregion #region方式2(鼠标右键拖动控制相机移动) //首先判断相机是否为空 if(mainCamrea) { //鼠标右键按下时记录起始位置 if(Input.GetMouseButtonDown(1)) { //新建的世界坐标系下的平面,用于检测射线 Planeplane=newPlane(Vector3.up,Vector3.zero); Rayray=mainCamrea.ScreenPointToRay(Input.mousePosition); floatdistance; if(plane.Raycast(ray,outdistance)) { //获取碰撞位置 startPoint=ray.GetPoint(distance); } } //鼠标右键一直按下时记录当前点位置 if(Input.GetMouseButton(1)) { Planeplane=newPlane(Vector3.up,Vector3.zero); Rayray=mainCamrea.ScreenPointToRay(Input.mousePosition); floatdistance; if(plane.Raycast(ray,outdistance)) { currentPoint=ray.GetPoint(distance); } movePos+=(startPoint-currentPoint); } } #endregion #endregion BoundaryLimit(refmovePos); transform.position=Vector3.Lerp(transform.position,movePos,moveTime); } ///<summary> ///边界限制 ///</summary> ///<paramname="_pos">要限制的目标向量</param> privatevoidBoundaryLimit(refVector3_pos) { _pos.x=Mathf.Clamp(_pos.x,xLimMin,xLimMax); _pos.z=Mathf.Clamp(_pos.z,yLimMin,yLimMax); } ///<summary> ///缩放限制 ///</summary> ///<paramname="_v3">要限制的目标向量</param> privatevoidZoomLimit(refVector3_v3) { _v3.y=Mathf.Clamp(_v3.y,zoomMin.y,zoomMax.y); _v3.z=Mathf.Clamp(_v3.z,zoomMin.z,zoomMax.z); } }
上述内容就是使用UnityRTS怎么实现一个相机移动缩放功能,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注恰卡编程网行业资讯频道。
推荐阅读
-
在Python中,将K添加到列元组列表中的最小元素
处理数据集涉及识别特定列中的最小值并通过添加常量值(K)来更新它。通过实施优化的解决方案,我们可以有效地执行此操作,这对于数据...
-
使用switch case语句编写的C程序,用于计算几何图形的面积
#includevoidmain(){intfig_code;floatside,base,length,...
-
如何使 C# 代码可重用?
要在C#中使代码可重用,请使用接口。接口定义属性、方法和事件,这些成员是接口的成员。接口只包含成员的声明。派生类负责定义成员。这通...
-
C# 中的覆盖和隐藏有什么区别?
方法隐藏在C#中也称为隐藏。父类的方法可供子类使用,无需在遮蔽中使用override关键字。子类有其自己版本的相同函数。在...
-
在Java中使用示例双倍longValue()函数
Java是一种强大的面向对象语言,可以对各种数据类型进行高度的控制和精确度。其中一种功能是doublelongValue(),...
-
如何在Java中定义JSON字段名称的命名约定?
TheFieldNamingPolicycanbeusedtodefineafewstandardnaming...
-
Servlet中的HttpSession接口
在JavaWeb开发领域,了解HttpSession接口是创建动态和响应式Web应用程序的关键。在本文中,我们将探讨...
-
使用while循环查找自然数之和的Java程序
自然数之和可以使用编程语言中的不同迭代语句来计算。迭代语句是执行一组特定代码行直到循环语句中的条件失败的语句。在本文中,我们将讨论...
-
我们可以将Java数组转换为列表吗?
我们可以使用Arrays.asList()方法轻松地将Java数组转换为List。语法publicstaticLi...
-
Java中如何在不使用任何外部库的情况下读取网页内容?
TheURLclassofthejava.netpackagerepresentsaUniformResour...