美術在使用Unity編輯地形時,提出了讓場景相機勻速運動的需求,因爲Unity原本的場景相機移動速度不可控,同時在移動過程中會加速。在網上找了很多沒有確切的解決方案,Unity似乎也並沒有提供相關的接口。筆者嘗試了一種利用EditorWindow的Update刷新相機位置的方法,效果還不錯。
首先創建一個EditorWindow,並在OnGui中提供速度的輸入框。
如果仍使用Unity原有的相機控制快捷鍵,在持續運動相機一段時間後,Unity自帶的相機速度會加到很大,而Unity自己處理Scene相機頻率比Update快,即使我們在每次Update的時候手動設置了相機位置,仍然會造成相機位置突變,導致圖像晃動。因此筆者採用了一組新的快捷鍵(方向鍵+鼠標右鍵)的組合,既不與現有操作衝突,又可以在移動過程中隨時調整相機角度。
通過SceneView.onSceneGUIDelegate註冊場景事件,捕捉按鍵變化,並在每個Update中獲取相機角度,計算運動後的位置。
具體代碼如下:
public class SceneCameraControlWindow : EditorWindow
{
private string m_speedStr = "1";
private float m_speed = 1f;
private bool m_enable = false;
private Vector3 m_curMove;
private void OnEnable()
{
SceneView.onSceneGUIDelegate += OnSceneFunc;
}
private void OnDisable()
{
SceneView.onSceneGUIDelegate -= OnSceneFunc;
}
private void OnGUI()
{
GUILayout.BeginHorizontal();
GUILayout.Label("速度:");
string newStr = GUILayout.TextField(m_speedStr);
GUILayout.EndHorizontal();
GUILayout.Label("按住鼠標右鍵+方向鍵(↑、↓、←、→)移動相機");
float newSpeed;
if(newStr != m_speedStr && float.TryParse(newStr, out newSpeed) && newSpeed >= 0)
{
m_speedStr = newStr;
m_speed = newSpeed;
}
}
private void Update()
{
if(m_enable && null != SceneView.lastActiveSceneView)
{
SceneView.lastActiveSceneView.pivot += (SceneView.lastActiveSceneView.camera.transform.rotation * m_curMove) * m_speed * Time.deltaTime;
}
}
private void OnSceneFunc(SceneView target)
{
if (null == SceneView.lastActiveSceneView || target != SceneView.lastActiveSceneView)
return;
switch (Event.current.type)
{
case EventType.MouseDown:
if(Event.current.button == 1)
{
m_enable = true;
}
break;
case EventType.MouseUp:
if (Event.current.button == 1)
{
m_enable = false;
}
break;
case EventType.KeyDown:
switch (Event.current.keyCode)
{
case KeyCode.UpArrow:
m_curMove.z = 1f;
break;
case KeyCode.DownArrow:
m_curMove.z = -1f;
break;
case KeyCode.LeftArrow:
m_curMove.x = -1f;
break;
case KeyCode.RightArrow:
m_curMove.x = 1f;
break;
}
break;
case EventType.KeyUp:
switch (Event.current.keyCode)
{
case KeyCode.UpArrow:
m_curMove.z = 0f;
break;
case KeyCode.DownArrow:
m_curMove.z = 0f;
break;
case KeyCode.LeftArrow:
m_curMove.x = 0f;
break;
case KeyCode.RightArrow:
m_curMove.x = 0f;
break;
}
break;
}
}
}