首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在没有施加力的情况下与一群物理物体接触

在没有施加力的情况下与一群物理物体接触
EN

Game Development用户
提问于 2017-01-29 20:34:34
回答 2查看 851关注 0票数 3

我正在做一场台球比赛,我希望这个圆圈(想象中的)能接触到桌子和球,和球一样完美。

现在我想我应该用刚体,把圆圈的位置和光线投射击中,它的对撞机,它会迫使它到一个合适的位置。

我遇到的问题是,由于它有一个对撞机,它也推动球,我不想。

因此,我的问题是,我如何使一个对象表现得像它在触摸和阻止其他GameObjects与对撞机和刚体,而不推他们?

EN

回答 2

Game Development用户

回答已采纳

发布于 2017-01-31 05:10:40

这里有一种方法,用Physics.SphereCast测试身体的对撞机,而不对它们施加任何力。

它假设你的光标被放置在与球的中心完全相同的y平面上,所以所有的碰撞都是在平面内与它们最宽的圆周碰撞,而摄像机则是直视着游乐场。(这可以调整为倾斜角度的相机,我只是还没做过)

它目前也只适用于静止对撞机-它测试光标没有移动到一个球,但如果一个球移动到光标。如果需要的话可以加进去。

代码语言:javascript
复制
public class ContactCursor : MonoBehaviour {

    // Limits our maximum travel to keep the complexity down.
    public float maxSpeed = 15f;

    public float radius = 0.5f;

    // Remember to set this to include the layer your balls are on.
    public LayerMask collisionLayers; 

    Camera _camera;
    float _cameraPlane;

    // Cache camera and our distance from it, for positioning relative to cursor.
    void Start () {
        _camera = Camera.main;
        _cameraPlane = _camera.WorldToScreenPoint(transform.position).z;
    }

    void LateUpdate () {
        // Transform the mouse into a position on our travel plane.
        Vector3 mousePosition = Input.mousePosition;
        mousePosition.z = _cameraPlane;
        mousePosition = _camera.ScreenToWorldPoint(mousePosition);

        Vector3 offset = mousePosition - transform.position;
        Vector3 direction = offset.normalized;
        float maxDistance = Mathf.Min(offset.magnitude, maxSpeed * Time.deltaTime);

        Vector3 targetPosition = transform.position + direction * maxDistance;

        // Currently set to do 2 passes:
        // 1: Beeline toward the mouse until you hit something.
        // 2: Use any remaining movement to move perpendicular to the obstacle.
        // In my tests this was enough, but you can increase this
        // if you have more complex arrangements or a faster cursor.
        int limit = 2;
        for (int i = 0; i < limit; i++) {

            // Check for a collision in the direction we're trying to move.
            RaycastHit hit;    
            if (Physics.SphereCast(transform.position, radius, direction, out hit, maxDistance, collisionLayers)) {

                // Back up to closest non-intersecting point.
                // (Plus a small fudge factor for stability).
                offset = hit.point + radius * hit.normal - transform.position;                
                float distance = Vector3.Dot(offset, direction) - 0.001f;
                targetPosition = transform.position + direction * distance;

                transform.position = targetPosition;

                if (i + 1 == limit)
                    return;

                // Determine a new move to approach the cursor without
                // penetrating deeper into whatever we hit.
                maxDistance = Mathf.Max(maxDistance - distance, 0f);

                offset = mousePosition - transform.position;    

                // Make sure we don't overshoot the closest point on this line
                // to the mouse (prevents vibrating when close-but-mot-quite).
                distance = offset.sqrMagnitude;
                float forbidden = Vector3.Dot(offset, hit.normal);
                distance -= forbidden * forbidden;
                // Shouldn't happen with infinite-precision real numbers, 
                // but rounding errors happen in practice.
                if (distance < 0f) 
                    return;    
                maxDistance = Mathf.Min(maxDistance, Mathf.Sqrt(distance));                            

                // Calculate new movement direction.
                offset -= forbidden * hit.normal;
                offset.y = 0f;
                direction = offset.normalized;

                targetPosition = transform.position + direction * maxDistance;
            }
            else {
                // No collision! Complete the move.
                transform.position = targetPosition;
                return;
            }
        }
    }
}
票数 6
EN

Game Development用户

发布于 2017-01-30 15:33:51

如果您的问题是,当球员放置球时,它会把其他球推回来,那么为什么不直接打开或关闭isKinematic呢?

关闭所有其他球的物理在球场上,让球员作出球的位置,当球员按下“确定”按钮,启用物理,让球员作出投篮。

票数 2
EN
页面原文内容由Game Development提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://gamedev.stackexchange.com/questions/136520

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档