显示碰撞不一致的gif:http://imgur.com/QB4XOv0.gif
在我的Unity2D游戏中,我有一个弹弓(玩家)在墙上射击弹珠(想想Puzzle Bobble类型拼图射击游戏)。每个弹珠都是预制件的克隆,每个预制件都有刚体, IsKinematic 和 CircleCollider 选中 OnTrigger 。
当大理石与两个侧壁碰撞时,我使用 OnTriggerEnter2D()并旋转角度,使其以一定角度从墙壁反弹。当大理石与顶壁碰撞时,它基本上会冻结,此时我会移除刚体组件并设置“topObjects”标记。
当大理石与另一块大理石碰撞时会出现不一致。有时会调用触发器函数,有时则不会调用。触发器似乎是随机的,不可预测的。
这是我的C#代码,用于检测碰撞及其附带的行为(附在大理石上):
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class RockMove : MonoBehaviour
{
public float speed = 0.5f;
private Vector2 direction = new Vector2(0, 1);
// current angle
private float currentAngleZ;
// indendiary angle
private float angleB;
// rotation speed
private float rot;
// curving speed
private float rotMod;
// stops marble when collides with wall
private bool IsMoving = true;
void Start() {
}
void Update ()
{
if (IsMoving) {
rot = RockSpawn.rot;
currentAngleZ = transform.eulerAngles.z;
rotMod = transform.position.x * -0.5f;
// moves it forward + adds speed
transform.Translate(direction * Time.deltaTime * speed, Space.Self);
// curving
transform.Rotate (0, 0, rotMod, Space.Self);
if (transform.position.x >= 0) {
// faster speed when near walls "gravity/magnetism"
speed += transform.position.x * 8 * Time.deltaTime;
}
if (transform.position.x < 0) {
// faster speed when near walls "gravity/magnetism"
speed += transform.position.x * -8 * Time.deltaTime;
}
}
else {
// when object is stationary
speed = 0;
}
}
void OnTriggerEnter2D(Collider2D collider){
// if collides with another marble
if (collider.gameObject.tag == "topObjects" ) {
// get rid of rigidbody
// can't have 2 rigidbodies when 2 objects collide
Destroy(rigidbody2D);
// freeze movement
IsMoving = false;
Debug.Log ("you collided with a marble");
// freeze rotation
this.transform.Rotate (0, 0, 0, Space.Self);
// assign the new tag
this.tag = "topObjects";
}
else if(collider.name == "TopWall")
{
Destroy(rigidbody2D);
IsMoving = false;
Debug.Log ("you broke the fourth wall!");
transform.Rotate (0, 0, 0);
this.tag = "topObjects";
}
else {
// bounce off walls
currentAngleZ = transform.eulerAngles.z;
angleB = 360 - (2 * currentAngleZ);
transform.Rotate (0, 0, angleB);
}
}
}
更新:简单地将Update()函数更改为FixedUpdate()似乎使触发器更加一致,但是它们的检测方式仍然存在不一致。
我测试了rigidbody2d.velocity,transform.position和各种其他变换函数,但是Transform.Translate通过将它从墙上弹回来产生了最好的结果,即使它理论上只是将对象传送到新位置。
降低速度也不会影响一致性,也不会改变圆形碰撞器的大小。
答案 0 :(得分:0)
无论您是否使用物理,OnTriggerEnter2D都应该始终如一。
但是,如果一个游戏对象与另一个游戏对象保持联系,那么你只会在它们碰撞的第一个瞬间标记一次OnTriggerEnter。之后,您可以通过调用OnTriggerStay来了解两个游戏对象是否仍然发生冲突。
然后在它们停止碰撞后,OnTriggerEnter将重置并在与其他gameObject联系时再次触发,即使它与之前碰撞的一样。你看过这个吗?
希望它有所帮助,我会发表评论,但我没有足够的声望点,所以如果我不应该被迫发帖回答对不起。
答案 1 :(得分:0)
这里有两个显而易见的事情:
1。)你的游戏对象有一个Rigidbody2D,所以你不应该通过变换移动它,而是通过具有以下功能的刚体:
rigidbody2D.MovePosition()
和
rigidbody2D.MoveRotation()
只需在Unity文档中查找它们。
2.)将所有这些放入
void FixedUpdate()
{
...
}
这是有关物理引擎的所有内容。 还有大量的在线资源可供阅读:)
答案 2 :(得分:-2)
我的理解是,运动刚体不能在2D中碰撞。我还很新,但我已经用自己的问题在几个答案中找到了这个。你应该多研究一下。