Creating an OrbitingMovement Component

This component is similar to RotatingMovementComponent in that it is designed to make the components parented to it move in a particular way. In this instance, it will move any attached components in an orbit around a fixed point at a fixed distance.

This could be used, for example, for a shield that orbits around a character in an Action RPG.

How to do it...

  1. Create a new SceneComponent subclass and add the following properties to the class declaration:
    UPROPERTY()
    bool RotateToFaceOutwards;
    UPROPERTY()
    float RotationSpeed;
    UPROPERTY()
    float OrbitDistance;
    float CurrentValue;
  2. Add the following to the constructor:
    RotationSpeed = 5;
    OrbitDistance = 100;
    CurrentValue = 0;
    RotateToFaceOutwards = true;
  3. Add the following code to the TickComponent function:
    float CurrentValueInRadians = FMath::DegreesToRadians<float>(CurrentValue);
    SetRelativeLocation(FVector(OrbitDistance * FMath::Cos(CurrentValueInRadians), OrbitDistance * FMath::Sin(CurrentValueInRadians), RelativeLocation.Z));
    if (RotateToFaceOutwards)
    {
      FVector LookDir = (RelativeLocation).GetSafeNormal();
      FRotator LookAtRot = LookDir.Rotation();
      SetRelativeRotation(LookAtRot);
    }
    CurrentValue = FMath::Fmod(CurrentValue + (RotationSpeed* DeltaTime) ,360);
  4. Verify your work against the following listing:
    #pragma once
    #include "Components/SceneComponent.h"
    #include "OrbitingMovementComponent.generated.h"
    
    UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
    class UE4COOKBOOK_API UOrbitingMovementComponent : public USceneComponent
    {
      GENERATED_BODY()
      public:
      // Sets default values for this component's properties
      UOrbitingMovementComponent();
    
      // Called when the game starts
      virtual void BeginPlay() override;
      // Called every frame
      virtual void TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) override;
    
      UPROPERTY()
      bool RotateToFaceOutwards;
      UPROPERTY()
      float RotationSpeed;
      UPROPERTY()
      float OrbitDistance;
      float CurrentValue;
    };
    #include "UE4Cookbook.h"
    #include "OrbitingMovementComponent.h"
    // Sets default values for this component's properties
    UOrbitingMovementComponent::UOrbitingMovementComponent()
    {
      // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
      // off to improve performance if you don't need them.
      bWantsBeginPlay = true;
      PrimaryComponentTick.bCanEverTick = true;
      RotationSpeed = 5;
      OrbitDistance = 100;
      CurrentValue = 0;
      RotateToFaceOutwards = true;
      //...
    }
    
    // Called when the game starts
    void UOrbitingMovementComponent::BeginPlay()
    {
      Super::BeginPlay();
      //...
    }
    // Called every frame
    void UOrbitingMovementComponent::TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )
    {
      Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
      float CurrentValueInRadians = FMath::DegreesToRadians<float>(CurrentValue);
      SetRelativeLocation(
      FVector(OrbitDistance * FMath::Cos(CurrentValueInRadians),
      OrbitDistance * FMath::Sin(CurrentValueInRadians),
      RelativeLocation.Z));
      if (RotateToFaceOutwards)
      {
        FVector LookDir = (RelativeLocation).GetSafeNormal();
        FRotator LookAtRot = LookDir.Rotation();
        SetRelativeRotation(LookAtRot);
      }
      CurrentValue = FMath::Fmod(CurrentValue + (RotationSpeed* DeltaTime) ,360);
      //...
    }
  5. You can test this component by creating a simple Actor Blueprint.
  6. Add an OrbitingMovement Component to your Actor, then add a few meshes using the Cube component. Parent them to the OrbitingMovement component by dragging them on to it in the Components panel. The resulting hierarchy should look like the following:
    How to do it...
  7. Refer to the Creating a custom Actor Component recipe if you're unsure of the process.
  8. Hit play to see the meshes moving around in a circular pattern around the center of the Actor.

How it works...

  1. The properties that are added to the component are the basic parameters that we use to customize the circular motion of the component.
  2. RotateToFaceOutwards specifies whether the component will orient to face away from the center of rotation on every update. RotationSpeed is the number of degrees the component rotates every second.
  3. OrbitDistance indicates the distance that the components that rotate must be moved from the origin. CurrentValue is the current rotation position in degrees.
  4. Inside our constructor, we establish some sane defaults for our new component.
  5. In the TickComponent function, we calculate the location and rotation of our component.
  6. The formula in the next step requires our angles to be expressed in radians rather than degrees. Radians describe an angle in terms of π. We first use the DegreesToRadians function to convert our current value in degrees to radians.
  7. The SetRelativeLocation function uses the general equation for circular motion, that is—Pos(θ) = cos(θ in radians), sin(θ in radians). We preserve the Z axis position of each object.
  8. The next step is to rotate the object back towards the origin (or else, directly away from it). This is only calculated if RotateToFaceOutwards is true, and involves getting the relative offset of the component to its parent, and creating a rotator based on a vector pointing from the parent to the current relative offset. We then set the relative rotation to the resulting rotator.
  9. Lastly, we increment the current value in degrees so that it moves RotationSpeed units per second, clamping the resulting value between 0 and 360 to allow the rotation to loop.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.157.39