• 总结一下今天做的面试题(三):第三人称相机控制


    同样是先看需求:

    整个地方最难的在于,相机被挤压时要怎么处理。

    由于没玩过上面两款游戏,也不知道是怎么处理的,我自己的想法是让相机直接旋转180度。

    首先贴一下人物控制脚本,别忘了给人物加上Charactor Controll组件

    using UnityEngine;
    using System.Collections;
    
    public class move_controll : MonoBehaviour {
        Transform m_transform,m_camera;
        CharacterController controller;
        float MoveSpeed = 1.0f;
        string[] clipName={"idle","shamble"};
        Animation m_animation;
        // Use this for initialization
        void Start () {
            m_transform = this.transform;
            m_camera = GameObject.FindGameObjectWithTag ("MainCamera").transform;
            controller=GetComponent<CharacterController>();
            m_animation = m_transform.GetComponent<Animation> ();
        }
        
        // Update is called once per frame
        void Update () {
            if ((Input.GetKey (KeyCode.W)) || (Input.GetKey (KeyCode.S)) || (Input.GetKey (KeyCode.A)) || (Input.GetKey (KeyCode.D))) {
                m_animation.Play (clipName[1]);
                if (Input.GetKey (KeyCode.W)) {
                    controller.transform.eulerAngles = new Vector3 (0, m_camera.transform.eulerAngles.y, 0);//the eulerAngles depend on camera's eulerAngles
                }
    
                if (Input.GetKey (KeyCode.S)) {
                    controller.transform.eulerAngles = new Vector3 (0, m_camera.transform.eulerAngles.y+180f, 0);
                }
    
                if (Input.GetKey (KeyCode.A)) {
                    controller.transform.eulerAngles = new Vector3 (0, m_camera.transform.eulerAngles.y+270f, 0);
                }
    
                if (Input.GetKey (KeyCode.D)) {
                    controller.transform.eulerAngles = new Vector3 (0, m_camera.transform.eulerAngles.y+90f, 0);
                }
    
                controller.Move(m_transform.forward * Time.deltaTime * MoveSpeed);
            }
            else
                //idle
                m_animation.Play (clipName[0]);
            //gravity
            if (!controller.isGrounded) {
                controller.Move(new Vector3(0,-10f*Time.deltaTime,0));
            }
        }
    }

    随后是相机控制,这里提供两个版本,一个是用滚轮控制镜头远近的(我从别的地方抄的):

    // ====================================================================================================================
    // Simple rotation and tilt of camera around a pivot object
    // Created by Leslie Young
    // http://www.plyoung.com/ or http://plyoung.wordpress.com/
    // ====================================================================================================================
    
    using UnityEngine;
    
    public class CameraOrbit : MonoBehaviour 
    {
        public Transform pivot;                            // the object being followed
        public Vector3 pivotOffset = Vector3.zero;        // offset from target's pivot
        public Transform target;                        // like a selected object (used with checking if objects between cam and target)
    
        public float distance = 10.0f; // distance from target (used with zoom)
        public float minDistance = 2f;
        public float maxDistance = 15f;
        public float zoomSpeed = 1f;
    
        public float xSpeed = 250.0f;
        public float ySpeed = 120.0f;
    
        public bool allowYTilt = true;
        public float yMinLimit = 30f;
        public float yMaxLimit = 80f;
    
        private float x = 0.0f;
        private float y = 0.0f;
    
        private float targetX = 0f;
        private float targetY = 0f;
        private float targetDistance = 0f;
        private float xVelocity = 1f;
        private float yVelocity = 1f;
        private float zoomVelocity = 1f;
    
        void Start()
        {
            var angles = transform.eulerAngles;
            targetX = x = angles.x;
            targetY = y = ClampAngle(angles.y, yMinLimit, yMaxLimit);
            targetDistance = distance;
        }
    
        void LateUpdate()
        {
            if (pivot)
            {
                // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                // scroll wheel used to zoom in/out
                float scroll = Input.GetAxis("Mouse ScrollWheel");
    
                if (scroll > 0.0f) targetDistance -= zoomSpeed;
                else if (scroll < 0.0f) targetDistance += zoomSpeed;
                targetDistance = Mathf.Clamp(targetDistance, minDistance, maxDistance);
    
                // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                // right mouse button must be held down to tilt/rotate cam
                // or player can use the left mouse button while holding Ctr
                if (Input.GetMouseButton(1) || (Input.GetMouseButton(0) && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) ))
                {
                    targetX += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
                    if (allowYTilt)
                    {
                        targetY -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
                        targetY = ClampAngle(targetY, yMinLimit, yMaxLimit);
                    }
                }
                x = Mathf.SmoothDampAngle(x, targetX, ref xVelocity, 0.3f);
                if (allowYTilt) y = Mathf.SmoothDampAngle(y, targetY, ref yVelocity, 0.3f);
                else y = targetY;
                Quaternion rotation = Quaternion.Euler(y, x, 0);
                distance = Mathf.SmoothDamp(distance, targetDistance, ref zoomVelocity, 0.5f);
    
                // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
                // apply
                Vector3 position = rotation * new Vector3(0.0f, 0.0f, -distance) + pivot.position + pivotOffset;
                transform.rotation = rotation;
                transform.position = position;
    
            }
        }
    
        private float ClampAngle(float angle, float min, float max)
        {
            if (angle < -360) angle += 360;
            if (angle > 360) angle -= 360;
            return Mathf.Clamp(angle, min, max);
        }
    
        // ====================================================================================================================
    }
    CameraOrbit

    然后我以这个脚本为基础来该,首先是人物被遮挡时,相机要拉近:

    采用射线的方式进行检测:

                RaycastHit hit;//ues a ray to make camera not be blocked
                if (Physics.Linecast (position, pivot.position,out hit)) {
                    string name = hit.collider.gameObject.tag;
                    if (name =="Untagged") {
                        targetDistance=(hit.point-pivot.position).magnitude;//if the hit object's tag is Untagged,change the distance
                    }
                }

    然后是相机被挤压导致距离极低时的旋转:

                if (distance > distanceLimit) {
                    position = rotation * new Vector3 (0.0f, 0.0f, -distance) + pivot.position + pivotOffset;
                } else {
                    rotation = Quaternion.Euler(y, x+180f, 0);
                    position = rotation * new Vector3 (0.0f, 0.0f, -m_distance) + pivot.position + pivotOffset;
                    targetX = targetX + 180;
                    x = x + 180;
                }

    整个脚本:

    using UnityEngine;
    using System.Collections;
    
    public class Camera_Controll : MonoBehaviour {
        public Transform pivot;
        public Vector3 pivotOffset = Vector3.zero;    
        public float distance = 10.0f; // distance from target (used with zoom)
        public float distanceLimit=3f;//distance when camera change Angles for 180
        public float zoomSpeed = 1f;
        public float xSpeed = 250.0f;
        public float ySpeed = 120.0f;
    
        public bool allowYTilt = true;
        public float yMinLimit = -60f;
        public float yMaxLimit = 60f;
    
        private float x = 0.0f;
        private float y = 0.0f;
        private float targetX = 0f;
        private float targetY = 0f;
        private float targetDistance = 0f;
        private float xVelocity = 1f;
        private float yVelocity = 1f;
        private float zoomVelocity = 1f;
        private float m_distance;
        // Use this for initialization
        void Start () {
            
            var angles = transform.eulerAngles;
            targetX = x = angles.x;
            targetY = y = ClampAngle(angles.y, yMinLimit, yMaxLimit);
            targetDistance = distance;
            m_distance = distance;
        }
        
        // Update is called once per frame
        void LateUpdate () {
            if (pivot)
            {
                targetDistance = m_distance;
    
                if (Input.GetMouseButton(1) || (Input.GetMouseButton(0) && (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) ))
                {
                    targetX += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
                    if (allowYTilt)
                    {
                        targetY -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;
                        targetY = ClampAngle(targetY, yMinLimit, yMaxLimit);
                    }
                }
                x = Mathf.SmoothDampAngle(x, targetX, ref xVelocity, 0.3f);
                if (allowYTilt) y = Mathf.SmoothDampAngle(y, targetY, ref yVelocity, 0.3f);
                else y = targetY;
                Quaternion rotation = Quaternion.Euler(y, x, 0);
                Vector3 position = rotation * new Vector3(0.0f, 0.0f, -m_distance) + pivot.position;//calculate the true camera positon
                RaycastHit hit;//ues a ray to make camera not be blocked
                if (Physics.Linecast (position, pivot.position,out hit)) {
                    string name = hit.collider.gameObject.tag;
                    if (name =="Untagged") {
                        targetDistance=(hit.point-pivot.position).magnitude;//if the hit object's tag is Untagged,change the distance
                    }
                }
                distance = Mathf.SmoothDamp(distance, targetDistance, ref zoomVelocity, 0.5f);
                if (distance > distanceLimit) {
                    position = rotation * new Vector3 (0.0f, 0.0f, -distance) + pivot.position + pivotOffset;
                } else {
                    rotation = Quaternion.Euler(y, x+180f, 0);
                    position = rotation * new Vector3 (0.0f, 0.0f, -m_distance) + pivot.position + pivotOffset;
                    targetX = targetX + 180;
                    x = x + 180;
                }
                transform.rotation = rotation;
                transform.position = position;
            }
        }
        private float ClampAngle(float angle, float min, float max)
        {
            if (angle < -360) angle += 360;
            if (angle > 360) angle -= 360;
            return Mathf.Clamp(angle, min, max);
        }
    }
    Camera_Controll.cs
  • 相关阅读:
    在thinkphp中批量生成Word并压缩打包下载
    使用phpExcel实现Excel数据的导入导出(完全步骤)
    HTML的几种触发
    IOS上iframe的滚动条失效的解决办法。
    VC6下安装与配置OpenCV1.0
    VS2010+Opencv2.4.0的配置攻略
    could not find the main class
    Makefile 教程
    第一个小程序——显示图像
    自建CDib类库
  • 原文地址:https://www.cnblogs.com/Swallowtail/p/6183161.html
Copyright © 2020-2023  润新知