public void CollisionBetweenCircleAndCircle(CustomCircleCollider circleA, CustomCircleCollider circleB) { if (circleA == null || circleB == null) { return; } float Ax = circleA.transform.position.x; float Ay = circleA.transform.position.y; float Bx = circleB.transform.position.x; float By = circleB.transform.position.y; float distanceBetweenCircles = Vector2.Distance(circleA.transform.position, circleB.gameObject.transform.position); //UnityEngine.Debug.Log($"d: {distanceBetweenCircles} | diam: {circleA.CircleRadius + circleB.CircleRadius}"); if (distanceBetweenCircles < circleA.CircleRadius + circleB.CircleRadius) { //Colisao ocorreu float angle = Mathf.Atan2(circleA.transform.position.x - circleB.gameObject.transform.position.x, circleA.transform.position.y - circleB.gameObject.transform.position.y); float distanceToMove = (circleA.CircleRadius + circleB.CircleRadius) - distanceBetweenCircles; Vector3 movement = new Vector3(angle * distanceBetweenCircles * Time.deltaTime , angle * distanceBetweenCircles * Time.deltaTime , 0); if (circleB.PhysicsProperties != null) { if (circleB.PhysicsProperties.canBounce) { BounceCollision(circleA, circleB); } else if (circleB.PhysicsProperties.stopOnCollide || circleA.PhysicsProperties.stopOnCollide) { if (circleA.PhysicsProperties.stopOnCollide) { StopOnCollide(circleA, circleB); } else { StopOnCollide(circleB, circleA); } } } //UnityEngine.Debug.Log($"{circleA.name} | {circleB.name}"); eventBus.Publish(new OnPhysicsObjectCollide(circleA, circleB)); // chamando o evento. Analogo ao "Invoke". } }
public void CollisionBetweenCircleAndSquare(CustomCircleCollider circle, CustomSquareCollider square) { if (circle == null || square == null) { return; } float Cx = circle.transform.position.x; float Cy = circle.transform.position.y; float Sx = square.transform.position.x; float Sy = square.transform.position.y; //float minDistanceTest = square.transform.position.x + square.size.x - circle.transform.position.x + circle.CircleDiameter; //float distanceBetweenObjects = (Cx - Sx * Cx - Sx) + (Cy - Sy * Cy - Sy); float distanceBetweenObjects = Vector2.Distance(square.transform.position, circle.gameObject.transform.position); if (distanceBetweenObjects < circle.CircleDiameter + square.size.x) { /*Testando se as bordas do circulo (circulo + raio) estão sobreponto alguma das bordas do quadrilatero em questão*/ if (Cx + circle.CircleRadius > square.LeftEdge && Cx - circle.CircleRadius < square.RightEdge && (Cy + circle.CircleRadius > square.BottomEdge && square.TopEdge > Cy - circle.CircleRadius || Cy - circle.CircleRadius < square.TopEdge && square.BottomEdge < Cy + circle.CircleRadius)) { if (circle.PhysicsProperties.canBounce) { BounceCollision(circle, square); } if (circle.PhysicsProperties.stopOnCollide || square.PhysicsProperties.stopOnCollide) { if (circle.PhysicsProperties.stopOnCollide) { StopOnCollide(circle, square); } else { StopOnCollide(square, circle); } } eventBus.Publish(new OnPhysicsObjectCollide(circle, square)); // chamando o evento. Analogo ao "Invoke". } else { return; } eventBus.Publish(new OnPhysicsObjectCollide(square, circle)); // chamando o evento. Analogo ao "Invoke". } }
/// <summary> /// Determines whether this instance is colliding with the specified other. /// </summary> /// <returns><c>true</c> if this instance is colliding with the specified other; otherwise, <c>false</c>.</returns> /// <param name="other">Other collider.</param> internal bool IsColliding(CustomCircleCollider other) { if (other == null || !other.isActiveAndEnabled || !isActiveAndEnabled) { return(false); } Vector3 delta = transform.position - other.transform.position; float distanceSquared = Vector3.Dot(delta, delta); float radiusSum = radius + other.radius; return(distanceSquared < radiusSum * radiusSum); }
public override void OnInspectorGUI() { base.OnInspectorGUI(); CustomCircleCollider col = target as CustomCircleCollider; GUILayoutOption option1 = GUILayout.Width(50); GUILayoutOption option2 = GUILayout.Width(80); //半径 GUILayout.BeginHorizontal(); GUILayout.Label("Radius", option1); float value = 0; if (float.TryParse(GUILayout.TextField(col.mRadius.value.ToString(), option2), out value)) { col.mRadius = new FixedPointF(value); } GUILayout.EndHorizontal(); }
/// <summary> /// 检查凸两个圆是否重合 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool CheckCircleAndCircle(CustomCircleCollider a, CustomCircleCollider b) { //障碍物之间的碰撞不处理 if (a.mIsobstacle && b.mIsobstacle) { return(false); } bool mInit = false; //a在左 bool a_at_left = true; //偏移向量 CustomVector2 offsetvec = new CustomVector2(0, 0); //偏移值 FixedPointF offsetfac = new FixedPointF(0); //圆心连线 CustomVector3 vec3 = a.mTrans.Position - b.mTrans.Position; CustomVector2 axis = new CustomVector2(vec3.x, vec3.z); FixedPointF x = axis.x; FixedPointF y = axis.y; FixedPointF temp = x * x + y * y; FixedPointF z = FixedPointF.Sqrt(temp); //圆心重合,x轴推开 if (z == FixedPointF.zero) { axis.x = new FixedPointF(1000, 1000); axis.y = new FixedPointF(0, 1000); } else { axis.x = x / z; axis.y = y / z; } CustomVector3 apos = a.mTrans.Position; CustomVector2 point = new CustomVector2(apos.x, apos.z); FixedPointF mapPoint = CustomVector2.Dot(point, axis); FixedPointF min = mapPoint - a.mRadius; FixedPointF max = mapPoint + a.mRadius; CustomVector2 proj_a = new CustomVector2(min, max); CustomVector3 bpos = b.mTrans.Position; point = new CustomVector2(bpos.x, bpos.z); mapPoint = CustomVector2.Dot(point, axis); min = mapPoint - b.mRadius; max = mapPoint + b.mRadius; CustomVector2 proj_b = new CustomVector2(min, max); if (!Check_Overlap(proj_a, proj_b)) { return(false); } else { bool a_at_left_temp = false; FixedPointF offsetfac_temp = new FixedPointF(0); Set_PushVec(proj_a, proj_b, ref a_at_left_temp, ref offsetfac_temp); if (!mInit) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; mInit = true; } else { if (offsetfac_temp < offsetfac) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; } } } Push(a, b, offsetfac, offsetvec, a_at_left); return(true); }
/// <summary> /// 检查凸多边形和圆是否重合 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public static bool CheckPolygonAndCircle(CustomPolygonCollider a, CustomCircleCollider b) { //障碍物之间的碰撞不处理 if (a.mIsobstacle && b.mIsobstacle) { return(false); } List <CustomVector3> a_worldBound = a.LocalToWorldBound; bool mInit = false; //a在左 bool a_at_left = true; //偏移向量 CustomVector2 offsetvec = new CustomVector2(0, 0); //偏移值 FixedPointF offsetfac = new FixedPointF(0); //顶点连线 //斜率k List <CustomVector2> a_edges = new List <CustomVector2>(); for (int i = 0; i < a_worldBound.Count; i++) { int point1_index = i; int point2_index = (i + 1) % a_worldBound.Count; CustomVector3 offset = a_worldBound[point2_index] - a_worldBound[point1_index]; a_edges.Add(new CustomVector2(offset.x, offset.z)); } for (int i = 0; i < a_edges.Count; i++) { CustomVector2 axis = a_edges[i]; axis = Vec_normal(axis); FixedPointF x = axis.x; FixedPointF y = axis.y; FixedPointF temp = x * x + y * y; FixedPointF z = FixedPointF.Sqrt(temp); axis.x = x / z; axis.y = y / z; //求圆在法线上的投影边界 CustomVector3 vec3 = b.mTrans.Position; CustomVector2 point = new CustomVector2(vec3.x, vec3.z); FixedPointF mapPoint = CustomVector2.Dot(point, axis); FixedPointF min = mapPoint - b.mRadius; FixedPointF max = mapPoint + b.mRadius; CustomVector2 proj_b = new CustomVector2(min, max); CustomVector2 proj_a = GetMapPointMinMaxDis(a_worldBound, axis); if (!Check_Overlap(proj_a, proj_b)) { return(false); } else { bool a_at_left_temp = false; FixedPointF offsetfac_temp = new FixedPointF(0); Set_PushVec(proj_a, proj_b, ref a_at_left_temp, ref offsetfac_temp); if (!mInit) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; mInit = true; } else { if (offsetfac_temp < offsetfac) { a_at_left = a_at_left_temp; offsetfac = offsetfac_temp; offsetvec = axis; } } } } Push(a, b, offsetfac, offsetvec, a_at_left); return(true); }