Game视图中实现类Scene中Camera的控制(非自身中心)

	//此版本是在摄像机跟随物体的基础上改的,自己用了感觉挺好的,一点不足是因为相机跟随物体,所以相机旋转是以目标物体为中心旋转的,而并不是绕相机自身。我的做法是把Target设置成空物体,下面不挂任何mesh,办法可能比较老土,哈哈。。欢迎指正!!)
using UnityEngine;
using System.Collections;

//[ExecuteInEditMode]
public class MyDungeonCamera : MonoBehaviour
{
    /// [摄像机控制参数]
    public GameObject Target = null;
    public float RotateX = 0f;                                  // 俯仰角度(垂直)
    public float RotateY = 180.0f;                              // 偏航角度(水平)
    public float Distance = 10f;                                // 摄像机远近
    public float MoveSmoothTime = 0.3f;                         // 位置平滑时间
    public float RotateSmoothTime = 0.3f;                       // 旋转平滑时间
    public float ScrollWheelSpeed = 1000f;                      // 中轴调整速度
    public Vector3 TargetOffset = Vector3.zero;                 // 目标偏移量

    private Vector3 Velocity = Vector3.zero;                    // 平滑初速度
    private Vector3 Offset = Vector3.zero;                      // 根据上面三个变量计算出
    private const float MinDistance = 2f;                       // 镜头最近距离
    private const float MaxDistance = 100f;                     // 镜头最远距离
    private Quaternion tmpRotation = Quaternion.identity;
    private Vector3 tmpPosition = Vector3.zero;

    /// [Target参数]
    private float m_Horizontal;
    private float m_Vertical;
    private float m_UpDown;

    private float RotateDamping
    {
        get
        {
            if (RotateSmoothTime <= 0f) RotateSmoothTime = 0.001f;
            return 1f / RotateSmoothTime;
        }
    }

    void Update()
    {
        TargetCtrl();
    }


    void LateUpdate()
    {
        if (Target == null) return;

        tmpRotation = transform.rotation;
        tmpPosition = transform.position;

        UpdateDistance();
        UpdateRotation();
        UpdatePosition();

        transform.rotation = tmpRotation;
        transform.position = tmpPosition;
    }

    private void UpdateRotation()
    {
        if (!NeedRotate()) return;
        
        Quaternion wantedRotation = Quaternion.Euler(RotateX, RotateY, 0f);
        // 旋转采用球形插值
        tmpRotation = Quaternion.Slerp(tmpRotation, wantedRotation, Time.deltaTime * RotateDamping);
        // 实现实时方向改变
        Target.transform.forward = transform.forward;
    }

    private void UpdatePosition()
    {
        // 如果有旋转插值,则位置根据旋转变换;否则,位置自己进行插值过渡
        if (!NeedRotate())
        {
            Offset = Quaternion.Euler(RotateX, RotateY, 0f) * Vector3.forward * Distance;
            Vector3 wantedPos = Target.transform.position - Offset + TargetOffset;
            // 位置采用平滑阻尼过渡
            tmpPosition = Vector3.SmoothDamp(tmpPosition, wantedPos, ref Velocity, MoveSmoothTime);
        }
        else
        {
            Offset = tmpRotation * Vector3.forward * Distance;
            tmpPosition = Target.transform.position - Offset + TargetOffset;
        }
    }

    private void UpdateDistance()
    {
        float horizontal = Input.GetAxis("Mouse ScrollWheel") * ScrollWheelSpeed * Time.deltaTime;
        Distance -= horizontal;
        Distance = Mathf.Clamp(Distance, MinDistance, MaxDistance);
    }

    private bool NeedRotate()
    {
        Vector3 eulerAngles = transform.rotation.eulerAngles;
        return !(FloatEqual(eulerAngles.x, RotateX) && FloatEqual(eulerAngles.y, RotateY));
    }

    public static bool FloatEqual(float value1, float value2)
    {
        float ret = value1 - value2;
        return ret > -0.0005f && ret < 0.0005f;
    }

    /// <summary>
    /// Target移动控制
    /// </summary>
    private void TargetCtrl()
    {
        m_Horizontal = Input.GetAxis("Horizontal") * Time.deltaTime * 4;
        m_Vertical = Input.GetAxis("Vertical") * Time.deltaTime * 4;

        if (Input.GetKey(KeyCode.Mouse1))
        {
            
            RotateX -=Input.GetAxis("Mouse Y") * Time.deltaTime * 50;
            RotateX = Mathf.Clamp(RotateX, -50, 88);
            RotateY -= -Input.GetAxis("Mouse X") * Time.deltaTime * 50;
            RotateY = Mathf.Clamp(RotateY, -110, 110);
        }

        if (Input.GetKey(KeyCode.Q))
        {
            m_UpDown -= 0.3f * Time.deltaTime;
        }
        else if (Input.GetKey(KeyCode.E))
        {
            m_UpDown += 0.3f * Time.deltaTime;
        }
        else
        {
            m_UpDown = 0;
        }
        Target.transform.Translate(m_Horizontal, m_UpDown, m_Vertical);
        //Target.transform.forward = transform.forward;
    }


}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sam_ONE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值