碰撞后正确附加到游戏对象?

2024-02-03

我怎么能够properly使一个游戏对象在碰撞后附加(或“粘”)到另一个游戏对象?问题:我希望游戏对象在碰撞后附加,即使它正在改变比例。

“碰撞时附加”代码:

protected Transform stuckTo = null;
protected Vector3 offset = Vector3.zero;

public void LateUpdate()
{
    if (stuckTo != null)
        transform.position = stuckTo.position - offset;
}  

void OnCollisionEnter(Collision col)
{
    rb = GetComponent<Rigidbody>();
    rb.isKinematic = true;

    if(stuckTo == null 
       || stuckTo != col.gameObject.transform)
        offset = col.gameObject.transform.position - transform.position;

    stuckTo = col.gameObject.transform;
}

此代码使游戏对象在碰撞后完美附着。但是当该游戏对象改变比例时(当它附加时),它在视觉上看起来不再附加到它所碰撞的任何东西。基本上,此代码使游戏对象仅保持碰撞时的原始比例。如何让游戏对象始终粘在它所碰撞的物体上?在此过程中其规模有多大?我想避免养育:“但这有点不安全,养育碰撞器可能会导致奇怪的结果,比如随机传送或物体开始疯狂移动和旋转等。” - 萨米德·塔里克·切坦:comment http://gamedev.stackexchange.com/questions/106270/how-can-i-make-a-gameobject-stick-to-another-gameobject-after-it-has-collided#comment194060_106275.

缩放脚本:

public Transform object1; //this is the object that my future-scaling GameObject collided with.
public Transform object2; //another object, the same scale as object1, somewhere else 
//(or vice versa)

void Update () 
{
    float distance = Vector3.Distance (object1.position, object2.position);
    float original_width = 10;
        if (distance <= 10) 
    {
        float scale_x = distance / original_width;
        scale_x = Mathf.Min (scale_x, 3.0f);
        transform.localScale = new Vector3 (scale_x * 3.0f, 3.0f / scale_x, 3.0f);
    }
}

您的基本想法是正确的,您的代码可以稍微修改以支持这一点。

技巧如下:不是将对象粘贴到与其碰撞的对象上,而是在碰撞点创建一个虚拟游戏对象(我们称其为“胶水”),然后将对象粘贴到胶水上。然后,粘合对象将成为我们碰撞对象的父对象。

由于glue只是一个虚拟对象,只有组件变换和一些脚本,因此父子关系没有问题。

另外,请注意,如果我们有多个接触点,在哪个接触点创建粘合并不重要,并且也很容易扩展它以支持旋转,请参见下文。

因此,在碰撞时,我们现在唯一要做的就是创建胶水。这是代码:

void CreateGlue(Vector3 position, GameObject other) {
    // Here we create a glue object programatically, but you can make a prefab if you want.
    // Glue object is a simple transform with Glue.cs script attached.
    var glue = (new GameObject("glue")).AddComponent<Glue>();

    // We set glue position at the contact point
    glue.transform.position = position;

    // This also enables us to support object rotation. We initially set glue rotation to the same value
    // as our game object rotation. If you don't want rotation - simply remove this.
    glue.transform.rotation = transform.rotation;

    // We make the object we collided with a parent of glue object
    glue.transform.SetParent(other.transform);

    // And now we call glue initialization
    glue.AttachObject(gameObject);
}

void OnCollisionEnter(Collision col)
{
    // On collision we simply create a glue object at any contact point.
    CreateGlue(col.contacts[0].point, col.gameObject);
}

这是 Glue.cs 脚本的样子,它将处理 LateUpdate 并修改转换。

public class Glue : MonoBehaviour {

    protected Transform stuckTo = null;
    protected Vector3 offset = Vector3.zero;

    public void AttachObject(GameObject other)
    {
        // Basically - same code as yours with slight modifications

        // Make rigidbody Kinematic
        var rb = other.GetComponent<Rigidbody>();
        rb.isKinematic = true;

        // Calculate offset - pay attention the direction of the offset is now reverse
        // since we attach glue to object and not object to glue. It can be modified to work
        // the other way, it just seems more reasonable to set all "glueing" functionality
        // at Glue object
        offset = transform.position - other.transform.position;

        stuckTo = other.transform;
    }

    public void LateUpdate()
    {
        if (stuckTo != null) {
            // If you don't want to support rotation remove this line
            stuckTo.rotation = transform.rotation;

            stuckTo.position = transform.position - transform.rotation * offset;
        }
    }

    // Just visualizing the glue point, remove if not needed
    void OnDrawGizmos() {
        Gizmos.color = Color.cyan;
        Gizmos.DrawSphere(transform.position, 0.2f);
    }
}

另外,请注意,按照此处建议的方式简单地对对象进行父级设置会给您带来一些额外的麻烦,因为缩放父级也会缩放子级,因此您必须将子级重新缩放回其原始大小。问题是这些缩放操作是相对于不同的锚点的,因此您还必须对对象位置进行额外的调整。虽然可以做到。

我还创建了一个小示例项目,请参见此处(Unity v5.2.f3):https://www.dropbox.com/s/whr85cmdp1tv7tv/GlueObjects.zip?dl=0 https://www.dropbox.com/s/whr85cmdp1tv7tv/GlueObjects.zip?dl=0

附:我看到你混合了变换和刚体语义,因为它是在运动学刚体上完成的,这不是什么大问题,而只是一个建议:想想你是否真的需要在已经“粘”到其他物体上的物体上使用刚体,如果不需要的话- 也许只是删除或禁用刚体,而不是使其成为运动学。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

碰撞后正确附加到游戏对象? 的相关文章

随机推荐