我正在做一场台球比赛,我希望这个圆圈(想象中的)能接触到桌子和球,和球一样完美。
现在我想我应该用刚体,把圆圈的位置和光线投射击中,它的对撞机,它会迫使它到一个合适的位置。
我遇到的问题是,由于它有一个对撞机,它也推动球,我不想。
因此,我的问题是,我如何使一个对象表现得像它在触摸和阻止其他GameObjects与对撞机和刚体,而不推他们?
发布于 2017-01-31 05:10:40
这里有一种方法,用Physics.SphereCast测试身体的对撞机,而不对它们施加任何力。
它假设你的光标被放置在与球的中心完全相同的y平面上,所以所有的碰撞都是在平面内与它们最宽的圆周碰撞,而摄像机则是直视着游乐场。(这可以调整为倾斜角度的相机,我只是还没做过)
它目前也只适用于静止对撞机-它测试光标没有移动到一个球,但如果一个球移动到光标。如果需要的话可以加进去。
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;
}
}
}
}
发布于 2017-01-30 15:33:51
如果您的问题是,当球员放置球时,它会把其他球推回来,那么为什么不直接打开或关闭isKinematic呢?
关闭所有其他球的物理在球场上,让球员作出球的位置,当球员按下“确定”按钮,启用物理,让球员作出投篮。
https://gamedev.stackexchange.com/questions/136520
复制相似问题