这篇文章主要介绍Unity中地面检测方案的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
在角色坐标(一般是脚底),发射一根向下的射线,长度大约为0.2,
只适用于简单地形,实际使用中常常遇到以下问题
用的collider去碰撞地面时,某些时候会有一定的穿插,于是角色的最低点就可能穿透地面,你发射射线的点可能就到了地面以下,射线一直检测不到真正的地面,于是角色就一直悬空。
角色是走斜坡的时候,角色中点可能会离开地面一小段距离,这一小段距离往往就足够让判断机制误以为角色已经离地了。如果你增加射线的长度,那么一定程度上能缓解斜坡问题,但是会降低跳跃判断的精度:角色每次跳起,会有一小段距离,其实已经离地了,但是仍然返回了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;}
直接给角色加入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");
}
}
写法和简单射线没有什么不同,区别在于给角色加上三条射线:左脚,右脚,裆,三条射线有一条返回true则isGround为true。
回到顶部
API: public static Collider[] OverlapCapsule(Vector3 point0, Vector3 point1, float radius, int layerMask = AllLayers,QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
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; }
假设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中地面检测方案的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。