Unity简单的移动实现(总集篇)

Unity简单的移动实现终于基本完工了,现在的角色已经可以自由的移动,跑步,下蹲和跳跃了,视角的旋转也没问题了,就差最后一步上楼梯的问题了,这一点我们会在总集篇内解决。

回顾

Unity简单的移动实现(四)
Unity简单的移动实现(三)
Unity简单的移动实现(二)
Unity简单的移动实现(一)

上楼梯

思路就是通过碰撞检测去爬,碰到比自己高的就可以爬上去了

 float PlayerMinPoint = transform.position.y - (PlayerCollider.height * transform.localScale.y) * 0.5f;//角色最低点
        float CollisionMaxPoint = collision.transform.position.y + collision.transform.localScale.y * 0.5f;//物体最高点
        float DifferenceValue = CollisionMaxPoint - Mathf.Abs(PlayerMinPoint);//计算高度差
      
        if (!collision.transform.GetComponent<Rigidbody>() &&  DifferenceValue >= 0 && DifferenceValue <= StairHeight)
        {
        	//设置新的高度
            transform.position = new Vector3(transform.position.x, (PlayerCollider.height * transform.localScale.y * 0.5f) + CollisionMaxPoint, transform.position.z);
            rig.velocity = T_MoveSpeed;//还原速度
        }

为什么要判断碰撞物体是否有刚体,是因为一般来说建筑物是不会加刚体的,只有小物件会加刚体用来互动,所以第一步就是要排除我们会踩到小物品上,如果有人需要踩到小物体上可以换一个判断思路。

总集

经过了四集半的书写,我们简单的人物移动终于完成了,它可以正常的移动,加速,跳跃,下蹲和上楼梯,基本的移动功能就完成了,如果你有更好的方法去实现这些功能,欢迎在评论区交流,当然,这一套代码可以适应不太复杂的场景,如果有需要我会考虑做一个普通的移动实现或者复杂的移动实现,当然比这个要复杂的多,考虑的东西也多,特性(BUG)也会更多。

代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : AActor
{
    Rigidbody rig;//角色刚体
    CapsuleCollider PlayerCollider;//角色碰撞盒
    private void Awake()
    {
        //GetKey();//设置角色键位 可以忽略
    }
  
    private void Start()
    {
        rig = GetComponent<Rigidbody>();//获取组件
        PlayerCollider = GetComponent<CapsuleCollider>();//获取角色碰撞盒
    }
    private void Update()
    {
        RayHit();//射线检测
        RotActor();//旋转
    }
    private void FixedUpdate()
    {
        rig.velocity = ActorMove();//赋予速度      
    }

    private void OnCollisionEnter(Collision collision)
    {
        //判断落地
        if (collision.transform.tag == "Plane")
        {
            IsJump = false;
        }

        //上楼梯
        float PlayerMinPoint = transform.position.y - 
        (PlayerCollider.height * transform.localScale.y) * 0.5f;//角色最低点
        float CollisionMaxPoint = collision.transform.position.y +
        collision.transform.localScale.y * 0.5f;//物体最高点
        float DifferenceValue = CollisionMaxPoint - Mathf.Abs(PlayerMinPoint);//计算高度差
      
        if (!collision.transform.GetComponent<Rigidbody>() && 
         DifferenceValue >= 0 && 
         DifferenceValue <= StairHeight)
        {
            transform.position = new Vector3
            (transform.position.x, 
            (PlayerCollider.height * transform.localScale.y * 0.5f) + CollisionMaxPoint,
             transform.position.z);
            rig.velocity = T_MoveSpeed;
        }
        
    }


    /*----------------------分界线-------------------------*/
    //移动和旋转视角
    public float MoveSpeed; //移动速度
    [Range(1,2)]
    public float RunCoefficient; //跑动系数
    [Range(0,1)]
    public float SquadCoefficient; //蹲跑系数
    [Range(0,1)]
    public float Friction = 0.2f;//摩擦系数
    float MoveCoefficient = 1.0f; //移动系数
    Vector3 Direction; //移动方向
    Vector3 C_MoveSpped; //钳制后的速度
    Vector3 V_MoveSpeed; //物理移动速度
    Vector3 T_MoveSpeed; //二次计算后的速度

    bool IsJump = false;//是否跳跃
    public float JumpHeighMultiple = 5;//跳跃高度倍数

    bool IsSquad = false;//是否下蹲

    public GameObject Head;//头部(摄像机)
    public float HeadRotionSpeed;//头部旋转速度
    public float BodyRotionSpeed;//身体旋转速度
    public float MaxAngle;//最大角度
    public float MinAngle;//最小角度
    float Angle;//当前头部角度

    public float SquadHeight;//角色下蹲高度
    public float StairHeight;//可以上的楼梯高度
   
    //移动
    public override Vector3 ActorMove()
    {
        //获取方向
        if (Input.GetKey(Keys["ForWord"]) && Input.GetKey(Keys["Left"]))
        {
            Direction = transform.forward - transform.right;
        }
        else if (Input.GetKey(Keys["ForWord"]) && Input.GetKey(Keys["Right"]))
        {
            Direction = transform.forward + transform.right;
        }
        else if (Input.GetKey(Keys["BackOff"]) && Input.GetKey(Keys["Left"]))
        {
            Direction = -transform.forward - transform.right;
        }
        else if (Input.GetKey(Keys["BackOff"]) && Input.GetKey(Keys["Right"]))
        {
            Direction = -transform.forward + transform.right;
        }
        else if (Input.GetKey(Keys["ForWord"]))
        {
            Direction = transform.forward;
        }
        else if (Input.GetKey(Keys["BackOff"]))
        {
            Direction = -transform.forward;
        }
        else if (Input.GetKey(Keys["Left"]))
        {
            Direction = -transform.right;
        }
        else if (Input.GetKey(Keys["Right"]))
        {
            Direction = transform.right;
        }     
        else
        {
            Direction = Vector3.zero;
        }

        //跳跑蹲
        if (Input.GetKeyDown(Keys["Jump"]) && !IsJump)
        {
            Jump();  
        }

        if (Input.GetKey(Keys["Run"]) && !IsJump)
        {
            Run();
        }       
        else if (Input.GetKey(Keys["Squad"]))
        {
            Squad();
        }
        //检测头部是否有物体
        else if (hit.transform == null || hit.transform.GetComponent<Rigidbody>())
        {
            Recovery();
        }
       
        //计算速度
        V_MoveSpeed = rig.velocity + (Direction * MoveSpeed * Time.deltaTime);
        //速度衰减
        V_MoveSpeed = new Vector3
        (Mathf.Lerp(V_MoveSpeed.x,0,Friction),
        V_MoveSpeed.y,
        Mathf.Lerp(V_MoveSpeed.z,0,Friction));
        //钳制速度
        C_MoveSpped = new Vector3
        (Mathf.Clamp(V_MoveSpeed.x, -10, 10),
         rig.velocity.y,
         Mathf.Clamp(V_MoveSpeed.z, -10, 10));
        //二次计算
        T_MoveSpeed = new Vector3
        (C_MoveSpped.x * MoveCoefficient,
         C_MoveSpped.y,
         C_MoveSpped.z * MoveCoefficient);
        //返回速度
        return T_MoveSpeed;
    }

    //旋转
    public void RotActor()
    {
        //身体旋转 
        transform.eulerAngles += new Vector3
        (0,
         Input.GetAxis("Mouse X") * Time.deltaTime * BodyRotionSpeed,
         0);
        //头部旋转
        Angle += -Input.GetAxis("Mouse Y") * Time.deltaTime * HeadRotionSpeed;
        Head.transform.eulerAngles = new Vector3
        (Mathf.Clamp(Angle, MinAngle, MaxAngle),
         transform.eulerAngles.y,
         transform.eulerAngles.z);
    }
   
    //跑
    public override void Run()
    {
        MoveCoefficient = RunCoefficient;
    }
    
    //跳
    public override void Jump()
    {
        rig.AddForce(transform.up * JumpHeighMultiple,ForceMode.VelocityChange);
        IsJump = true;
    }
    
    //蹲
    public override void Squad()
    {
        MoveCoefficient = SquadCoefficient;//改变速度
        PlayerCollider.height = Height;//设置碰撞大小
    }
    
    //恢复
    public void Recovery()
    {
        MoveCoefficient = 1.0f;
        PlayerCollider.height = 0.18f;
    }
	
	//射线检测
    Ray ray;
    RaycastHit hit;

    void RayHit()
    {
        ray = new Ray(Head.transform.position, transform.up);
        Physics.Raycast(ray, out hit);
    }

代码就是这么多,一些简单的问题我就直接在这里说明
1.代码挂载:直接挂载给角色对象主体就行了,参数自己调整。
2.继承:我继承的是自己创建的抽象类,可以直接继承MonoBehaviour。
3.控制:我要和键位设置挂钩,所以都是自己的参数,可以直接用KeyCode去实现。
4.落地:这一部分并不完美,可以再去修改条件,让落地更方便。
5.碰撞盒:随意,我这里的是CapsuleCollider,想换其他碰撞盒的话,记住把代码部分换掉。
6.别忘了给物体和人物添加物理材质,防止它们碰到一起不动了。

结尾

Unity简单的移动实现就告一段落,如果有问题可以在评论区留言,这个移动实现可以应用在比较简单的场景中使用,复杂的场景可能会吃不消,移动基本就这些了,等我想到要分享什么的时候就是下一篇出现的时候,我们下一篇见。

你可能感兴趣的:(Unity经验分享)