Unity3D使用鼠標(biāo)旋轉(zhuǎn)縮放平移視角
Unity使用鼠標(biāo)旋轉(zhuǎn)縮放平移視角,供大家參考,具體內(nèi)容如下
用代碼在Game界面完美實(shí)現(xiàn)Scene界面的操作方法。
使用方法:把腳本掛在相機(jī)上,把跟蹤的target拖到腳本上。
視角跟蹤的是一個(gè)空物體,當(dāng)然如果你是做RPG游戲需要跟蹤某一角色的視角,那就不需要中鍵平移功能,把空物體換成角色就行。
代碼主要是分三部分功能進(jìn)行實(shí)現(xiàn)。
1.右鍵拖動(dòng)控制視角的旋轉(zhuǎn);
2.滾輪旋轉(zhuǎn)控制視角的縮放;
3.中鍵拖動(dòng)控制視角的平移。
右鍵拖動(dòng)控制旋轉(zhuǎn)主要是用GetAxis獲得鼠標(biāo)在x方向與y方向平移的距離,相機(jī)的旋轉(zhuǎn)是通過(guò)旋轉(zhuǎn)相機(jī)本體坐標(biāo)系的x軸與y軸實(shí)現(xiàn)的,重要的是在旋轉(zhuǎn)相機(jī)的同時(shí),要控制相機(jī)和target物體的相對(duì)距離,即同時(shí)控制相機(jī)繞target物體的旋轉(zhuǎn)。這個(gè)網(wǎng)上多數(shù)實(shí)現(xiàn)都相同,不贅述
中鍵滾輪控制視角的縮放,定義Distance變量控制相機(jī)與target的距離(相機(jī)z軸方向的距離),用GetAxis獲得滾輪旋轉(zhuǎn)的程度,控制Distance的變動(dòng)。這里和網(wǎng)上已有的方法也沒(méi)什么區(qū)別。
中鍵拖動(dòng)控制視角的平移,之前在網(wǎng)上查找相關(guān)的實(shí)現(xiàn),結(jié)果實(shí)際效果都比較差,所以自己實(shí)現(xiàn)了一下。視角的平移是通過(guò)獲取中鍵在屏幕坐標(biāo)系下的平移的方向向量,然后轉(zhuǎn)換為世界坐標(biāo)系下的target坐標(biāo)的平移,然后調(diào)整相機(jī)的位置進(jìn)行相應(yīng)的平移以保證旋轉(zhuǎn)和縮放不受影響。
屏幕坐標(biāo)系的平移轉(zhuǎn)換到世界坐標(biāo)系下的平移,本質(zhì)上就是世界坐標(biāo)系下沿著相機(jī)的本體坐標(biāo)系的x與y軸進(jìn)行相應(yīng)的平移。所以只需要求出屏幕坐標(biāo)系x與y方向的平移,分別乘以相機(jī)x與y軸的方向向量,然后與target原來(lái)的坐標(biāo)相加,就可以獲得target平移后的位置,再將相機(jī)的位置平移過(guò)去即實(shí)現(xiàn)了視角的平移,這種平移保證了相機(jī)平面和target之間的相對(duì)距離保持不變。具體代碼如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MouseLookTest : MonoBehaviour { //相機(jī)跟隨的目標(biāo)物體,一般是一個(gè)空物體 public Transform target; private int MouseWheelSensitivity = 1; //滾輪靈敏度設(shè)置 private int MouseZoomMin = 1; //相機(jī)距離最小值 private int MouseZoomMax = 20; //相機(jī)距離最大值 private float moveSpeed = 10; //相機(jī)跟隨速度(中鍵平移時(shí)),采用平滑模式時(shí)起作用,越大則運(yùn)動(dòng)越平滑 private float xSpeed = 250.0f; //旋轉(zhuǎn)視角時(shí)相機(jī)x軸轉(zhuǎn)速 private float ySpeed = 120.0f; //旋轉(zhuǎn)視角時(shí)相機(jī)y軸轉(zhuǎn)速 private int yMinLimit = -360; private int yMaxLimit = 360; private float x = 0.0f; //存儲(chǔ)相機(jī)的euler角 private float y = 0.0f; //存儲(chǔ)相機(jī)的euler角 private float Distance = 5; //相機(jī)和target之間的距離,因?yàn)橄鄼C(jī)的Z軸總是指向target,也就是相機(jī)z軸方向上的距離 private Vector3 targetOnScreenPosition; //目標(biāo)的屏幕坐標(biāo),第三個(gè)值為z軸距離 private Quaternion storeRotation; //存儲(chǔ)相機(jī)的姿態(tài)四元數(shù) private Vector3 CameraTargetPosition; //target的位置 private Vector3 initPosition; //平移時(shí)用于存儲(chǔ)平移的起點(diǎn)位置 private Vector3 cameraX; //相機(jī)的x軸方向向量 private Vector3 cameraY; //相機(jī)的y軸方向向量 private Vector3 cameraZ; //相機(jī)的z軸方向向量 private Vector3 initScreenPos; //中鍵剛按下時(shí)鼠標(biāo)的屏幕坐標(biāo)(第三個(gè)值其實(shí)沒(méi)什么用) private Vector3 curScreenPos; //當(dāng)前鼠標(biāo)的屏幕坐標(biāo)(第三個(gè)值其實(shí)沒(méi)什么用) void Start () { //這里就是設(shè)置一下初始的相機(jī)視角以及一些其他變量,這里的x和y。。。是和下面getAxis的mouse x與mouse y對(duì)應(yīng) var angles = transform.eulerAngles; x = angles.y; y = angles.x; CameraTargetPosition = target.position; storeRotation = Quaternion.Euler (y + 60, x, 0); transform.rotation = storeRotation; //設(shè)置相機(jī)姿態(tài) Vector3 position = storeRotation * new Vector3 (0.0F, 0.0F, -Distance) + CameraTargetPosition; //四元數(shù)表示一個(gè)旋轉(zhuǎn),四元數(shù)乘以向量相當(dāng)于把向量旋轉(zhuǎn)對(duì)應(yīng)角度,然后加上目標(biāo)物體的位置就是相機(jī)位置了 transform.position = storeRotation * new Vector3 (0, 0, -Distance) + CameraTargetPosition; //設(shè)置相機(jī)位置 // Debug.Log("Camera x: "+transform.right); // Debug.Log("Camera y: "+transform.up); // Debug.Log("Camera z: "+transform.forward); // //-------------TEST----------------- // testScreenToWorldPoint(); } void Update () { //鼠標(biāo)右鍵旋轉(zhuǎn)功能 if (Input.GetMouseButton (1)) { x += Input.GetAxis ("Mouse X") * xSpeed * 0.02f; y -= Input.GetAxis ("Mouse Y") * ySpeed * 0.02f; y = ClampAngle (y, yMinLimit, yMaxLimit); storeRotation = Quaternion.Euler (y + 60, x, 0); var position = storeRotation * new Vector3 (0.0f, 0.0f, -Distance) + CameraTargetPosition; transform.rotation = storeRotation; transform.position = position; } else if (Input.GetAxis ("Mouse ScrollWheel") != 0) //鼠標(biāo)滾輪縮放功能 { if (Distance >= MouseZoomMin && Distance <= MouseZoomMax) { Distance -= Input.GetAxis ("Mouse ScrollWheel") * MouseWheelSensitivity; } if (Distance < MouseZoomMin) { Distance = MouseZoomMin; } if (Distance > MouseZoomMax) { Distance = MouseZoomMax; } var rotation = transform.rotation; transform.position = storeRotation * new Vector3 (0.0F, 0.0F, -Distance) + CameraTargetPosition; } //鼠標(biāo)中鍵平移 if (Input.GetMouseButtonDown (2)) { cameraX = transform.right; cameraY = transform.up; cameraZ = transform.forward; initScreenPos = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, targetOnScreenPosition.z); Debug.Log ("downOnce"); //targetOnScreenPosition.z為目標(biāo)物體到相機(jī)xmidbuttonDownPositiony平面的法線距離 targetOnScreenPosition = Camera.main.WorldToScreenPoint (CameraTargetPosition); initPosition = CameraTargetPosition; } if (Input.GetMouseButton (2)) { curScreenPos = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, targetOnScreenPosition.z); //0.01這個(gè)系數(shù)是控制平移的速度,要根據(jù)相機(jī)和目標(biāo)物體的distance來(lái)靈活選擇 target.position = initPosition - 0.01f * ((curScreenPos.x - initScreenPos.x) * cameraX + (curScreenPos.y - initScreenPos.y) * cameraY); //重新計(jì)算位置 Vector3 mPosition = storeRotation * new Vector3 (0.0F, 0.0F, -Distance) + target.position; transform.position = mPosition; // //用這個(gè)會(huì)讓相機(jī)的平移變得更平滑,但是可能在你buttonup時(shí)未使相機(jī)移動(dòng)到應(yīng)到的位置,導(dǎo)致再進(jìn)行旋轉(zhuǎn)與縮放操作時(shí)出現(xiàn)短暫抖動(dòng) //transform.position=Vector3.Lerp(transform.position,mPosition,Time.deltaTime*moveSpeed); } if (Input.GetMouseButtonUp (2)) { Debug.Log ("upOnce"); //平移結(jié)束把cameraTargetPosition的位置更新一下,不然會(huì)影響縮放與旋轉(zhuǎn)功能 CameraTargetPosition = target.position; } } //將angle限制在min~max之間 static float ClampAngle (float angle, float min, float max) { if (angle < -360) angle += 360; if (angle > 360) angle -= 360; return Mathf.Clamp (angle, min, max); } void testScreenToWorldPoint () { //第三個(gè)坐標(biāo)指的是在相機(jī)z軸指向方向上的距離 Vector3 screenPoint = Camera.main.WorldToScreenPoint (CameraTargetPosition); Debug.Log ("ScreenPoint: " + screenPoint); // var worldPosition = Camera.main.ScreenToWorldPoint(new Vector3(1,1,10)); // Debug.Log("worldPosition: "+worldPosition); } }
實(shí)現(xiàn)的效果如下圖:
demo工程在此下載:MouseLookDemoWithUnity3D
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
欄 目:C#教程
下一篇:Unity實(shí)現(xiàn)卡拉OK歌詞過(guò)渡效果
本文標(biāo)題:Unity3D使用鼠標(biāo)旋轉(zhuǎn)縮放平移視角
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/4729.html
您可能感興趣的文章
- 01-10C#使用Dispose模式實(shí)現(xiàn)手動(dòng)對(duì)資源的釋放
- 01-10C#3.0使用EventLog類寫Windows事件日志的方法
- 01-10C#使用windows服務(wù)開(kāi)啟應(yīng)用程序的方法
- 01-10c# ArrayList的使用方法小總結(jié)
- 01-10C#使用ADO.Net部件來(lái)訪問(wèn)Access數(shù)據(jù)庫(kù)的方法
- 01-10C#禁止textbox復(fù)制、粘貼、剪切及鼠標(biāo)右鍵的方法
- 01-10C#使用Mutex簡(jiǎn)單實(shí)現(xiàn)程序單實(shí)例運(yùn)行的方法
- 01-10使用Nopcommerce為商城添加滿XX減XX優(yōu)惠券功能
- 01-10winform實(shí)現(xiàn)限制及解除鼠標(biāo)移動(dòng)范圍的方法
- 01-10C#中yield用法使用說(shuō)明


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10delphi制作wav文件的方法
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文