bool UAbilityTask_ApplyRootMotionMoveToActorForce::UpdateTargetLocation(float DeltaTime) { if (TargetActor && GetWorld()) { const FVector PreviousTargetLocation = TargetLocation; FVector ExactTargetLocation = CalculateTargetOffset(); const float CurrentTime = GetWorld()->GetTimeSeconds(); const float CompletionPercent = (CurrentTime - StartTime) / Duration; const float TargetLerpSpeedHorizontal = TargetLerpSpeedHorizontalCurve ? TargetLerpSpeedHorizontalCurve->GetFloatValue(CompletionPercent) : 1000.f; const float TargetLerpSpeedVertical = TargetLerpSpeedVerticalCurve ? TargetLerpSpeedVerticalCurve->GetFloatValue(CompletionPercent) : 500.f; const float MaxHorizontalChange = FMath::Max(0.f, TargetLerpSpeedHorizontal * DeltaTime); const float MaxVerticalChange = FMath::Max(0.f, TargetLerpSpeedVertical * DeltaTime); FVector ToExactLocation = ExactTargetLocation - PreviousTargetLocation; FVector TargetLocationDelta = ToExactLocation; // Cap vertical lerp if (FMath::Abs(ToExactLocation.Z) > MaxVerticalChange) { if (ToExactLocation.Z >= 0.f) { TargetLocationDelta.Z = MaxVerticalChange; } else { TargetLocationDelta.Z = -MaxVerticalChange; } } // Cap horizontal lerp if (FMath::Abs(ToExactLocation.SizeSquared2D()) > MaxHorizontalChange*MaxHorizontalChange) { FVector ToExactLocationHorizontal(ToExactLocation.X, ToExactLocation.Y, 0.f); ToExactLocationHorizontal.Normalize(); ToExactLocationHorizontal *= MaxHorizontalChange; TargetLocationDelta.X = ToExactLocationHorizontal.X; TargetLocationDelta.Y = ToExactLocationHorizontal.Y; } TargetLocation += TargetLocationDelta; return true; } return false; }
void AVehiclePawn::UpdateWheelEffects(float DeltaTime) { if (bTiresTouchingGround == false && LandingSound) //we don't update bTiresTouchingGround until later in this function, so we can use it here to determine whether we're landing { float MaxSpringForce = GetVehicleMovement()->GetMaxSpringForce(); if (MaxSpringForce > SpringCompressionLandingThreshold) { UGameplayStatics::PlaySoundAtLocation(this, LandingSound, GetActorLocation()); } } bTiresTouchingGround = false; if (DustType && !bIsDying && GetVehicleMovement() && GetVehicleMovement()->Wheels.Num() > 0) { const float CurrentSpeed = GetVehicleSpeed(); for (int32 i = 0; i < ARRAY_COUNT(DustPSC); i++) { UPhysicalMaterial* ContactMat = GetVehicleMovement()->Wheels[i]->GetContactSurfaceMaterial(); if (ContactMat != NULL) { bTiresTouchingGround = true; } UParticleSystem* WheelFX = DustType->GetDustFX(ContactMat, CurrentSpeed); const bool bIsActive = DustPSC[i] != NULL && !DustPSC[i]->bWasDeactivated && !DustPSC[i]->bWasCompleted; UParticleSystem* CurrentFX = DustPSC[i] != NULL ? DustPSC[i]->Template : NULL; if (WheelFX != NULL && (CurrentFX != WheelFX || !bIsActive)) { if (DustPSC[i] == NULL || !DustPSC[i]->bWasDeactivated) { if (DustPSC[i] != NULL) { DustPSC[i]->SetActive(false); DustPSC[i]->bAutoDestroy = true; } SpawnNewWheelEffect(i); } DustPSC[i]->SetTemplate(WheelFX); DustPSC[i]->ActivateSystem(); } else if (WheelFX == NULL && bIsActive) { DustPSC[i]->SetActive(false); } } } if (SkidAC != NULL) { FVector Vel = GetVelocity(); bool bVehicleStopped = Vel.SizeSquared2D() < SkidThresholdVelocity*SkidThresholdVelocity; bool TireSlipping = GetVehicleMovement()->CheckSlipThreshold(LongSlipSkidThreshold, LateralSlipSkidThreshold); bool bWantsToSkid = bTiresTouchingGround && !bVehicleStopped && TireSlipping; float CurrTime = GetWorld()->GetTimeSeconds(); if (bWantsToSkid && !bSkidding) { bSkidding = true; SkidAC->Play(); SkidStartTime = CurrTime; } if (!bWantsToSkid && bSkidding) { bSkidding = false; SkidAC->FadeOut(SkidFadeoutTime, 0); if (CurrTime - SkidStartTime > SkidDurationRequiredForStopSound) { UGameplayStatics::PlaySoundAtLocation(this, SkidSoundStop, GetActorLocation()); } } } }
static void CalcBoundingSphyl(const FRawMesh& RawMesh, FSphere& sphere, float& length, FRotator& rotation, FVector& LimitVec) { if (RawMesh.VertexPositions.Num() == 0) return; FVector Center, Extents; CalcBoundingBox(RawMesh, Center, Extents, LimitVec); // @todo sphere.Center could perhaps be adjusted to best fit if model is non-symmetric on it's longest axis sphere.Center = Center; // Work out best axis aligned orientation (longest side) float Extent = Extents.GetMax(); if (Extent == Extents.X) { rotation = FRotator(90.f, 0.f, 0.f); Extents.X = 0.0f; } else if (Extent == Extents.Y) { rotation = FRotator(0.f, 0.f, 90.f); Extents.Y = 0.0f; } else { rotation = FRotator(0.f, 0.f, 0.f); Extents.Z = 0.0f; } // Cleared the largest axis above, remaining determines the radius float r = Extents.GetMax(); float r2 = FMath::Square(r); // Now check each point lies within this the radius. If not - expand it a bit. for (uint32 i = 0; i<(uint32)RawMesh.VertexPositions.Num(); i++) { FVector cToP = (RawMesh.VertexPositions[i] * LimitVec) - sphere.Center; cToP = rotation.UnrotateVector(cToP); const float pr2 = cToP.SizeSquared2D(); // Ignore Z here... // If this point is outside our current bounding sphere's radius if (pr2 > r2) { // ..expand radius just enough to include this point. const float pr = FMath::Sqrt(pr2); r = 0.5f * (r + pr); r2 = FMath::Square(r); } } // The length is the longest side minus the radius. float hl = FMath::Max(0.0f, Extent - r); // Now check each point lies within the length. If not - expand it a bit. for (uint32 i = 0; i<(uint32)RawMesh.VertexPositions.Num(); i++) { FVector cToP = (RawMesh.VertexPositions[i] * LimitVec) - sphere.Center; cToP = rotation.UnrotateVector(cToP); // If this point is outside our current bounding sphyl's length if (FMath::Abs(cToP.Z) > hl) { const bool bFlip = (cToP.Z < 0.f ? true : false); const FVector cOrigin(0.f, 0.f, (bFlip ? -hl : hl)); const float pr2 = (cOrigin - cToP).SizeSquared(); // If this point is outside our current bounding sphyl's radius if (pr2 > r2) { FVector cPoint; FMath::SphereDistToLine(cOrigin, r, cToP, (bFlip ? FVector(0.f, 0.f, 1.f) : FVector(0.f, 0.f, -1.f)), cPoint); // Don't accept zero as a valid diff when we know it's outside the sphere (saves needless retest on further iterations of like points) hl += FMath::Max(FMath::Abs(cToP.Z - cPoint.Z), 1.e-6f); } } } sphere.W = r; length = hl * 2.0f; }