回想一下学unity也学了不少东西了,可是很多东西还是学了忘忘了学,于是可能还得当场百度一下才能回想的起来。为加强自己的熟练程度,继续来更新博客了。
左右移动
实现移动有三种方式:
- 直接改变位置
- 给物体添加速度
- 给物体添加力
1.直接改变位置的方法
transfor.Translate(Vector3);
如果双方都没有刚体组件,则会直接穿过。
如果玩家是刚体,则会出现如下情况:
这种方法会存在一点小问题,在3维空间中,当角色接近不可移动的物体时,如果继续按方向键,人物则会有穿模抖动现象,穿入到物体中。
2.给物体添加速度的方法 需要给物体挂接RigidBody组件,然后调用:
Rigidbody rigidbody;
rigidbody.velocity=new Vector3(0,0,0);
3.给物体添加力的方法
Rigidbody rigidbody;
rigidbody.AddForce(new Vector3(0,0,0));
(第三种方法会使得玩家具有惯性,如果想让玩家在空中有这种惯性但是在地面上的惯性很小可以给地板添加物理材质,将其的摩擦系数提高) 例如马里奥:
跳跃
普通的跳跃只需要给玩家添加向上的速度或者向上的力即可,然后加入一个玩家是否在地面的判断(目的是防止无限跳)。
判断是否在地面
三种方法
- 给地面设置tag然后调用碰撞enter和exit函数
- 对地面进行射线检测
- 在底部添加小物体然后使用球形检测
- 角色控制器自带的isGrounded方法
第一种方法:
private void OnCollisionEnter(Collision collision)
{
if (collision.collider.tag == "Ground")
{
isGround = true;
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.collider.tag == "Ground")
{
isGround = false;
}
}
这种方法隐患很大,不建议使用。例如当物体处于地面上并解除台阶的侧面然后离开时,此时会OnCollisionExit函数设置为离开地面的状态。
第二种方法 射线检测 射线检测的官方文档: 代码如下:
bool isGrounded = Physics.Raycast(transform.position, Vector3.down, playerHeight/2+0.1f);
球形检测法: 在物体底部创建一个物体:
public Transform groundcheck;
public LayerMask layerMask;
float checkRadius = 0.2f;
void Update()
{
bool isGround = Physics.CheckSphere(groundcheck.position, checkRadius, layerMask);
}
这个layermask是可以用来过滤一些层次,比如此处我们只需要地面环境具有这个检测的效果,可以将地面的layer设置一下:
蓄力跳跃
注意到例如马里奥的游戏中,短按跳的低,长按跳的高,实现的方法如下:
角色控制器的使用方法
角色控制器更注重实现人物的移动而不展现物理规律。rigidbody更注重展现物理规律。例如上坡,用角色控制器很好实现但是rigidbody很难。
使用例子如下:
float speed = 10f;
float rotateSpeed = 1f;
CharacterController cc;
void Start()
{
cc = GetComponent<CharacterController>();
}
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float veritcal = Input.GetAxis("Vertical");
var move = transform.forward * speed * veritcal * Time.deltaTime;
cc.Move(move);
transform.Rotate(Vector3.up, horizontal * rotateSpeed);
}
效果如下: 详细的transform.Rotate函数方法使用如下: https://docs.unity3d.com/cn/current/ScriptReference/Transform.Rotate.html
不使用刚体而模拟重力
但是要用角色控制器
private Vector3 velocity = Vector3.zero;
float gravity = -9.8f;
bool isGround = Physics.CheckSphere(groundcheck.position, checkRadius, layerMask);
if (isGround == true) Debug.Log("is in ground");
if (!isGround)
{
velocity.y += gravity * Time.deltaTime;
cc.Move(velocity * Time.deltaTime);
}
else
{
velocity.y = 0;
}
}
(transform的速度不需要刚体) 注意,如果此时一帧内有两个move函数其实互不冲突,它是一个“移动的矢量形式的结果”。
几个参数的定义:
slope limit可以上的斜坡的角度 step offset可以上的台阶的高度
Skin Width: 皮肤厚度。该参数决定了两个碰撞体可以相互渗入的深度,较大的参数值会产生抖动现象,较小的参数值会导致所控制的游戏对象被卡住,较为合理的设置是该参数值为Radius值的10%。 Character Controller的Skin Width是非常重要的属性,因此必须正确的设置。如果角色被卡住了,通常是由于Skin Width的厚度太小而导致的该值可以使其他的对象轻微的穿过Character Controller,并且可以避免抖动且防止角色卡住。
角色控制器里的碰撞效果
在这里插入代码片
Character Controller不会对施加给他的作用力做出反应,也不会作用于其他的刚体。如果想让Character Controller组建能够够作用于其他的刚体对象,可以通过脚本【OnControllerColliderHit()函数】在与其碰撞的对象上使用一个作用力。另外如果想让 Character Controller受物理效果影响,那最好用刚体来替代它。
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.transform.tag == "Collider")
{
hit.rigidbody.AddForce(transform.forward * speed);
}
}
Inspector组件中的debug界面
这里存在一个界面可以用来实时的查看一些值,例如刚体中的速度。
|