public override void TryExitState(float DeltaTime) { var scaleFactor = animal.ScaleFactor; var Radius = animal.RayCastRadius * scaleFactor; DeltaGoingDown = GoingDown; var Gravity = animal.Gravity; GoingDown = Vector3.Dot(animal.DeltaPos, Gravity) > 0; //Check if is falling down //GoingDown = Vector3.Dot(animal.DeltaPos, Gravity) > 0; //Check if is falling down float DeltaDistance = 0; if (GoingDown) { DeltaDistance = Vector3.Project(animal.DeltaPos, Gravity).magnitude; FallCurrentDistance += DeltaDistance; } FallPoint = animal.Main_Pivot_Point; //FallPoint += Vector3.Project(animal.AdditivePosition, Gravity); //To check ahead that the animal can land.. if (animal.debugGizmos && debug) { MTools.DrawWireSphere(FallPoint, Color.magenta, Radius); MTools.DrawWireSphere(FallPoint + Gravity * animal.Height, (Color.red + Color.blue) / 2, Radius); Debug.DrawRay(FallPoint, Gravity * 100f, Color.magenta); } if (Physics.Raycast(FallPoint, Gravity, out FallRayCast, 100f, animal.GroundLayer, IgnoreTrigger)) { DistanceToGround = FallRayCast.distance; FoundLand = true; if (animal.debugGizmos && debug) { MTools.DrawWireSphere(FallRayCast.point, (Color.blue + Color.red) / 2, Radius); MTools.DrawWireSphere(FallPoint, (Color.red), Radius); } switch (BlendFall) { case FallBlending.DistanceNormalized: { var realDistance = DistanceToGround - animal.Height; if (MaxHeight < realDistance) { MaxHeight = realDistance; //get the Highest Distance the first time you touch the ground } else { realDistance -= LowerBlendDistance; FallBlend = Mathf.Lerp(FallBlend, realDistance / MaxHeight, DeltaTime * 10); //Small blend in case there's a new ground found animal.State_SetFloat(1 - FallBlend); //Blend between High and Low Fall } } break; case FallBlending.Distance: animal.State_SetFloat(FallCurrentDistance); break; case FallBlending.VerticalVelocity: var UpInertia = Vector3.Project(animal.DeltaPos, animal.UpVector).magnitude; //Clean the Vector from Forward and Horizontal Influence animal.State_SetFloat(UpInertia / animal.DeltaTime * (GoingDown ? 1 : -1)); break; default: break; } if (animal.Height > DistanceToGround || ((DistanceToGround - DeltaDistance) < 0)) //Means has touched the ground { var angl = Vector3.Angle(FallRayCast.normal, animal.UpVector); var DeepSlope = angl > animal.maxAngleSlope; if (!DeepSlope) //Check if we are not on a deep slope { AllowExit(); animal.Grounded = true; animal.UseGravity = false; var GroundedPos = Vector3.Project(FallRayCast.point - animal.transform.position, Gravity); //IMPORTANT HACk FOR animal.Teleport_Internal(animal.transform.position + GroundedPos); //SUPER IMPORTANT!!! animal.ResetUPVector(); //IMPORTAAANT! UpImpulse = Vector3.zero; Debugging($"[Try Exit] (Grounded) + [Terrain Angle ={angl}]"); } } } else { //Means that has lost the RayCastHit that it had if (FoundLand) { // Debug.LogWarning("The Animal Tried to go below the terrain.... Unity Physic Bug :( "); animal.Teleport_Internal(animal.LastPos); //HACK WHEN THE ANIMAL Goes UnderGround animal.ResetUPVector(); } } if (!animal.Zone && !animal.HasExternalForce) { if ((DeltaGoingDown && !GoingDown)) { if (LastDeltaDistance > DeltaDistance && DeltaDistance != 0) { //Means that is still trying to fall but it cant because something is bloking the fall soo lets push it forward animal.ResetUPVector(); animal.GravityTime = animal.StartGravityTime; animal.MovementAxis.z = 1; //Force going forward HACK animal.InertiaPositionSpeed = animal.Forward * animal.ScaleFactor * DeltaTime * animal.FallForward; Debug.Log("GoingForward " + DeltaDistance); } } } LastDeltaDistance = DeltaDistance; }
public override void TryExitState(float DeltaTime) { var scaleFactor = animal.ScaleFactor; var Radius = animal.RayCastRadius * scaleFactor; var Gravity = animal.Gravity; bool GoingDown = Vector3.Dot(animal.DeltaPos, Gravity) > 0; //Check if is falling down var DeltaDistance_Down = Vector3.Project(animal.DeltaPos, Gravity).magnitude; if (GoingDown) { FallCurrentDistance += DeltaDistance_Down; } FallPoint = animal.Main_Pivot_Point; //FallPoint += Vector3.Project(animal.AdditivePosition, Gravity); //To check ahead that the animal can land.. if (animal.debugGizmos && debug) { MTools.DrawWireSphere(FallPoint, Color.magenta, Radius); MTools.DrawWireSphere(FallPoint + Gravity * animal.Height, (Color.red + Color.blue) / 2, Radius); Debug.DrawRay(FallPoint, Gravity * 100f, Color.magenta); } if (Physics.Raycast(FallPoint, Gravity, out FallRayCast, 100f, animal.GroundLayer, QueryTriggerInteraction.Ignore)) { DistanceToGround = FallRayCast.distance; if (animal.debugGizmos && debug) { MTools.DrawWireSphere(FallRayCast.point, (Color.blue + Color.red) / 2, Radius); MTools.DrawWireSphere(FallPoint, (Color.red), Radius); } switch (BlendFall) { case FallBlending.DistanceNormalized: { var realDistance = DistanceToGround - animal.Height; if (MaxHeight < realDistance) { MaxHeight = realDistance; //get the Highest Distance the first time you touch the ground } else { realDistance -= LowerBlendDistance; FallBlend = Mathf.Lerp(FallBlend, realDistance / MaxHeight, DeltaTime * 10); //Small blend in case there's a new ground found animal.State_SetFloat(1 - FallBlend); //Blend between High and Low Fall } } break; case FallBlending.Distance: animal.State_SetFloat(FallCurrentDistance); break; case FallBlending.VerticalVelocity: var UpInertia = Vector3.Project(animal.DeltaPos, animal.UpVector).magnitude; //Clean the Vector from Forward and Horizontal Influence animal.State_SetFloat(UpInertia / animal.DeltaTime * (GoingDown ? 1 : -1)); break; default: break; } if (animal.IsOnZone && animal.HasExternalForce) { return; //HACK FOR SPRING AND WIND ZONES } // Debug.Log($"Dist: {DistanceToGround:F3} | Delta_Dist: {DeltaDistance_Down:F3} | {(DistanceToGround - DeltaDistance_Down):F3}"); if (animal.Height > DistanceToGround || ((DistanceToGround - DeltaDistance_Down) < 0)) //Means has touched the ground { var angl = Vector3.Angle(FallRayCast.normal, animal.UpVector); var DeepSlope = angl > animal.maxAngleSlope; if (!DeepSlope) { AllowExit(); animal.Grounded = true; animal.UseGravity = false; var GroundedPos = Vector3.Project(FallRayCast.point - animal.transform.position, Gravity); //IMPORTANT animal.Teleport(animal.transform.position + GroundedPos); //SUPER IMPORTANT!!! animal.ResetUPVector(); //IMPORTAAANT! UpImpulse = Vector3.zero; Debugging("[Try Exit] (Grounded) + [Terrain Angle = " + angl + "]"); } } } }
private bool TryFallRayCasting(Vector3 fall_Pivot, float Multiplier) { FallHits = new RaycastHit[RayHits]; var Direction = animal.TerrainSlope < 0 ? animal.Gravity : -transform.up; var Radius = animal.RayCastRadius * animal.ScaleFactor; Hits = Physics.SphereCastNonAlloc(fall_Pivot, Radius, Direction, FallHits, Multiplier, animal.GroundLayer, IgnoreTrigger); if (Hits > 0) { if (animal.Grounded) { foreach (var hit in FallHits) { if (hit.collider != null) { var slope = Vector3.Angle(hit.normal, animal.UpVector); slope *= Vector3.Dot(animal.UpVector, animal.Forward) < 0 ? -1 : 1; //Calcualte the Fall Angle Positive or Negative if (slope > -animal.maxAngleSlope && slope <= animal.maxAngleSlope) { FallRayCast = hit; if (debug) { Debug.DrawRay(fall_Pivot, Direction * Multiplier, Color.magenta); Debug.DrawRay(FallRayCast.point, FallRayCast.normal * animal.ScaleFactor * 0.2f, Color.magenta); MTools.DrawWireSphere(fall_Pivot + Direction * DistanceToGround, Color.magenta, Radius); } break; } } } DistanceToGround = FallRayCast.distance; var TerrainSlope = Vector3.Angle(FallRayCast.normal, animal.UpVector); TerrainSlope *= Vector3.Dot(animal.UpVector, animal.Forward) < 0 ? -1 : 1; //Calcualte the Fall Angle Positive or Negative if (TerrainSlope < -animal.maxAngleSlope || animal.DeepSlope) { Debugging($"[Try] Slope is too deep [{FallRayCast.collider}] | Hits: {Hits} | Slope : {TerrainSlope:F2} T:{Time.time:F3}"); return(true); } } else //If the Animal is in the air NOT GROUNDED { FallRayCast = FallHits[0]; DistanceToGround = FallRayCast.distance; var FallSlope = Vector3.Angle(FallRayCast.normal, animal.UpVector); if (FallSlope > animal.maxAngleSlope) { Debugging($"[Try] The Animal is on the Air and the angle SLOPE of the ground Hitted is too Deep"); return(true); } if (animal.Height >= DistanceToGround) //If the distance to ground is very small means that we are very close to the ground { if (animal.ExternalForce != Vector3.zero) { return(true); //Hack for external forces } Debugging($"[Try Failed] Distance to the ground is very small means that we are very close to the ground. CHECK IF GROUNDED"); animal.CheckIfGrounded();//Hack IMPORTANT HACK!!!!!!! return(false); } } } else { Debugging($"[Try] There's no Ground beneath the Animal"); // Debug.Break(); return(true); } // animal.CheckIfGrounded(); //Hack IMPORTANT HACK!!!!!!! return(false); }
/// <summary>Raycasting stuff to align and calculate the ground from the animal ****IMPORTANT***</summary> internal virtual void AlignRayCasting() { MainRay = FrontRay = false; hit_Chest = new RaycastHit(); //Clean the Raycasts every time hit_Hip = new RaycastHit(); //Clean the Raycasts every time hit_Chest.distance = hit_Hip.distance = Height; //Reset the Distances to the Heigth of the animal //var Direction = Gravity; var Direction = -transform.up; if (Physics.Raycast(Main_Pivot_Point, Direction, out hit_Chest, Pivot_Multiplier, GroundLayer, QueryTriggerInteraction.Ignore)) { FrontRay = true; var MainPivotSlope = Vector3.SignedAngle(hit_Chest.normal, UpVector, Right); if (MainPivotSlope > maxAngleSlope) //Means that the Slope is higher thanthe Max slope so stop the animal from Going forward AND ONLY ON LOCOMOTION { if (MovementAxisRaw.z > 0 && !hit_Chest.transform.gameObject.CompareTag("Stair")) { AdditivePosition = Vector3.ProjectOnPlane(AdditivePosition, Forward); //Remove Forward Movement MovementAxis.z = 0; } } // else { if (debugGizmos) { Debug.DrawRay(hit_Chest.point, hit_Chest.normal * ScaleFactor * 0.2f, Color.green); MTools.DrawWireSphere(Main_Pivot_Point + Direction * (hit_Chest.distance - RayCastRadius), Color.green, RayCastRadius * ScaleFactor); } if (platform == null || platform != hit_Chest.transform) //Platforming logic { platform = hit_Chest.transform; platform_Pos = platform.position; platform_Rot = platform.rotation; } hit_Chest.collider.attachedRigidbody?.AddForceAtPosition(Gravity * (RB.mass / 2), hit_Chest.point, ForceMode.Force); } } else { platform = null; } if (Has_Pivot_Hip && Has_Pivot_Chest) //Ray From the Hip to the ground { var hipPoint = Pivot_Hip.World(transform) + DeltaVelocity; if (Physics.Raycast(hipPoint, Direction, out hit_Hip, ScaleFactor * Pivot_Hip.multiplier, GroundLayer, QueryTriggerInteraction.Ignore)) { MainRay = true; if (debugGizmos) { Debug.DrawRay(hit_Hip.point, hit_Hip.normal * ScaleFactor * 0.2f, Color.green); MTools.DrawWireSphere(hipPoint + Direction * (hit_Hip.distance - RayCastRadius), Color.green, RayCastRadius * ScaleFactor); } if (platform == null || platform != hit_Chest.transform) //Platforming logic { platform = hit_Hip.transform; platform_Pos = platform.position; platform_Rot = platform.rotation; } hit_Hip.collider.attachedRigidbody?.AddForceAtPosition(Gravity * (RB.mass / 2), hit_Hip.point, ForceMode.Force); if (!FrontRay) { hit_Chest = hit_Hip; //If there's no Front Ray } } else { platform = null; if (FrontRay) { InertiaPositionSpeed = Forward * ScaleFactor * DeltaTime * 2; //Force going forward in case there's no front Ray (HACK) hit_Hip = hit_Chest; //In case there's no Hip Ray } } } else { MainRay = FrontRay; //Just in case you dont have HIP RAY IMPORTANT FOR HUMANOID CHARACTERSSSSSSSSSSSS hit_Hip = hit_Chest; //In case there's no Hip Ray } if (ground_Changes_Gravity) { Gravity = -hit_Hip.normal; } CalculateSurfaceNormal(); }