问题:-
我的游戏中有一个交通系统,我想摧毁一辆被另一辆车撞到的汽车。但问题是,这两辆车的脚本都是相同的,名为TrafficCar。下面是脚本中的函数,它负责冲突。
void OnCollisionEnter (Collision col)
{
// I want to destroy car after 1 sec due to some reason
if (col.gameObject.tag == gameObject.tag)
Destroy (col.gameObject,1f); // or let suppose I'm using traffic pooling
}在这种情况下,两辆车都被毁了。但我想毁了那辆被撞到的车
问题:-
我怎样才能摧毁那些被撞到的汽车?
例如:A车撞到B车,B车就被毁了
预先感谢
发布于 2022-09-21 11:58:13
我认为解决这个问题的方法是存储一个已知的=>已经处理过的碰撞的列表,并且只处理每一个碰撞对。
类似的东西。
// struct that holds references to the two colliding gameobjects and implements
// GetHashCode and IEquatable regardless of the order of the two GameObjects
private readonly struct CollisionPair : IEquatable<CollisionPair>
{
private readonly GameObject _a;
private readonly GameObject _b;
public CollisionPair(GameObject a, GameObject b)
{
_a = a;
_b = b;
}
public bool Equals(CollisionPair other)
{
// return true regardless of the order of a and b
return Equals(_a, other._a) && Equals(_b, other._b) || Equals(_b, other._a) && Equals(_a, other._b);
}
public override bool Equals(object obj)
{
return obj is CollisionPair other && Equals(other);
}
// return same HashCode regardless of the order of a and b
public override int GetHashCode()
{
var hashA = _a.GetHashCode();
var hashB = _b.GetHashCode();
return HashCode.Combine(Math.Min(hashA, hashB), Mathf.Max(hashA, hashB));
}
public static bool operator ==(CollisionPair left, CollisionPair right)
{
return left.Equals(right);
}
public static bool operator !=(CollisionPair left, CollisionPair right)
{
return !left.Equals(right);
}
}然后有收藏,然后做。
// stores the already handled collision pairs => if already know this collision => ignore
private static readonly HashSet<CollisionPair> _alreadyHandledCollisions = new();
// [OPTIONAL] stores objects that are already marked for destroy
// if collide with such thing or we are such thing => ignore
private static HashSet<GameObject> _alreadyMarkedForDestroy = new();
private void OnCollisionEnter(Collision col)
{
// Tag doesn't match => ignore
if (!col.gameObject.CompareTag(gameObject.tag)) return;
// [OPTIONAL] This object will be destroyed within a second already => ignore
if(_alreadyMarkedForDestroy.Contains(gameObject)) return;
// [OPTIONAL] The other object will be destroyed within a second already => ignore
if(_alreadyMarkedForDestroy.Contains(col.gameObject)) return;
var collisionPair = new CollisionPair(gameObject, col.gameObject);
// This colliso pair has already been handled (by the other object) => ignore
// but also remove this collision pair since it has already been handled by the other collision partner
if (_alreadyHandledCollisions.Contains(collisionPair))
{
_alreadyHandledCollisions.RemoveWhere(c => c == collisionPair);
return;
}
// Otherwise you handle the collision and store it so he other one doesn't
_alreadyHandledCollisions.Add(collisionPair);
Destroy(col.gameObject, 1f);
// [OPTIONAL]
_alreadyMarkedForDestroy.Add(col.gameObject);
}标记为[OPTIONAL]的附加内容是防止将在下一秒内销毁的对象与其他对象发生新的冲突。如果这是想要的话,就把这些行去掉。
作为一个小演示,我另外标记了要用红色销毁的对象,所以您可以看到它总是只有一个,一旦它是红色的,所有与该对象的进一步碰撞都会被忽略。

发布于 2022-09-21 09:11:28
你可以用刚体找出哪辆车被撞了。
void OnCollisionEnter (Collision col)
{
// I want to destroy car after 1 sec due to some reason
if (col.gameObject.tag == gameObject.tag && IsFirstCar(col.gameObject)) Destroy (col.gameObject,1f);
}
bool IsFirstCar(GameObject other)
{
var rb = GetComponent<Rigidbody>();
var otherRb = other.GetComponent<Rigidbody>();
return rb.velocity.magnitude > otherRb.velocity.magnitude;
}如果A车撞到B车,这意味着A车的速度大于B车,那么我们就可以摧毁B车。
https://stackoverflow.com/questions/73798069
复制相似问题