Exemplo n.º 1
0
static bool HasteTrace(UWorld* InWorld, FHitResult& OutHit, FVector InStart, FVector InEnd, FName InTraceTag, bool InbReturnFaceIndex = false)
{
	FCollisionQueryParams QueryParams(InTraceTag, true);
	QueryParams.bReturnFaceIndex = InbReturnFaceIndex;

	bool bResult = true;
	while (true)
	{
		bResult = InWorld->LineTraceSingleByChannel(OutHit, InStart, InEnd, ECC_WorldStatic, QueryParams);
		if (bResult)
		{
			// In the editor traces can hit "No Collision" type actors, so ugh.
			FBodyInstance* BodyInstance = OutHit.Component->GetBodyInstance();
			if (BodyInstance->GetCollisionEnabled() != ECollisionEnabled::QueryAndPhysics || BodyInstance->GetResponseToChannel(ECC_WorldStatic) != ECR_Block)
			{
				AActor* Actor = OutHit.Actor.Get();
				if (Actor)
				{
					QueryParams.AddIgnoredActor(Actor);
				}
				InStart = OutHit.ImpactPoint;
				continue;
			}
		}
		break;
	}
	return bResult;
}
bool UMovementComponent::OverlapTest(const FVector& Location, const FQuat& RotationQuat, const ECollisionChannel CollisionChannel, const FCollisionShape& CollisionShape, const AActor* IgnoreActor) const
{
	static FName NAME_TestOverlap = FName(TEXT("MovementOverlapTest"));
	FCollisionQueryParams QueryParams(NAME_TestOverlap, false, IgnoreActor);
	FCollisionResponseParams ResponseParam;
	InitCollisionParams(QueryParams, ResponseParam);
	return GetWorld()->OverlapBlockingTestByChannel(Location, RotationQuat, CollisionChannel, CollisionShape, QueryParams, ResponseParam);
}
UPrimitiveComponent* UPhysicsSpringComponent::GetSpringCollision(const FVector& Start, const FVector& End, float& Time) const
{
	UWorld* World = GetWorld();
	AActor* IgnoreActor = bIgnoreSelf ? GetOwner() : nullptr;

	static FName NAME_Spring = FName(TEXT("SpringComponent"));
	FCollisionQueryParams QueryParams(NAME_Spring, true, IgnoreActor);
	FHitResult Hit;

	UPrimitiveComponent* CollidedComponent = nullptr;
	
	const FVector Delta = End - Start;
	const float DeltaSizeSqr = Delta.SizeSquared();
	if (DeltaSizeSqr > FMath::Square(SMALL_NUMBER))
	{
		if (bool bBlockingHit = World->SweepSingleByChannel(Hit, Start, End, FQuat::Identity, SpringChannel, FCollisionShape::MakeSphere(SpringRadius), QueryParams))
		{
			CollidedComponent = Hit.GetComponent();
			Time = CollidedComponent ? Hit.Time : 1.f;
		}
	}

	return CollidedComponent;
}
void UGripMotionControllerComponent::TickGrip()
{
	if (GrippedActors.Num())
	{
		FTransform WorldTransform;
		FTransform InverseTransform = this->GetComponentTransform().Inverse();

		for (int i = GrippedActors.Num() - 1; i >= 0; --i)
		{
			if (GrippedActors[i].Actor || GrippedActors[i].Component)
			{
				// GetRelativeTransformReverse had some serious f*****g floating point errors associated with it that was f*****g everything up
				// Not sure whats wrong with the function but I might want to push a patch out eventually
				WorldTransform = GrippedActors[i].RelativeTransform.GetRelativeTransform(InverseTransform);

				UPrimitiveComponent *root = GrippedActors[i].Component;
				AActor *actor = GrippedActors[i].Actor;

				if (!root)
					root = Cast<UPrimitiveComponent>(GrippedActors[i].Actor->GetRootComponent());

				if (!root)
					continue;

				if (!actor)
					actor = root->GetOwner();

				if (!actor)
					continue;

				if (bIsServer)
				{
					// Handle collision intersection detection, this is used to intelligently manage some of the networking and late update features.
					switch (GrippedActors[i].GripCollisionType.GetValue())
					{
					case EGripCollisionType::InteractiveCollisionWithPhysics:
					case EGripCollisionType::InteractiveHybridCollisionWithSweep:
					{
						TArray<FOverlapResult> Hits;
						FComponentQueryParams Params(NAME_None, this->GetOwner());
						Params.bTraceAsyncScene = root->bCheckAsyncSceneOnMove;
						Params.AddIgnoredActor(actor);
						Params.AddIgnoredActors(root->MoveIgnoreActors);

						if(GetWorld()->ComponentOverlapMulti(Hits, root, root->GetComponentLocation(), root->GetComponentQuat(), Params))
						{
							GrippedActors[i].bColliding = true;
						}
						else
						{
							GrippedActors[i].bColliding = false;
						}
					}

					// Skip collision intersects with these types, they dont need it
					case EGripCollisionType::PhysicsOnly:
					case EGripCollisionType::SweepWithPhysics:
					case EGripCollisionType::InteractiveCollisionWithSweep:
					default:break;
					}
				}

				// Need to figure out best default behavior
				/*if (GrippedActors[i].bHasSecondaryAttachment && GrippedActors[i].SecondaryAttachment)
				{
				WorldTransform.SetRotation((WorldTransform.GetLocation() - GrippedActors[i].SecondaryAttachment->GetComponentLocation()).ToOrientationRotator().Quaternion());
				}*/

				if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveCollisionWithPhysics)
				{
					UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform);
				}
				else if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveCollisionWithSweep)
				{
					if (bIsServer)
					{
						FHitResult OutHit;

						// Need to use without teleport so that the physics velocity is updated for when the actor is released to throw
						root->SetWorldTransform(WorldTransform, true, &OutHit);

						if (OutHit.bBlockingHit)
						{
							GrippedActors[i].bColliding = true;

							if (!actor->bReplicateMovement)
								actor->SetReplicateMovement(true);
						}
						else
						{
							GrippedActors[i].bColliding = false;

							if (actor->bReplicateMovement)
								actor->SetReplicateMovement(false);
						}
					}
					else
					{
						if (!GrippedActors[i].bColliding)
						{
							root->SetWorldTransform(WorldTransform, true);
						}
					}
				}
				else if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveHybridCollisionWithSweep)
				{
					// Need to use without teleport so that the physics velocity is updated for when the actor is released to throw
					//if (bIsServer)
					//{
					FBPActorPhysicsHandleInformation * GripHandle = GetPhysicsGrip(GrippedActors[i]);
					if (!GrippedActors[i].bColliding)
					{
						// Make sure that there is no collision on course before turning off collision and snapping to controller
						if (bIsServer && actor && actor->bReplicateMovement)
						{
							FCollisionQueryParams QueryParams(NAME_None, false, this->GetOwner());
							FCollisionResponseParams ResponseParam;
							root->InitSweepCollisionParams(QueryParams, ResponseParam);
							QueryParams.AddIgnoredActor(actor);
							QueryParams.AddIgnoredActors(root->MoveIgnoreActors);

							if (GetWorld()->SweepTestByChannel(root->GetComponentLocation(), WorldTransform.GetLocation(), root->GetComponentQuat(), ECollisionChannel::ECC_Visibility, root->GetCollisionShape(), QueryParams, ResponseParam))
							{
								GrippedActors[i].bColliding = true;
							}
							else
							{
								GrippedActors[i].bColliding = false;
							}
						}
						
						// If still not colliding
						if (!GrippedActors[i].bColliding)
						{
							if (bIsServer && actor->bReplicateMovement) // So we don't call on on change event over and over locally
								actor->SetReplicateMovement(false);

							if (bIsServer && GripHandle)
							{
								DestroyPhysicsHandle(GrippedActors[i]);

								if(GrippedActors[i].Actor)
									GrippedActors[i].Actor->DisableComponentsSimulatePhysics();
								else
									root->SetSimulatePhysics(false);
							}

							root->SetWorldTransform(WorldTransform, false);
						}
						else
						{
							if (bIsServer && GrippedActors[i].bColliding && GripHandle)
								UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform);
						}

					}
					else if (GrippedActors[i].bColliding && !GripHandle)
					{
						if (bIsServer && !actor->bReplicateMovement)
							actor->SetReplicateMovement(true);

						root->SetSimulatePhysics(true);

						if (bIsServer)
							SetUpPhysicsHandle(GrippedActors[i]);
					}
					else
					{
						if (bIsServer && GrippedActors[i].bColliding && GripHandle)
							UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform);
					}
				}
				else if (GrippedActors[i].GripCollisionType == EGripCollisionType::SweepWithPhysics)
				{
					if (bIsServer)
					{
						
						FVector OriginalPosition(root->GetComponentLocation());
						FRotator OriginalOrientation(root->GetComponentRotation());

						FVector NewPosition(WorldTransform.GetTranslation());
						FRotator NewOrientation(WorldTransform.GetRotation());

						// Now sweep collision separately so we can get hits but not have the location altered
						if (bUseWithoutTracking || NewPosition != OriginalPosition || NewOrientation != OriginalOrientation)
						{
							FVector move = NewPosition - OriginalPosition;

							// ComponentSweepMulti does nothing if moving < KINDA_SMALL_NUMBER in distance, so it's important to not try to sweep distances smaller than that. 
							const float MinMovementDistSq = (FMath::Square(4.f*KINDA_SMALL_NUMBER));

							if (bUseWithoutTracking || move.SizeSquared() > MinMovementDistSq || NewOrientation != OriginalOrientation)
							{
								if (CheckComponentWithSweep(root, move, NewOrientation, false))
								{

								}
							}
						}

						// Move the actor, we are not offsetting by the hit result anyway
						root->SetWorldTransform(WorldTransform, false);
					}
					else
					{
						// Move the actor, we are not offsetting by the hit result anyway
						root->SetWorldTransform(WorldTransform, false);
					}
				}
				else if (GrippedActors[i].GripCollisionType == EGripCollisionType::PhysicsOnly)
				{
					// Move the actor, we are not offsetting by the hit result anyway
					root->SetWorldTransform(WorldTransform, false);
				}
			}
			else
			{
				if (bIsServer)
				{
					DestroyPhysicsHandle(GrippedActors[i]);

					GrippedActors.RemoveAt(i); // If it got garbage collected then just remove the pointer, won't happen with new uproperty use, but keeping it here anyway
				}
			}

		}
	}

}
Exemplo n.º 5
0
void USpringArmComponent::UpdateDesiredArmLocation(bool bDoTrace, bool bDoLocationLag, bool bDoRotationLag, float DeltaTime)
{
	FRotator DesiredRot = GetComponentRotation();

	// If inheriting rotation, check options for which components to inherit
	if(!bAbsoluteRotation)
	{
		if(!bInheritPitch)
		{
			DesiredRot.Pitch = RelativeRotation.Pitch;
		}

		if (!bInheritYaw)
		{
			DesiredRot.Yaw = RelativeRotation.Yaw;
		}

		if (!bInheritRoll)
		{
			DesiredRot.Roll = RelativeRotation.Roll;
		}
	}

	// Apply 'lag' to rotation if desired
	if(bDoRotationLag)
	{
		DesiredRot = FMath::RInterpTo(PreviousDesiredRot, DesiredRot, DeltaTime, CameraRotationLagSpeed);
	}
	PreviousDesiredRot = DesiredRot;

	// Get the spring arm 'origin', the target we want to look at
	FVector ArmOrigin = GetComponentLocation() + TargetOffset;
	// We lag the target, not the actuall camera position, so rotating the camera around does not hav lag
	FVector DesiredLoc = ArmOrigin;
	if (bDoLocationLag)
	{
		DesiredLoc = FMath::VInterpTo(PreviousDesiredLoc, DesiredLoc, DeltaTime, CameraLagSpeed);
	}
	PreviousDesiredLoc = DesiredLoc;

	// Now offset camera position back along our rotation
	DesiredLoc -= DesiredRot.Vector() * TargetArmLength;
	// Add socket offset in local space
	DesiredLoc += FRotationMatrix(DesiredRot).TransformVector(SocketOffset);

	// Do a sweep to ensure we are not penetrating the world
	FVector ResultLoc;
	if (bDoTrace && (TargetArmLength != 0.0f))
	{
		static FName TraceTagName(TEXT("SpringArm"));
		FCollisionQueryParams QueryParams(TraceTagName, false, GetOwner());

		FHitResult Result;
		GetWorld()->SweepSingle(Result, ArmOrigin, DesiredLoc, FQuat::Identity, ProbeChannel, FCollisionShape::MakeSphere(ProbeSize), QueryParams);

		ResultLoc = BlendLocations(DesiredLoc, Result.Location, Result.bBlockingHit, DeltaTime);
	}
	else
	{
		ResultLoc = DesiredLoc;
	}

	// Form a transform for new world transform for camera
	FTransform WorldCamTM(DesiredRot, ResultLoc);
	// Convert to relative to component
	FTransform RelCamTM = WorldCamTM.GetRelativeTransform(ComponentToWorld);

	// Update socket location/rotation
	RelativeSocketLocation = RelCamTM.GetLocation();
	RelativeSocketRotation = RelCamTM.GetRotation();

	UpdateChildTransforms();
}