温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

使用Unity怎么实现地面检测

发布时间:2021-05-31 16:11:25 来源:亿速云 阅读:1353 作者:Leah 栏目:开发技术

这篇文章将为大家详细讲解有关使用Unity怎么实现地面检测,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

1.普通射线

在角色坐标(一般是脚底),发射一根向下的射线(长度约0.2)

但是简单射线只适用于简单地形,实际使用中常常遇到以下问题

1.用collider去碰撞地面,某些时候会有一定的穿插,于是角色的最低点就可能穿透地面,你发射射线的点可能就到了地面以下,射线一直检测不到真正的地面,于是角色就一直悬空

2.角色走斜坡时,角色中点可能会离开地面一小段距离,这一小段距离往往就足够让判断机制误以为角色已经离地,如果你增加射线的长度,那么一定程度上能缓解斜坡问题,但是会降低跳跃判断的精度,精度过低就有可能出现:角色跳起,会有那么一小段距离,其实已经离地了,但是仍然返回了isGround = true;

using System.Collections; using System.Collections.Generic; using UnityEngine;   public class RaycastTest : MonoBehaviour {     private bool isGround = false;     private Rigidbody2D myRigidbody2D;     void Awake () {         myAnimator = GetComponent<Animator>();         myRigidbody2D = GetComponent<Rigidbody2D>();     }	void FixedUpdate () {         Debug.DrawRay(transform.position, Vector2.down * 0.11f, Color.red);         RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 0.15f, 1 << 8);         if (hit.collider != null)             isGround = true;         else             isGround = false; }

2.Unity官方的Character Controller

直接给角色加入Character Controller组件,在脚本中Get到Character Controller,调用.isGrounded即可,但是实际效果让人失望

因为.isGrounded是当角色移动的时候才会检测是否着地的,也就是说它只能在调用simplemove(和move等移动函数)时,判断isGrounded(是否着地)

这时播放一些动画会导致判断在true和false状态来回切换,并且Skinwidth也会导致这种问题,再加上一些角色控制器的限制,逻辑上不是那么自由,例如需要自己实现物理模拟,比如重力,个人觉得非常麻烦,不推荐

using System.Collections; using System.Collections.Generic; using UnityEngine; public class OnGroundSensor : MonoBehaviour {     public CapsuleCollider capcol;     public float offset = 0.1f;     private Vector3 point1;     private Vector3 point2;     private float radius;     void Awake()     {         radius = capcol.radius - 0.05f;     }     void FixedUpdate()     {         point1 = transform.position + transform.up * (radius - offset);         point2 = transform.position + transform.up * (capcol.height - offset) - transform.up * radius;         Collider[] outputCols = Physics.OverlapCapsule(point1, point2, radius, LayerMask.GetMask("Ground"));         if (outputCols.Length != 0)         {             //foreach (var col in outputCols)             //    print("collision:" + col.name);             SendMessageUpwards("IsGround");         }         else             SendMessageUpwards("IsNotGround");     } }

3.三射线

这个方法是社团内的Aery同志传授的,他应用到了一个2d卷轴游戏上https://github.com/KillerAery/DarkAdventrue

写法和简单射线没有什么不同,区别在于给角色加上三条射线:左脚,右脚,裆
三条射线有一条返回true则isGround为true

在我们的这个2d游戏上表现不错

我们看看他的代码

float dt = Time.deltaTime; //累计时间 vida.chargeTimer += dt; vida.jumpTimer += dt; //TODO 待优化代码 //是否到地面 用三个groundCheck来检测  //public Transform[] groundChecks = new Transform[3]; for (int i = 0; i < 3; ++i) {     checkResult = Physics2D.Linecast(transform.position,                      groundChecks[i].position,                      1 << LayerMask.NameToLayer("Ground"));     vida.grounded = checkResult;     if (vida.grounded) break; } if (vida.grounded) {     //火箭蛋(硬件蛋特殊技能)     if (vida.playerType == Tags.YingjianDan)     {         vida.jumpable = 1;     } } //跳跃 //按下K时 if (Input.GetKeyDown(KeyCode.K) && vida.jumpTimer >= 0.03f) {     if (vida.grounded)     {         //允许跳跃         vida.jumpTimer = 0.0f;         vida.jump = true;     }     else if (vida.jumpable > 0)     {         vida.jumpable--;         //允许跳跃         vida.jumpTimer = 0.0f;         vida.jump = true;     } }

4.OverlapCapsule 投射胶囊碰撞体

这个方法是看傅老师的黑魂复刻系列视频学的

使用Unity怎么实现地面检测

使用Unity怎么实现地面检测

point0,point1,radius 分别为胶囊体起点球心,胶囊体终点球心,胶囊体半径

我们这里只要用到这一重载方法 Physics.OverlapCapsule(pointBottom, pointTop, radius, LayerMask)

private CapsuleCollider capsuleCollider; private Vector3 pointBottom, pointTop; private float radius;  void Awake () {     capsuleCollider = GetComponent<CapsuleCollider>();     radius = capsuleCollider.radius; }

5.LayerMask设置方法

最后提下这个LayerMask

假设ground层为10,指定碰撞第10层Layer,写法为:Layermask mask=1<<10

但是,投射的胶囊体也会检测自己本身,如果你希望游戏中基本上任何能碰撞物体都能够用来站脚,那么应设置为:碰撞除了角色所在的Layer以外的所有层(假设Player层为8

写法为:~(1<<8)

bool OnGround() {         pointBottom = transform.position + transform.up * radius-transform.up*overLapCapsuleOffset;         pointTop = transform.position + transform.up * capsuleCollider.height - transform.up * radius;         LayerMask ignoreMask = ~(1 << 8);           colliders = Physics.OverlapCapsule(pointBottom, pointTop, radius, ignoreMask);         Debug.DrawLine(pointBottom, pointTop,Color.green);         if (colliders.Length!=0)         {             isOnGround = true;             return true;         }         else         {              isOnGround = false;             return false;         } }

关于使用Unity怎么实现地面检测就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI