###### tags: `Unity` {%hackmd @kk6333/theme-sty1 %} # Unity3D : 畫面控制 ( 視窗拖曳、縮放、旋轉 ) 當在製作一些第三視角的遊戲時, 一定很常會用到畫面縮放、拖曳畫面、旋轉視野角度 ... 等畫面控制功能 這篇筆記會實踐此三個功能,如果其中有 Bug、或有更好的方法歡迎留言 ~ 先上成果的影片 {%youtube 7d4h2bUqy6I %} <br> ## 1. 概念想法 我們會分三個函數,並用不同滑鼠按鍵實踐功能 - 旋轉畫面 : 右鍵按住拖曳 - 移動畫面 : 左鍵按住拖曳 - 縮放畫面 : 滾輪轉動 在縮放畫面這塊,會使用一個 Target 物件做示範, 此 Target 其實是可有可無,在這是用來限制與物件的縮放距離 ## 2. 實作 接下來的三個函數是統整在一個 Script 裡取名 Cam_Control 並將 Script 掛在 Main Camerea 下 ![](https://i.imgur.com/ndr188J.png) --- ### 變數設定 ```csharp= public Transform Map; // Target 物件 public Transform fixed_X_Rotate_point; // 利用此點做拖拉平移 (旋轉點) // 最小、最大縮放距離 public float minZoomDist; public float maxZoomDist; // 滑鼠位置 private float rotate_x = 0; private float rotate_y = 0; private float mouse_x = 0; private float mouse_y = 0; // 將按鍵編號用 private enum MouseButton { MouseBtn_Left = 0, MouseBtn_Right = 1, MouseBtn_roll = 2} ``` > 特別提一下此三個變數 > 是用來調控操作的靈敏度,可以把它設為 float 變數 > 這邊是因為方便操作所以寫在另一個函數中 ( ~~其實是我懶得改~~ ) ```csharp= User_info.instance.cam_rotate_speed // 旋轉靈敏度 (float) User_info.instance.cam_move_speed // 移動靈敏度 (float) User_info.instance.cam_zoom_speed // 縮放靈敏度 (float) ``` --- ### Updata > 這邊會按照順序偵測、呼叫功能 ```csharp= private void Update() { Move(); Rotate(); Zoom(); } ``` --- ### 旋轉畫面 > 這邊會利用一個**空物件** "fixed_X_Rotate_point" 作為旋轉角度的基準點 > 原因是當我 Camera 旋轉時軸心會亂掉,所以以一個固定物件來做軸的取樣 > > ![](https://i.imgur.com/RkmM1VC.png =200x35) :warning: 旋轉軸物件不要掛在 Camera 底下 ( 子物件 ) ```csharp= void Rotate() { // 取得按鍵事件 if(Map != null && Input.GetMouseButton((int)MouseButton.MouseBtn_Right)) { // 獲得滑鼠移動變量 rotate_x += Input.GetAxis("Mouse X") * User_info.instance.cam_rotate_speed; rotate_y -= Input.GetAxis("Mouse Y") * User_info.instance.cam_rotate_speed; // 利用滑鼠移動變量計算旋轉角度 var rotate = Quaternion.Euler(-rotate_y, -rotate_x, 0 ); // 旋轉鏡頭 transform.rotation = rotate; // 以 y 軸旋轉 fixed_X_rotate ( 旋轉基準點 ) rotate = Quaternion.Euler(0, -rotate_x, 0); fixed_X_Rotate_point.rotation = rotate; } } ``` --- ### 移動畫面 > 這邊比較簡單,偵測滑鼠移動的變量 > 再根據 "變量乘上方向" 來持續對 Camera 做移動 ```csharp= void Move() { // 取得按鍵事件 if (Map != null && Input.GetMouseButton((int)MouseButton.MouseBtn_Left)) { // 獲得滑鼠移動變量 mouse_x = Input.GetAxis("Mouse X") * User_info.instance.cam_move_speed; mouse_y = Input.GetAxis("Mouse Y") * User_info.instance.cam_move_speed; // 移動鏡頭 transform.position -= fixed_X_Rotate_point.forward * mouse_y; transform.position -= fixed_X_Rotate_point.right * mouse_x; } } ``` ### 縮放畫面 > 縮放部分我用一個 Target 物件為縮放的限制, > 這個是不必要的,但當你有個地圖物件,也許會不希望鏡頭可以穿到地底下 (?) > 此物件命名為 Map ```csharp= void Zoom() { if (Map != null && (Input.GetAxis("Mouse ScrollWheel") > 0 || Input.GetAxis("Mouse ScrollWheel") < 0) ) { // 計算 Map 與鏡頭距離 Vector3 diff_vector = transform.position - Map.position; // 防止太過靠近 if (diff_vector.y <= minZoomDist && Input.GetAxis("Mouse ScrollWheel") > 0) return; // 獲得滑鼠滾輪旋轉變量 float zoomD = Input.GetAxis("Mouse ScrollWheel")*User_info.instance.cam_zoom_speed; // 移動鏡頭 transform.position += transform.forward * zoomD; } } ``` ---