只实现物理反弹的效果,不实现蹦床会有的视觉拉伸效果,请自行找相关代码
经过我的实践,我发现要想实现一个平台反弹的效果,要么就选择给player添加一个物理材质(平台加了没用),
但是这样会造成一个问题,如果我们要弄一个3d控制器的游戏,那么没理由让玩家什么情况下都要弹起来吧。
因此参考这篇优质文章https://blog.csdn.net/LLLLL__/article/details/117266549
我们可以给玩家移动代码中添加如下的代码 :
注意:
contacts[0]
,因为它会产生内存垃圾。改用 GetContact
或 GetContacts
,即other.GetContact(0).normal
private Vector3 lastDir;
private void LateUpdate()
{
lastDir = rb.velocity;
}
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag == "Wall")
{
Vector3 reflexAngle = Vector3.Reflect(lastDir, other.contacts[0].normal);
rb.velocity = reflexAngle.normalized * lastDir.magnitude;
}
}
下面的选择则是挂载到我们的平台上。
注意:
playerRigidbody
是在OnCollisionEnter
方法中声明的,因此它的作用范围仅限于OnCollisionEnter
方法,这会导致编译错误。
要解决这个问题,可以将playerRigidbody
声明为类级别的字段,以便在整个类中都能访问它。
同时,还需要在OnCollisionEnter
方法中获取到playerRigidbody
。
using UnityEngine;
public class Bounch_Platform : MonoBehaviour
{
private Vector3 lastDir;
private Rigidbody playerRigidbody; // 声明为类级别字段
private void OnCollisionEnter(Collision other)
{
// 检测是否碰到了玩家(假设玩家有一个标签为 "Player")
if (other.gameObject.CompareTag("Player"))
{
playerRigidbody = other.gameObject.GetComponent<Rigidbody>(); // 获取玩家的刚体
if (playerRigidbody != null)
{
Vector3 reflexAngle = Vector3.Reflect(lastDir, other.GetContact(0).normal);
// 应用反射角度来实现弹跳
playerRigidbody.velocity = reflexAngle.normalized * lastDir.magnitude;
}
}
}
private void LateUpdate()
{
if (playerRigidbody != null)
{
lastDir = playerRigidbody.velocity;
}
}
}
Collider
和碰撞Collision
不是同一个东西,有些人可能会考虑使用触发事件(假设已经点了is trigger
),去完成这个反弹效果。Tip:
我们实现物理移动,rigidbody组件是一定要选择跟我们的脚本挂载到同一个游戏对象,碰撞体在什么位置反而无所谓,只是不要想着可以通过GetComponentInChildren
或GetComponentInParent
取巧解决上面的结构问题,这样会造成不必要的工作量。
游戏是由事件驱动的,比如OnCollisionEnter
和OnTriggerEnter
,对涉及到碰撞的事件可以通过以下两种方法实现:
老手的操作并不代表这一定好,只是这样更适合更加小型的项目,更方便我们聚合tag
在一起,而如果我们选择把一个物体当成一个模块,意味着可以复用这些类型的预制体。
一旦使用老手的操作,如果遇到需要改动或者弃用某些对象,可能会影响到相关的事件的判断,而且unity
也对tags改名操作和弃用操作也不智能,选择新手的方式无疑更好。