Unity3D经典案例游戏:TANKS! Phase 3 of 8 - Camera Control 相关源C#代码解析

该源代码转载自Unity游戏案例中的TANKS代码中

------------来自第二次使用Unity3D制作游戏的游戏制作新人小白

一、代码自我解析

二、油管学习地址

三、Unity3D源代码

 

 

一、源代码自我解析

using UnityEngine;

public class CameraControl : MonoBehaviour
{
    public float m_DampTime = 0.2f;                 // 摄像机延迟移动时间系数
    public float m_ScreenEdgeBuffer = 4f;           // 在最上面/下面的目标和屏幕边缘之间的空间(边缘缓冲区大小)
    public float m_MinSize = 6.5f;                  // 正交摄像机所能看的最小尺寸
    /*[HideInInspector]*/ public Transform[] m_Targets;
                                                    // 摄像机需要包含的所有目标


    private Camera m_Camera;                        // 用于引用摄像机
    private float m_ZoomSpeed;                      // 定义摄像机变焦的速率
    private Vector3 m_MoveVelocity;                 // 用于相机移动时对速度进行缓冲的向量
    private Vector3 m_DesiredPosition;              // 相机移动的位置


    private void Awake()
    {
        m_Camera = GetComponentInChildren<Camera>();    // 游戏一开始便使m_Camera对象获取场景中的相机
    }


    private void FixedUpdate()
    {
        // 移动相机
        Move();

        // 改变相机的焦距大小
        Zoom();
    }


    private void Move()
    {
        // 找到目标到原点的平均位置所在(坦克的移动路线上的中点)
        FindAveragePosition();

        // 使相机光滑地移动到目标位置
        transform.position = Vector3.SmoothDamp(transform.position, m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
    }


    private void FindAveragePosition()
    {
        Vector3 averagePos = new Vector3();
        int numTargets = 0;

        // 检查所有的目标并将它们的位置相加(所有坦克)
        for (int i = 0; i < m_Targets.Length; i++)
        {
            // 如果目标不存在,跳过并继续执行for循环
            if (!m_Targets[i].gameObject.activeSelf)
                continue;

            // 通过添加到平均值中,并在平均值中增加目标的数量。
            averagePos += m_Targets[i].position;
            numTargets++;
        }

        // 检测目标数是否大于0若是便计算出平均的位置
        if (numTargets > 0)
            averagePos /= numTargets;

        // 保持y值不变,坦克不会飞,所以y一定不能改变
        averagePos.y = transform.position.y;

        // 计算出来的平均位置就是相机要移动到的位置
        m_DesiredPosition = averagePos;
    }


    private void Zoom()
    {
        // 根据所需的位置找到所需的大小,并顺利过渡到该大小。
        float requiredSize = FindRequiredSize();
        m_Camera.orthographicSize = Mathf.SmoothDamp(m_Camera.orthographicSize, requiredSize, ref m_ZoomSpeed, m_DampTime);
    }


    private float FindRequiredSize()
    {
        // 找到相机设备在其本地空间中移动的位置。
        Vector3 desiredLocalPos = transform.InverseTransformPoint(m_DesiredPosition);

        // 将相机变焦大小初始值设为0
        float size = 0f;

        // 遍历一遍相机照射目标
        for (int i = 0; i < m_Targets.Length; i++)
        {
            // 如果目标不存在,跳过并继续执行for循环
            if (!m_Targets[i].gameObject.activeSelf)
                continue;

            // 此外,找到目标在摄像机所在的本地空间里的坐标
            Vector3 targetLocalPos = transform.InverseTransformPoint(m_Targets[i].position);

            // 从相机的本地空间的期望位置找到目标的位置
            Vector3 desiredPosToTarget = targetLocalPos - desiredLocalPos;

            // 从当前大小和坦克与相机的“上”或“下”距离中选择最大的一个。(位置不变或者是拉伸摄像机)
            size = Mathf.Max (size, Mathf.Abs (desiredPosToTarget.y));

            // 根据坦克出现在摄像机的左或右,选择当前尺寸中最大的那一个
            size = Mathf.Max (size, Mathf.Abs (desiredPosToTarget.x) / m_Camera.aspect);
        }

        // 将边缘缓冲区添加到该大小
        size += m_ScreenEdgeBuffer;

        // 确保相机的尺寸不小于最小值
        size = Mathf.Max(size, m_MinSize);

        return size;
    }


    public void SetStartPositionAndSize()
    {
        // 找到期望位置
        FindAveragePosition();

        // 在没有阻尼时设置相机位置到期望位置(阻尼即相机的缓冲)个人理解类似摩擦力之类的使得相机移动更平滑
        transform.position = m_DesiredPosition;

        m_Camera.orthographicSize = FindRequiredSize();
    }
}

 

// 以上只是自己对于该代码的理解,如有误还望指出让我及时改正。

 

二、油管学习Unity地址  

 

https://www.youtube.com/watch?v=paLLfWd2k5A

 

三、Unity3D中该案例源代码:

using UnityEngine;

namespace Complete
{
    public class CameraControl : MonoBehaviour
    {
        public float m_DampTime = 0.2f;                 // Approximate time for the camera to refocus.
        public float m_ScreenEdgeBuffer = 4f;           // Space between the top/bottom most target and the screen edge.
        public float m_MinSize = 6.5f;                  // The smallest orthographic size the camera can be.
        [HideInInspector] public Transform[] m_Targets; // All the targets the camera needs to encompass.


        private Camera m_Camera;                        // Used for referencing the camera.
        private float m_ZoomSpeed;                      // Reference speed for the smooth damping of the orthographic size.
        private Vector3 m_MoveVelocity;                 // Reference velocity for the smooth damping of the position.
        private Vector3 m_DesiredPosition;              // The position the camera is moving towards.


        private void Awake ()
        {
            m_Camera = GetComponentInChildren<Camera> ();
        }


        private void FixedUpdate ()
        {
            // Move the camera towards a desired position.
            Move ();

            // Change the size of the camera based.
            Zoom ();
        }


        private void Move ()
        {
            // Find the average position of the targets.
            FindAveragePosition ();

            // Smoothly transition to that position.
            transform.position = Vector3.SmoothDamp(transform.position, m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
        }


        private void FindAveragePosition ()
        {
            Vector3 averagePos = new Vector3 ();
            int numTargets = 0;

            // Go through all the targets and add their positions together.
            for (int i = 0; i < m_Targets.Length; i++)
            {
                // If the target isn't active, go on to the next one.
                if (!m_Targets[i].gameObject.activeSelf)
                    continue;

                // Add to the average and increment the number of targets in the average.
                averagePos += m_Targets[i].position;
                numTargets++;
            }

            // If there are targets divide the sum of the positions by the number of them to find the average.
            if (numTargets > 0)
                averagePos /= numTargets;

            // Keep the same y value.
            averagePos.y = transform.position.y;

            // The desired position is the average position;
            m_DesiredPosition = averagePos;
        }


        private void Zoom ()
        {
            // Find the required size based on the desired position and smoothly transition to that size.
            float requiredSize = FindRequiredSize();
            m_Camera.orthographicSize = Mathf.SmoothDamp (m_Camera.orthographicSize, requiredSize, ref m_ZoomSpeed, m_DampTime);
        }


        private float FindRequiredSize ()
        {
            // Find the position the camera rig is moving towards in its local space.
            Vector3 desiredLocalPos = transform.InverseTransformPoint(m_DesiredPosition);

            // Start the camera's size calculation at zero.
            float size = 0f;

            // Go through all the targets...
            for (int i = 0; i < m_Targets.Length; i++)
            {
                // ... and if they aren't active continue on to the next target.
                if (!m_Targets[i].gameObject.activeSelf)
                    continue;

                // Otherwise, find the position of the target in the camera's local space.
                Vector3 targetLocalPos = transform.InverseTransformPoint(m_Targets[i].position);

                // Find the position of the target from the desired position of the camera's local space.
                Vector3 desiredPosToTarget = targetLocalPos - desiredLocalPos;

                // Choose the largest out of the current size and the distance of the tank 'up' or 'down' from the camera.
                size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.y));

                // Choose the largest out of the current size and the calculated size based on the tank being to the left or right of the camera.
                size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.x) / m_Camera.aspect);
            }

            // Add the edge buffer to the size.
            size += m_ScreenEdgeBuffer;

            // Make sure the camera's size isn't below the minimum.
            size = Mathf.Max (size, m_MinSize);

            return size;
        }


        public void SetStartPositionAndSize ()
        {
            // Find the desired position.
            FindAveragePosition ();

            // Set the camera's position to the desired position without damping.
            transform.position = m_DesiredPosition;

            // Find and set the required size of the camera.
            m_Camera.orthographicSize = FindRequiredSize ();
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值