当前位置:   article > 正文

Unity第三人称角色控制器_unity第三人称控制器

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);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

摄像机控制部分

    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;
                }
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

移动端版本

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

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

角色控制代码

    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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

相机控制部分代码

    // 限制摄像机角度范围
    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;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

摇杆控制器脚本

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();
        };
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/873892
推荐阅读
相关标签
  

闽ICP备14008679号