protected void FindSurface(Collider2D collider) { Vector3 forward = spriteOriginallyFacesLeft ? Vector3.left : Vector3.right; if (m_SpriteRenderer.flipX) { forward.x = -forward.x; } TileBase surfaceHit = PhysicsHelper.FindTileForOverride(collider, transform.position, forward); VFXController.Instance.Trigger(VFX_HASH, transform.position, 0, m_SpriteRenderer.flipX, null, surfaceHit); }
public bool MakePlatformFallthrough() { int colliderCount = 0; int fallthroughColliderCount = 0; for (int i = 0; i < m_CharacterController2D.GroundColliders.Length; i++) { Collider2D col = m_CharacterController2D.GroundColliders[i]; if (col == null) { continue; } colliderCount++; if (PhysicsHelper.ColliderHasPlatformEffector(col)) { fallthroughColliderCount++; } } if (fallthroughColliderCount == colliderCount) { for (int i = 0; i < m_CharacterController2D.GroundColliders.Length; i++) { Collider2D col = m_CharacterController2D.GroundColliders[i]; if (col == null) { continue; } PlatformEffector2D effector; PhysicsHelper.TryGetPlatformEffector(col, out effector); FallthroughReseter reseter = effector.gameObject.AddComponent <FallthroughReseter>(); reseter.StartFall(effector); //set invincible for half a second when falling through a platform, as it will make the player "standup" StartCoroutine(FallThroughtInvincibility()); } } return(fallthroughColliderCount == colliderCount); }
public void FindCurrentSurface() { Collider2D groundCollider = m_CharacterController2D.GroundColliders[0]; if (groundCollider == null) { groundCollider = m_CharacterController2D.GroundColliders[1]; } if (groundCollider == null) { return; } TileBase b = PhysicsHelper.FindTileForOverride(groundCollider, transform.position, Vector2.down); if (b != null) { m_CurrentSurface = b; } }
static void Create() { GameObject physicsHelperGameObject = new GameObject("PhysicsHelper"); s_Instance = physicsHelperGameObject.AddComponent <PhysicsHelper> (); }
/// <summary> /// This updates the state of IsGrounded. It is called automatically in FixedUpdate but can be called more frequently if higher accurracy is required. /// </summary> public void CheckCapsuleEndCollisions(bool bottom = true) { Vector2 raycastDirection; Vector2 raycastStart; float raycastDistance; //Si el componente CapsuleCollider2D no esta if (m_Capsule == null) { //inicio de rayo comienza con la posicion del rigid + la compensación raycastStart = m_Rigidbody2D.position + Vector2.up; raycastDistance = 1f + groundedRaycastDistance; if (bottom) { raycastDirection = Vector2.down; m_RaycastPositions[0] = raycastStart + Vector2.left * 0.4f; m_RaycastPositions[1] = raycastStart; m_RaycastPositions[2] = raycastStart + Vector2.right * 0.4f; } else { raycastDirection = Vector2.up; m_RaycastPositions[0] = raycastStart + Vector2.left * 0.4f; m_RaycastPositions[1] = raycastStart; m_RaycastPositions[2] = raycastStart + Vector2.right * 0.4f; } } else//si hay componente CapsulaCollider 2D { //inicio de rayo comienza con la posicion del rigid + la compensación raycastStart = m_Rigidbody2D.position + m_Capsule.offset; //encuentre el centro del personaje raycastDistance = m_Capsule.size.x * 0.5f + groundedRaycastDistance * 2f; //valor de mitad del personaje en x + rayo a Piso= .1f *2f(supungo que para anticipar mas el rayo) if (bottom) { //Calcule el inicio del rayo en el centro inferior, multiplico down(-) por la mitad Y y a Y le quita el valor de la mitad de X del tamaño del collider raycastDirection = Vector2.down; Vector2 raycastStartBottomCentre = raycastStart + Vector2.down * (m_Capsule.size.y * 0.5f - m_Capsule.size.x * 0.5f); //Pondra los rayos justo antes de la curvatura de la capsula en la parte inferior m_RaycastPositions[0] = raycastStartBottomCentre + Vector2.left * m_Capsule.size.x * 0.5f; m_RaycastPositions[1] = raycastStartBottomCentre; m_RaycastPositions[2] = raycastStartBottomCentre + Vector2.right * m_Capsule.size.x * 0.5f; } else { raycastDirection = Vector2.up; Vector2 raycastStartTopCentre = raycastStart + Vector2.up * (m_Capsule.size.y * 0.5f - m_Capsule.size.x * 0.5f); //Igual que en el if pero arriba m_RaycastPositions[0] = raycastStartTopCentre + Vector2.left * m_Capsule.size.x * 0.5f; m_RaycastPositions[1] = raycastStartTopCentre; m_RaycastPositions[2] = raycastStartTopCentre + Vector2.right * m_Capsule.size.x * 0.5f; } } //Emicion de Rayo y Colisionadores en el piso for (int i = 0; i < m_RaycastPositions.Length; i++) { //Cuenta la cantidad de objetos golpeados int count = Physics2D.Raycast(m_RaycastPositions[i], raycastDirection, m_ContactFilter, m_HitBuffer, raycastDistance); if (bottom)//Si es piso almacene lo encontrado colliders o no. { //Encontro mas de un golpe? si si:almacene ese golpetemporal encontrado, sino:almacene un raycashit2d vacio m_FoundHits[i] = count > 0 ? m_HitBuffer[0] : new RaycastHit2D(); //almacene el primer objeto golpeado de cada uno de los 3 rayos m_GroundColliders[i] = m_FoundHits[i].collider; //Almacene los collider de los primeros golpes encontrados (Se usa para plataformas mobiles mas abajo) } else//Es techo { IsCeilinged = false;//si va en el aire y no ha golpeado nada //hasta la cantidad de golpes for (int j = 0; j < m_HitBuffer.Length; j++) { if (m_HitBuffer[j].collider != null) //Si lo que golpeo tiene un collider { //Creo dice si es diferente a una plataforma mobil entonces es techo if (!PhysicsHelper.ColliderHasPlatformEffector(m_HitBuffer[j].collider)) //Cache para plataformas { IsCeilinged = true; //Es techo } } } } } //Determina normales para saber si esta en el piso if (bottom) { Vector2 groundNormal = Vector2.zero; int hitCount = 0; for (int i = 0; i < m_FoundHits.Length; i++) { if (m_FoundHits[i].collider != null) //Si hay colliders encontrados en el primer impacto de cada rayo { groundNormal += m_FoundHits[i].normal; //Acumule en el vector2 las normales de todos los golpes encontrados hitCount++; } } if (hitCount > 0) //Si hay golpes { groundNormal.Normalize(); // normalice el vector acumulador } //velocidad relativa a la plataforma mobil Vector2 relativeVelocity = Velocity; for (int i = 0; i < m_GroundColliders.Length; i++) { if (m_GroundColliders[i] == null) //sino encuentra collider { continue; // salte al final del bucle evitando llamar a La clase de ayuda } MovingPlatform movingPlatform; if (PhysicsHelper.TryGetMovingPlatform(m_GroundColliders[i], out movingPlatform)) { relativeVelocity -= movingPlatform.Velocity / Time.deltaTime; break; } } //Piso. Debe determinar si esta en el piso //Si la normal en X e Y es 0 es porque esta en el aire no hay normales que rebotan de los colliders if (Mathf.Approximately(groundNormal.x, 0f) && Mathf.Approximately(groundNormal.y, 0f)) { IsGrounded = false; } else// Es piso { IsGrounded = relativeVelocity.y <= 0f;//Es piso si hay normales rebotando y velocidad relativa en Y es menor o igual a cero, es decir si el personaje esta quieto o con gravedad ejerciendo if (m_Capsule != null) //Si no tiene capsula { if (m_GroundColliders[1] != null) //Pero encontro un golpe en la posicion 1, supungo que cero seria el mismo { float capsuleBottomHeight = m_Rigidbody2D.position.y + m_Capsule.offset.y - m_Capsule.size.y * 0.5f; //en la posicion del rigidbody + la compensacion de la cap en Y - la mitad de la cap float middleHitHeight = m_FoundHits[1].point.y; //punto Y del golpe 2 ( el 1 seria [0]) IsGrounded &= middleHitHeight < capsuleBottomHeight + groundedRaycastDistance; //si es menor de la posicion a la capsula + distancia de rayo entonces true //el operador & evalúa ambos operandos, incluso aunque el izquierdo se evalúe como false, de modo que el resultado debe ser false con independencia del valor del operando derecho. //el operador && no evalúa el operando derecho si el izquierdo se evalúa como false. } } } } //inicializa o limpia el bugger de goles en el array for (int i = 0; i < m_HitBuffer.Length; i++) { m_HitBuffer[i] = new RaycastHit2D(); } }
/// <summary> /// This updates the state of IsGrounded. It is called automatically in FixedUpdate but can be called more frequently if higher accurracy is required. /// </summary> public new void CheckCapsuleEndCollisions(bool bottom = true) { Vector2 raycastDirection; Vector2 raycastStart; float raycastDistance; if (m_Capsule == null) { raycastStart = m_Rigidbody2D.position + Vector2.up; raycastDistance = 1f + groundedRaycastDistance; if (bottom) { raycastDirection = Vector2.down; m_RaycastPositions[0] = raycastStart + Vector2.left * 0.4f; m_RaycastPositions[1] = raycastStart; m_RaycastPositions[2] = raycastStart + Vector2.right * 0.4f; } else { raycastDirection = Vector2.up; m_RaycastPositions[0] = raycastStart + Vector2.left * 0.4f; m_RaycastPositions[1] = raycastStart; m_RaycastPositions[2] = raycastStart + Vector2.right * 0.4f; } } else { raycastStart = m_Rigidbody2D.position + m_Capsule.offset; raycastDistance = m_Capsule.size.x * 0.5f + groundedRaycastDistance * 2f; if (bottom) { raycastDirection = Vector2.down; Vector2 raycastStartBottomCentre = raycastStart + Vector2.down * (m_Capsule.size.y * 0.5f - m_Capsule.size.x * 0.5f); m_RaycastPositions[0] = raycastStartBottomCentre + Vector2.left * m_Capsule.size.x * 0.5f; m_RaycastPositions[1] = raycastStartBottomCentre; m_RaycastPositions[2] = raycastStartBottomCentre + Vector2.right * m_Capsule.size.x * 0.5f; } else { raycastDirection = Vector2.up; Vector2 raycastStartTopCentre = raycastStart + Vector2.up * (m_Capsule.size.y * 0.5f - m_Capsule.size.x * 0.5f); m_RaycastPositions[0] = raycastStartTopCentre + Vector2.left * m_Capsule.size.x * 0.5f; m_RaycastPositions[1] = raycastStartTopCentre; m_RaycastPositions[2] = raycastStartTopCentre + Vector2.right * m_Capsule.size.x * 0.5f; } } for (int i = 0; i < m_RaycastPositions.Length; i++) { int count = Physics2D.Raycast(m_RaycastPositions[i], raycastDirection, m_ContactFilter, m_HitBuffer, raycastDistance); if (bottom) { m_FoundHits[i] = count > 0 ? m_HitBuffer[0] : new RaycastHit2D(); m_GroundColliders[i] = m_FoundHits[i].collider; } else { IsCeilinged = false; for (int j = 0; j < m_HitBuffer.Length; j++) { if (m_HitBuffer[j].collider != null) { if (!PhysicsHelper.ColliderHasPlatformEffector(m_HitBuffer[j].collider)) { IsCeilinged = true; } } } } } if (bottom) { Vector2 groundNormal = Vector2.zero; int hitCount = 0; for (int i = 0; i < m_FoundHits.Length; i++) { if (m_FoundHits[i].collider != null) { groundNormal += m_FoundHits[i].normal; hitCount++; } } if (hitCount > 0) { groundNormal.Normalize(); } Vector2 relativeVelocity = Velocity; for (int i = 0; i < m_GroundColliders.Length; i++) { if (m_GroundColliders[i] == null) { continue; } MovingPlatform movingPlatform; if (PhysicsHelper.TryGetMovingPlatform(m_GroundColliders[i], out movingPlatform)) { relativeVelocity -= movingPlatform.Velocity / Time.deltaTime; break; } } if (Mathf.Approximately(groundNormal.x, 0f) && Mathf.Approximately(groundNormal.y, 0f)) { IsGrounded = false; } else { IsGrounded = relativeVelocity.y <= 0f; if (m_Capsule != null) { if (m_GroundColliders[1] != null) { float capsuleBottomHeight = m_Rigidbody2D.position.y + m_Capsule.offset.y - m_Capsule.size.y * 0.5f; float middleHitHeight = m_FoundHits[1].point.y; IsGrounded &= middleHitHeight < capsuleBottomHeight + groundedRaycastDistance; } } } } for (int i = 0; i < m_HitBuffer.Length; i++) { m_HitBuffer[i] = new RaycastHit2D(); } }