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