Unity第三人称角色控制器

知识点记录(希望是以后要用到了是可以直接拿来复制粘贴)

第三人称角色控制器

PC端版本

标准功能:按下WASD移动,空格键跳跃,Shift加速,鼠标右键控制摄像机旋转视角

角色移动部分代码

    public float walkSpeed = 5;//移动
    public float runSpeed = 10;//奔跑
    public float turnSmoothTime = 0.13f;//角色转向平滑时间
    float turnSmoothVelocity;
    public Camera cameraT;
    private Rigidbody rb;
    public Animator ani;//动画控制器,没有的可以不加,在下面脚本里删掉就行
    
    private void Awake()
    {
    
    
        rb = transform.GetComponent<Rigidbody>();
        cameraT = Camera.main;
    }
    void FixedUpdate()
    {
    
    
        PlayerMoveThirdPerson();
    }
    //主要脚本
    public void PlayerMoveThirdPerson()
    {
    
    
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");
        Vector3 m_CamForward = Vector3.Scale(cameraT.transform.forward, new Vector3(1, 0, 1)).normalized;
        Vector3 m_Move = v * m_CamForward + h * cameraT.transform.right;
        if (m_Move.magnitude > 1f)
            m_Move = m_Move.normalized;
        Vector2 m_Input = new Vector2(h, v).normalized;//获取输入
        float targetSpeed = Input.GetKey(KeyCode.LeftShift) ? runSpeed : walkSpeed;//加速或匀速
        transform.Translate(m_Move * targetSpeed * Time.deltaTime, Space.World);
        //rb.MovePosition(rb.position+m_Move * targetSpeed * Time.deltaTime);//另一种移动方式

        if (m_Input != Vector2.zero)
        {
    
    
            ani.SetInteger("AnimationPar", 1);//动画部分,可删减
            float targetRotation = Mathf.Atan2(h, v) * Mathf.Rad2Deg + cameraT.transform.eulerAngles.y;
            transform.eulerAngles = Vector3.up * Mathf.SmoothDampAngle(transform.eulerAngles.y, targetRotation, ref turnSmoothVelocity, turnSmoothTime);
        }
        else
        {
    
    
            ani.SetInteger("AnimationPar", 0);
        }
        if (Input.GetKey(KeyCode.Space))
        {
    
    
            if (ani.GetInteger("AnimationPar") == 1)
            {
    
    
                ani.SetBool("FreeFall", true);
                ani.SetBool("Grounded", true);
                ani.SetBool("JumpRun", true);
            }
            else
            {
    
    
                ani.SetBool("JumpRun", false);
                ani.SetBool("IsJump", true);
                ani.SetBool("Grounded", true);
            }
        }
        else
        {
    
    
            ani.SetBool("IsJump", false);
            ani.SetBool("FreeFall", false);
        }
        transform.GetComponent<Rigidbody>().velocity = Vector3.zero;
        Physics.gravity = new Vector3(0, -45, 0);
    }

摄像机控制部分

    public Transform target;//角色
    public Vector3 targetOffset;
    public float distance = 5.0f;
    public float maxDistance = 20;//缩放
    public float minDistance = .6f;//缩放
    public float xSpeed = 200.0f;//速度
    public float ySpeed = 200.0f;
    public int yMinLimit = -80;//限定角度
    public int yMaxLimit = 80;
    public int zoomRate = 40;
    public float zoomDampening = 5.0f;
    public float xDeg = 0.0f;//自身的角度记录
    public float yDeg = 0.0f;//自身的角度
    public float currentDistance;//缩放记录
    public float desiredDistance;//缩放
    private Quaternion currentRotation;
    private Quaternion desiredRotation;
    public Quaternion rotation;
    private Vector3 position;

    public float X;//初始化角度X轴
    public float Y;//初始化角度Y轴

    public bool isCameraChange = false;
    private bool Rot = false;
    void LateUpdate()
    {
    
    
        if (Input.GetMouseButton(1))
        {
    
    
            xDeg += (Input.GetAxis("Mouse X") * xSpeed * 0.01f);
            yDeg -= (Input.GetAxis("Mouse Y") * ySpeed * 0.01f);
        }
        yDeg = ClampAngle(yDeg, yMinLimit, yMaxLimit);
        // 设置相机旋转
        desiredRotation = Quaternion.Euler(yDeg, xDeg, 0);
        currentRotation = transform.rotation;//记录初始角度
        rotation = Quaternion.Lerp(currentRotation, desiredRotation, Time.deltaTime * zoomDampening);
        transform.rotation = rotation;
        //这里多加了一个鼠标滚轮控制相机缩放的功能(其实是控制相机的距离)
        if (!isCameraChange)
        {
    
    
            desiredDistance -= Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * zoomRate * Mathf.Abs(desiredDistance);
            //变焦最小/最大
            desiredDistance = Mathf.Clamp(desiredDistance, minDistance, maxDistance);
            //平滑变焦
            currentDistance = Mathf.Lerp(currentDistance, desiredDistance, Time.deltaTime * zoomDampening);
        }
        position = new Vector3(target.position.x, 0, target.position.z) - (rotation * Vector3.forward * currentDistance + targetOffset);
        transform.position = position;
        //这个脚本是角色和摄像机之间有遮挡时改变相机位置,但是有时候会比较突兀,可删减
        ProcessMode2();
    }
    private static float ClampAngle(float angle, float min, float max)
    {
    
    
        if (angle < -360)
            angle += 360;
        if (angle > 360)
            angle -= 360;
        return Mathf.Clamp(angle, min, max);
    }
    public float distanceAway;//相机到角色距离
    public Vector3 DisOffset;
    /// <summary>
    /// 从摄像机到角色
    /// </summary>
    public void ProcessMode2()
    {
    
    
        RaycastHit hit;
        distanceAway = Vector3.Distance(transform.position, target.position);
        if (Physics.Linecast(target.position + Vector3.up, transform.position, out hit))
        {
    
    
            string name = hit.collider.gameObject.tag;
            if (name != "MainCamera")
            {
    
    
                //如果射线碰撞的不是相机,那么就取得射线碰撞点到玩家的距离
                float currentDistance = Vector3.Distance(hit.point, target.position);
                if (currentDistance < distanceAway)
                {
    
    
                    //Debug.Log("角色遮挡");
                    transform.position = hit.point + DisOffset;
                }
            }
        }
    }

移动端版本

(移动端这里是学习了林新发大佬的方法)

因为是移动端,所以这里使用了摇杆,左摇杆控制角色移动,右摇杆控制摄像机
关于摇杆制作的部分,大家可以看看这篇文章摇杆制作

角色控制代码

    public float speed = 1f;
    // 转向速度
    public float turnSpeed = 20f;
    public Animator anim;
    // 跟节点
    public Transform rootTrans;
    // 模型节点
    public Transform modelTrans;
    // 是否在移动
    private bool moving = false;
    // 移动向量
    private Vector3 moveDirection = Vector3.zero;
    // 是否可移动
    private bool canMove = true;
    
    void Update()
    {
    
    
        if (canMove && moving)
        {
    
    
            anim.SetInteger("AnimationPar", 1);
            rootTrans.position += moveDirection * speed * Time.deltaTime;
            modelTrans.forward = Vector3.Lerp(modelTrans.forward, moveDirection, turnSpeed * Time.deltaTime);
        }
        else
        {
    
    
            anim.SetInteger("AnimationPar", 0);
        }
    }
    public void Move(Vector3 direction)
    {
    
    
        moveDirection = direction;
        moving = true;
    }
    public void Stand()
    {
    
    
        moving = false;
    }

相机控制部分代码

    // 限制摄像机角度范围
    private const float Y_ANGLE_MIN = 10f;
    private const float Y_ANGLE_MAX = 50.0f;
    // 摄像机看向的物体
    public Transform lookAt;
    // 摄像机Transform
    public Transform camTransform;
    // 摄像机距离目标物体的距离
    public float distance = 1.2f;
    // 原始距离
    private float originalDistance;
    // 旋转速度
    public float rotateSpeed = 0.01f;
    private float currentX = 0.0f;
    private float currentY = 20.0f;
    private bool rotating;
    private Vector2 rotateDelta;
    private void Start()
    {
    
    
        camTransform = transform;
        originalDistance = distance;      
    }
   private void Update()
    {
    
    
        if (rotating)
        {
    
    
            currentX += rotateDelta.x;
            currentY += rotateDelta.y;
            currentY = Mathf.Clamp(currentY, Y_ANGLE_MIN, Y_ANGLE_MAX);
        }
    }
    public void RotateCam(Vector2 delta)
    {
    
    
        rotateDelta = delta * rotateSpeed;
        rotating = true;
    }
    public void StopRotate()
    {
    
    
        rotating = false;
    }
    private void LateUpdate()
    {
    
    
        Vector3 dir = new Vector3(0, 0, -distance);
        Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);
        camTransform.position = lookAt.position + rotation * dir;
        camTransform.LookAt(lookAt.position);
    }

    /// <summary>
    /// 修改distnace 镜头调整
    /// </summary>
    /// <param name="args"></param>
    private void OnEventChangeCamDistance(params object[] args)
    {
    
    
        var offset = (float)args[0];
        distance = originalDistance + offset * 20f;
    }

摇杆控制器脚本

public class GamCtrl : MonoBehaviour
{
    
    
    private static GamCtrl instance;
    public static GamCtrl Instance
    {
    
    
        get
        {
    
    
            if (instance==null)
            {
    
    
                instance = new GamCtrl();
            }
            return instance;
        }
    }
    public PlayerActionComp2 player;//角色控制脚本
    public CameraControl2 cameraCtrl;//摄像机控制脚本
    public Rocker rocker;左摇杆
    public Rocker world;右摇杆

    private void Start()
    {
    
        
       //拖动摇杆
        rocker.onDragPcak = (direction) =>
        {
    
    
            var realDirect = cameraCtrl.transform.localToWorldMatrix * new Vector3(direction.x, 0, direction.y);
            realDirect.y = 0;
            realDirect = realDirect.normalized;
            player.Move(realDirect);
        };
        //停止拖动
        rocker.onStopDrag = () => {
    
     player.Stand(); };
        world.onDragPcak = (direction) =>
        {
    
    
            cameraCtrl.RotateCam(direction);
        };
        world.onStopDrag = () =>
        {
    
    
            cameraCtrl.StopRotate();
        };
    }

猜你喜欢

转载自blog.csdn.net/m0_64375864/article/details/130565897