【unity】用代码实现“碰到障碍后 运动对象的运动方向如何改变(反弹/滑行)”

【unity】用代码实现“碰到障碍后 运动对象的运动方向如何改变(反弹/滑行)”向右下方 移动的对象 碰到右侧的墙壁 后 继续沿着着墙壁向下方移动 unity2d 计算与障碍物平行方向

大家好,欢迎来到IT知识分享网。

想要实现的效果:

例1:飞出的弹丸,碰到墙壁后,反弹。【↘️| 】——>【↙️| 】

例2:向右下方【↘️】移动的对象,碰到右侧的墙壁 【↘️| 】 后,继续沿着着墙壁向下方移动【↓ | 】

【unity】用代码实现“碰到障碍后 运动对象的运动方向如何改变(反弹/滑行)” 

为什么要用代码实现?

确实,一般来说使用刚体和碰撞器(Dynamic模式)的话Unity会负责物理碰撞的部分。 

但我的实现是用Kinematic X Static。敌人使用Kinematic 是因为需要控制他们各自不同的运动方式,所以碰到障碍物要绕行/滑行/反弹的话需要自己手动实现。

一、计算反射向量

无论要实现哪个效果都需要一个很重要的函数:根据入射向量,计算反射向量。(见下图)

【unity】用代码实现“碰到障碍后 运动对象的运动方向如何改变(反弹/滑行)”
原本的运动方向是inDirection,再提供一个碰撞法线inNormal,就可以得到反射向量啦。

 

用法很简单:

Vector3 reflectDir = Vector3.Reflect(OrgDir, normal);//OrgDir是原本的运动方向向量,normal是碰撞表面的法线 

那么,碰撞表面的法线inNormal要怎样得到?

我只记录我有在使用的两种方式,应该可以满足大部分需求。

1.有发生实际碰撞:

在脚本中使用碰撞检测,可以得到碰撞点信息:

protected ContactPoint2D contactPoint;//用这个变量保存碰撞点信息 protected void OnCollisionEnter2D(Collision2D collision) { contactPoint = collision.GetContact(0); //这个函数用来获取发生碰撞的点。因为它可能会是一个点的集合,我只需要一个就可以了,所以取第一个。 }

contackPoint.normal 就是法线。

reflectDir = Vector2.Reflect(orgDir, contactPoint.normal);

 2.未发生实际碰撞

有一些情况需要在发生实际碰撞之前,先去检测会不会发生碰撞(未雨绸缪)。

比如对象看到运动方向前面有障碍物,它会提前绕行,而不是撞到以后再改变运动方向。

这种情况可以使用Cast函数,unity提供了多种Cast函数。比如:

  • Collider2D.Cast (将碰撞体形状投射到从该碰撞体位置开始的场景中,忽略该碰撞体本身)
  • Rigidbody2D.Cast (附加到 Rigidbody2D 的所有 Collider2D 形状都将投射到场景中 – 忽略附加到同一个 Rigidbody2D 的碰撞体。)
  • Physics2D.RaycastAll (射线投射)

关于射线的更多内容可以参考这个⬇️,不再这篇多做赘述。【unity】用代码实现“碰到障碍后 运动对象的运动方向如何改变(反弹/滑行)”这里我使用了 Rigidbody2D.Cast 函数。

 //用一个数组保存投射的结果,这里我设定数组长度为10个 RaycastHit2D[] hits = new RaycastHit2D[10]; //检测对象运动方向上有没有障碍物,检测距离为dist,n表示检测到的碰撞数量 //contactFilter_obstacle 是提前设定好的过滤条件,如何设置要根据需求而定 public bool HasObstacle(Vector2 orgDir, float dist) { int n = m_rigidbody.Cast(orgDir, contactFilter_obstacle, hits, dist); return n != 0; } 

Cast函数将碰撞结果保存在 hits 数组中,hits[0].normal 就是我们需要的法线。

二、对象碰撞后的运动方向

有了反射向量就很简单了。

要实现例1反弹效果的话,直接使用反射向量即可。

要实现例2贴墙继续走的话,用 OrgDir + ReflectDir 即可。注意实现时,要保持同之前运动相同的速度,就需要一些细节了,比如这样:

//入射与反射向量相加后,把向量归一化。再乘以原本要移动的距离。避免对象的运动速度骤减或突然翻倍 return (orgDir + reflectDir).normalized * moveLength;

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/150207.html

(0)
上一篇 2025-03-20 12:26
下一篇 2025-03-20 12:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信