第三人称防穿墙相机

using UnityEngine;

public class ThirdCamera : MonoBehaviour
{

    [SerializeField] private float rotateSpeed = 360;
    [Header("拉近拉远的速度")]
    [SerializeField] private float mouseScrollSpeed = 30;
    [Header("当前相机到target的距离,不滑动中键的话可以手动调整")]
    [HideInInspector] public float Distance = 3;
    [Header("相机到target的最大距离,最小默认为0")]
     public float MaxDistance = 3;
    [Header("限制相机相对target的方向与水平面的角度")]
    [SerializeField] private float clampAngle = 30;
    /// <summary> 相机相对target的方向 </summary>
     private Vector3 cameraDir = new Vector3(0, 4.3f,-9.8f);

    [SerializeField] private Transform target;
    public Vector3 TargetDir => cameraDir.normalized * Mathf.Clamp(Distance, 0, MaxDistance);
    public Transform Target => target;
    public void SetTargetStart(Transform target)
    {
        this.target = target;
    }
    void FixedUpdate()
    {
        if (!target)
            return;
        Rotate();
        MouseScrollWheel();
        Chuangqiang();
        transform.position = target.transform.TransformPoint(TargetDir);
        transform.localRotation = Quaternion.LookRotation(-transform.position + target.transform.position);
    }
    /// <summary> 旋转 </summary>
    void Rotate()
    {
        if (!Input.GetMouseButton(0))
            return;
        float angleX = Input.GetAxis("Mouse X") * rotateSpeed * Time.deltaTime;
        float angleY = Input.GetAxis("Mouse Y") * rotateSpeed * Time.deltaTime;
        if (Mathf.Abs(angleX) > Mathf.Abs(angleY))
            angleY = 0;
        else
            angleX = 0;

        var euler = -transform.right * angleY + Vector3.up * angleX;
        //记录
        var lastDir = cameraDir;
        cameraDir = Quaternion.Euler(euler) * cameraDir;
        //计算角度
        var dirProject = Vector3.ProjectOnPlane(cameraDir, Vector3.up);
        float angle = Vector3.Angle(cameraDir, dirProject);
        if (angle > clampAngle)
        {
            
            cameraDir = lastDir;
        }
    }
    /// <summary> 防穿墙 </summary>
    void Chuangqiang()
    {
        Ray ray = new Ray(target.transform.position, transform.position - target.transform.position);
        target.gameObject.layer = 2;
        gameObject.layer = 2;
        if (Physics.Raycast(ray, out RaycastHit hit, 100))
        {
            float hitDistance = Vector3.Distance(hit.point, target.transform.position);
            Distance = Mathf.Min(hitDistance, Distance);
        }
        target.gameObject.layer = 0;
        gameObject.layer = 0;
    }
    /// <summary> 鼠标中键滚轮</summary>
    void MouseScrollWheel()
    {
        float mouseScroll = Input.GetAxis("Mouse ScrollWheel");
        if (mouseScroll != 0)
        {
            Distance -= mouseScroll * Time.deltaTime * mouseScrollSpeed;
            Distance = Mathf.Clamp(Distance, 0, MaxDistance);
        }
    }
}

#region Editor
#if UNITY_EDITOR
namespace XPEditor
{
    using UnityEditor;
    [CustomEditor(typeof(ThirdCamera))]
    public class ThirdCameraEditor : Editor
    {
        ThirdCamera thirdCamera;
        private void Awake()
        {
            thirdCamera = target as ThirdCamera;

        }
        public override void OnInspectorGUI()
        {
             base.OnInspectorGUI();
           thirdCamera.Distance =  EditorGUILayout.Slider( new GUIContent("当前距离"),thirdCamera.Distance,0,thirdCamera.MaxDistance);
            serializedObject.ApplyModifiedProperties();
    
        }
    }
}
#endif
#endregion
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值