Unity3d 攝像機跟隨 右鍵旋轉
阿新 • • 發佈:2019-02-08
呼叫
private CameraMMO _cameraMMO; private CameraMMO cameraMMO { get { if (_cameraMMO == null) { _cameraMMO = gameObject.AddComponent<CameraMMO>(); _cameraMMO.Init( GameObject.FindGameObjectWithTag("Player").transform, Camera.main.transform); } return _cameraMMO; } }
CameraMMO.cs
// We developed a simple but useful MMORPG style camera. The player can zoom in // and out with the mouse wheel and rotate the camera around the hero by holding // down the right mouse button. // // Note: we turned off the linecast obstacle detection because it would require // colliders on all environment models, which means additional physics // complexity (which is not needed due to navmesh movement) and additional // components on many gameobjects. Even if performance is not a problem, there // is still the weird case where if a tent would have a collider, the inside // would still be part of the navmesh, but it's not clickable because of the // collider. Clicking on top of that collider would move the agent into the tent // though, which is not very good. Not worrying about all those things and // having a fast server is a better tradeoff. using UnityEngine; public class CameraMMO : MonoBehaviour { Transform targetT; Transform cameraT; public int mouseButton = 1; // right button by default public float distance = 20; public float minDistance = 3; public float maxDistance = 20; public float zoomSpeedMouse = 1; public float zoomSpeedTouch = 0.2f; public float rotationSpeed = 2; public float xMinAngle = -40; public float xMaxAngle = 80; // the target position can be adjusted by an offset in order to foucs on a // target's head for example public Vector3 offset = Vector3.zero; // the layer mask to use when trying to detect view blocking // (this way we dont zoom in all the way when standing in another entity) // (-> create a entity layer for them if needed) //public LayerMask layerMask; // store rotation so that unity never modifies it, otherwise unity will put // it back to 360 as soon as it's <0, which makes a negative min angle // impossible Vector3 rot; #region Init() 初始化 public bool isInit { get; private set; } public void Init(Transform targetT, Transform cameraT) { if (false == isInit) { this.targetT = targetT; this.cameraT = cameraT; cameraT.position = targetT.position - (cameraT.rotation * Vector3.forward * distance); rot = cameraT.eulerAngles; isInit = true; } } #endregion void LateUpdate() { if (!isInit) return; var targetPos = targetT.position + offset; // rotation and zoom should only happen if not in a UI right now if (!IsCursorOverUserInterface()) { // right mouse rotation if we have a mouse if (Input.mousePresent) { if (Input.GetMouseButton(mouseButton)) { // note: mouse x is for y rotation and vice versa rot.y += Input.GetAxis("Mouse X") * rotationSpeed; rot.x -= Input.GetAxis("Mouse Y") * rotationSpeed; rot.x = Mathf.Clamp(rot.x, xMinAngle, xMaxAngle); cameraT.rotation = Quaternion.Euler(rot.x, rot.y, 0); } } else { // forced 45 degree if there is no mouse to rotate (for mobile) cameraT.rotation = Quaternion.Euler(new Vector3(45, 0, 0)); } // zoom float speed = Input.mousePresent ? zoomSpeedMouse : zoomSpeedTouch; float step = GetZoomUniversal() * speed; distance = Mathf.Clamp(distance - step, minDistance, maxDistance); } // target follow cameraT.position = targetPos - (cameraT.rotation * Vector3.forward * distance); } static float GetZoomUniversal() { if (Input.mousePresent) return GetAxisRawScrollUniversal(); else if (Input.touchSupported) return GetPinch(); return 0; } // two finger pinch detection // source: https://docs.unity3d.com/Manual/PlatformDependentCompilation.html static float GetPinch() { if (Input.touchCount == 2) { // Store both touches. Touch touchZero = Input.GetTouch(0); Touch touchOne = Input.GetTouch(1); // Find the position in the previous frame of each touch. Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition; Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition; // Find the magnitude of the vector (the distance) between the touches in each frame. float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude; float touchDeltaMag = (touchZero.position - touchOne.position).magnitude; // Find the difference in the distances between each frame. return touchDeltaMag - prevTouchDeltaMag; } return 0; } static bool IsCursorOverUserInterface() { //// IsPointerOverGameObject check for left mouse (default) //if (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject()) // return true; //// IsPointerOverGameObject check for touches //for (int i = 0; i < Input.touchCount; ++i) // if (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject(Input.GetTouch(i).fingerId)) // return true; //// OnGUI check //return GUIUtility.hotControl != 0; return false; } // hard mouse scrolling that is consistent between all platforms // Input.GetAxis("Mouse ScrollWheel") and // Input.GetAxisRaw("Mouse ScrollWheel") // both return values like 0.01 on standalone and 0.5 on WebGL, which // causes too fast zooming on WebGL etc. // normally GetAxisRaw should return -1,0,1, but it doesn't for scrolling static float GetAxisRawScrollUniversal() { float scroll = Input.GetAxisRaw("Mouse ScrollWheel"); if (scroll < 0) return -1; if (scroll > 0) return 1; return 0; } }