Unity 3rd person follow camera

It can be rotated and zoomed, and the displacement when detecting the collision to try to keep the object from being occluded. Not much to say, go directly to the code

using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;

[AddComponentMenu("Zetan/Third Person Camera Follow")]
public class CameraFollow : MonoBehaviour {

    public Transform target;
    public Vector3 headOffset = Vector3.zero;
    public bool smooth;
    public float smoothLevel = 0.5f;
    Vector3 direction;
    public float rotateSpeed = 10.0f;
    public float zoomSpeed = 5f;
    public float minDistance = 3.0f;
    public float maxDistance = 15.0f;
    public float maxLookUpAngle = 80.0f;
    public float maxLookDownAngle = 30.0f;

    [SerializeField]
    float OriginDistance;
    [SerializeField]
    float currentDistance;

    Vector3 visibleEuler;

    // Use this for initialization
    void Start() {
        ResetView();
    }

    // Update is called once per frame
    void Update() {
        visibleEuler = ConvertEulerAngle(transform.rotation.eulerAngles);
    }

    private void LateUpdate()
    {
        float h = CrossPlatformInputManager.GetAxis("Mouse X");
        float v = CrossPlatformInputManager.GetAxis("Mouse Y");
        float zoom = CrossPlatformInputManager.GetAxis("Mouse ScrollWheel");
        Translate(zoom);
        Rotate(h, v);
    }

    void Translate(float zoom)
    {
        OriginDistance -= zoom * zoomSpeed;
        OriginDistance = Mathf.Clamp(OriginDistance, minDistance, maxDistance);
        RaycastHit hit;
        if (Physics.Raycast(target.position + headOffset, transform.position - target.position - headOffset, out hit, OriginDistance,
            ~(1 << LayerMask.NameToLayer("Water") | 1 << LayerMask.NameToLayer("Player")), QueryTriggerInteraction.Ignore))//The detection layer is changed according to requirements
        {
            currentDistance = hit.distance;
        }
        else
        {
            currentDistance = OriginDistance;
        }
        Vector3 disOffset = direction.normalized * currentDistance;
        if(smooth)transform.position = Vector3.Lerp(transform.position, target.position + headOffset + disOffset, smoothLevel);//Smooth movement, but the cumulative difference will cause the camera to gradually return to a certain perspective, with a slight jitter
        else transform.position = target.position + headOffset + disOffset;//There is a slight freeze when rotating
        transform.LookAt(target);
    }

    void Rotate(float h, float v)
    {
        float finallyRotateV = v * rotateSpeed;
        if (finallyRotateV + visibleEuler.x >= maxLookUpAngle)
        {
            finallyRotateV = visibleEuler.x + finallyRotateV - maxLookUpAngle;
        }
        else if (finallyRotateV + visibleEuler.x <= -maxLookDownAngle)
        {
            finallyRotateV = visibleEuler.x + finallyRotateV + maxLookDownAngle;
        }
        //rotate left and right
        transform.RotateAround(target.position + headOffset, transform.up, h * rotateSpeed);
        // rotate up and down
        transform.RotateAround(target.position + headOffset, transform.right, -finallyRotateV);
        transform.LookAt(target.position + headOffset);
        direction = (transform.position - target.position - headOffset).normalized;
    }

    public float ConvertAngle(float value)
    {
        float angle = value - 180;

        if (angle > 0)
            return angle - 180;

        return angle + 180;
    }

    public Vector3 ConvertEulerAngle(Vector3 euler)
    {
        return new Vector3(ConvertAngle(euler.x), ConvertAngle(euler.y), ConvertAngle(euler.z));
    }

    public void ResetView()
    {
        if(minDistance > maxDistance)
        {
            maxDistance += minDistance;
            minDistance = maxDistance - minDistance;
            maxDistance -= minDistance;
        }
        direction = -target.forward;
        Vector3 disOffset = direction * (minDistance + maxDistance) / 2;
        transform.position = target.position + headOffset + disOffset;
        OriginDistance = disOffset.magnitude;
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawLine(target.position + headOffset, transform.position);
        Gizmos.color = Color.yellow;
        Gizmos.DrawWireSphere(target.position + headOffset, minDistance);
        Gizmos.DrawLine(target.position + headOffset + target.forward * minDistance, target.position + headOffset + target.forward * maxDistance);
        Gizmos.DrawLine(target.position + headOffset - target.forward * minDistance, target.position + headOffset - target.forward * maxDistance);
        Gizmos.DrawLine(target.position + headOffset + target.up * minDistance, target.position + headOffset + target.up * maxDistance);
        Gizmos.DrawLine(target.position + headOffset - target.up * minDistance, target.position + headOffset - target.up * maxDistance);
        Gizmos.DrawLine(target.position + headOffset + target.right * minDistance, target.position + headOffset + target.right * maxDistance);
        Gizmos.DrawLine(target.position + headOffset - target.right * minDistance, target.position + headOffset - target.right * maxDistance);
        Gizmos.DrawWireSphere(target.position + headOffset, maxDistance);
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324722029&siteId=291194637