1. 程式人生 > >Unity3d 攝像機跟隨 右鍵旋轉

Unity3d 攝像機跟隨 右鍵旋轉

呼叫 

    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;
    }
}