unity 角色第三视角移动

在以前的仿真项目中用到了第三人称视角的移动,W、S、A、D控制角色的前后左右移动,摄像机跟随角色移动,并且摄像机做了缓冲处理。鼠标右键长按旋转控制镜头旋转,中键滑轮控制镜头拉进拉远。分为两个脚本,CharacterThirdControl挂在角色身上,CameraThirdControl挂在跟随摄像机身上。角色的标签设置为Player。跟随摄像机为主摄像机(可以根据自己需求改变)。下面直接贴代码,代码中已有注释:

1,CharacterThirdControl.cs

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(CharacterController))]
public class CharacterThirdControl: MonoBehaviour {

    Transform myCamera;  //跟随摄像机
    private CharacterController cc;
    Vector3 playerDirect;         //角色的目标方向
    Vector3 correctDirect;       //为了矫正计算方向向量的误差
    float perError = 0.2f;       //误差与摄像机缓冲存在关系
    float speed = 0.1f;            //速度与Update的帧数有关,同样数据帧数越多,速度越快
    Vector3 front;  //前
    Vector3 back;  //后
    Vector3 left;    //左
    Vector3 right; //右
    // Use this for initialization
    void Start()
    {
        myCamera = Camera.main.transform;  //将主摄像机设置为跟随摄像机
        front = Vector3.zero;
        back = Vector3.zero;
        left = Vector3.zero;
        right = Vector3.zero;
        correctDirect = Vector3.zero;
        cc = transform.GetComponent<CharacterController>();
    }

    void LateUpdate()
    {
        PlayerControl();
    }

    /// <summary>
    /// 计算方向向量函数
    /// </summary>
    private void CalculateDirection()
    {
        Vector3 temp = transform.position - myCamera.position;
        temp = new Vector3(temp.x, 0, temp.z);
        front = temp;
        if (correctDirect!=Vector3.zero && Mathf.Abs(correctDirect.x-front.x)< perError && Mathf.Abs(correctDirect.z - front.z) < perError)  //判断是否在误差范围内
        {
            front = correctDirect;
        }  
        back = -front;
        left =new  Vector3(-front.z, 0, front.x);
        right = -left;
        correctDirect = front;
    }

    /// <summary>
    /// 控制角色移动
    /// </summary>
    private void PlayerControl()
    {
        playerDirect = new Vector3(0, 0, 0);

        CalculateDirection();    //计算角色的方向

        if (Input.GetAxis("Horizontal") < 0)  //左
        {
            playerDirect = left;
        }
        if (Input.GetAxis("Horizontal") > 0)  //右
        {
            playerDirect = right;
        }
        if (Input.GetAxis("Vertical") > 0)  
        {
            if (Input.GetAxis("Horizontal") < 0)  //前左
            {
                playerDirect = front + left;
            }
            else if (Input.GetAxis("Horizontal") > 0) //前右
            {
                playerDirect = front + right;
            }
            else
            {
                playerDirect = front;     //前
            }
        }
        if (Input.GetAxis("Vertical") < 0)
        {
            if (Input.GetAxis("Horizontal") < 0)    //后左
            {
                playerDirect = back + left;
            }
            else if (Input.GetAxis("Horizontal") > 0)   //后右
            {
                playerDirect = back + right;
            }
            else
            {
                playerDirect = back;     //后
            }
        }
        if (playerDirect != Vector3.zero)
        {          
            playerDirect += transform.position;
            MoveSpeed(playerDirect);            
        }      
    }


    /// <summary>
    /// 调整角色方向,控制角色移动
    /// </summary>
    private void MoveSpeed(Vector3 direct)
    {
        transform.LookAt(new Vector3(direct.x, transform.position.y, direct.z));
        cc.Move(transform.forward * speed);
    }

}


2,CameraThirdControl.cs

using UnityEngine;
using System.Collections;

public class CameraThirdControl: MonoBehaviour
{
    [Range(0, 1)]
    [SerializeField]
    float target_offsety = 0.6f;    //高度差

    [Range(0, 90)]
    [SerializeField]
    float initRotate = 15f;     //摄像机角度

    [Range(2, 10)]
    [SerializeField]
    float DISTANCE_DEAFULT = 3.2f;  //设置摄像机与物体之间的距离

    Transform target;   //摄像机跟随的角色

    private float distance;
   

    private Vector3 playerTarget;

    private float lastRotate;

    // Use this for initialization
    void Start()
    {
        distance = DISTANCE_DEAFULT;    //设置摄像机与角色的距离
        target = GameObject.FindGameObjectWithTag("Player").transform;    //找到角色
        playerTarget = new Vector3(target.position.x, target.position.y + target_offsety, target.position.z);   //设置摄像机对着角色的位置
        Quaternion cr = Quaternion.Euler(initRotate, transform.eulerAngles.y, 0);   //设置摄像机与角色之间的角度
        //计算摄像机的位置
        Vector3 positon = playerTarget;
        positon += cr * Vector3.back * distance;
        transform.position = positon;
        transform.rotation = target.rotation;
        transform.LookAt(playerTarget);
    }
    // Update is called once per frame
    void Update()
    {
        //鼠标右键控制镜头转动
        if (Input.GetMouseButton(1))
        {
            transform.RotateAround(playerTarget, Vector3.up, Input.GetAxis("Mouse X")*3f);
        }
    }
    //更新摄像机的位置角度等信息
    void LateUpdate()
    {
        playerTarget = new Vector3(target.position.x, target.position.y + target_offsety, target.position.z);
        Quaternion cr = Quaternion.Euler(initRotate, transform.eulerAngles.y, 0);
        Vector3 positon = playerTarget + (cr * Vector3.back * distance);
        RaycastHit[] hits = Physics.RaycastAll(new Ray(playerTarget, (positon - playerTarget).normalized));
        distance = DISTANCE_DEAFULT;
        if (hits.Length > 0)
        {
            RaycastHit stand = new RaycastHit();
            float maxDistance = float.MaxValue;
            foreach (RaycastHit hit in hits)
            {
                if (!hit.collider.isTrigger && hit.collider.name != target.name && hit.distance < maxDistance)
                {
                    stand = hit;
                    maxDistance = stand.distance;
                }
            }
            if (stand.collider != null)
            {
                string tag = stand.collider.gameObject.tag;
                distance = Vector3.Distance(stand.point, playerTarget);
                if (distance > DISTANCE_DEAFULT)
                {
                    distance = DISTANCE_DEAFULT;
                }
            }
        }
        positon = playerTarget + (cr * Vector3.back * distance);
        transform.position = Vector3.Lerp(transform.position, positon, 0.5f);   //用于摄像机的缓冲,与误差存在关系

        Debug.DrawRay(playerTarget, positon - playerTarget, Color.red);   

        if (lastRotate != initRotate)
        {
            transform.LookAt(playerTarget);
            lastRotate = initRotate;
        }

        //鼠标中键控制镜头远近
        float fov = this.GetComponent<Camera>().fieldOfView;
        fov -= Input.GetAxis("Mouse ScrollWheel") * 10;
        this.GetComponent<Camera>().fieldOfView = Mathf.Clamp(fov, 30, 50);
    }

}


总结:以前写的最近整理了下,希望对你有帮助!   2018\4\16

阅读更多
个人分类: Unity
上一篇WPF窗口属性设置(无边框,任务栏隐藏图标,任务管理器应用程序隐藏图标)
下一篇C# XML读取和保存(使用序列化和反序列化,可以直接将对象存储和读取对象)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭