Creating events that can be implemented in Blueprint

Another way that C++ can be more tightly integrated with Blueprint is the creation of functions that can have Blueprint implementations in native code. This allows for a programmer to specify an event, and invoke it, without needing to know anything about the implementation. The class can then be subclassed in Blueprint, and another member of the production team can implement a handler for the event without ever having to go near a line of C++.

How to do it…

  1. Create a new StaticMeshActor class called Spotter.
  2. Make sure the following functions are defined and overridden in the class header:
    virtual void Tick( float DeltaSeconds ) override;
    UFUNCTION(BlueprintImplementableEvent)
    void OnPlayerSpotted(APawn* Player);
  3. Add this code to the constructor:
    PrimaryActorTick.bCanEverTick = true;
    auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(TEXT("StaticMesh'/Engine/BasicShapes/Cone.Cone'"));
    if (MeshAsset.Object != nullptr)
    {
      GetStaticMeshComponent()->SetStaticMesh(MeshAsset.Object);
      GetStaticMeshComponent()->bGenerateOverlapEvents = true;
    }
    GetStaticMeshComponent()->SetMobility(EComponentMobility::Movable);
    GetStaticMeshComponent()->SetRelativeRotation(FRotator(90, 0, 0));
  4. Add this to the Tick function:
    Super::Tick( DeltaTime );
    
    auto EndLocation = GetActorLocation() + ActorToWorld().TransformVector(FVector(0,0,-200));
    FHitResult HitResult;
    GetWorld()->SweepSingleByChannel(HitResult, GetActorLocation(), EndLocation, FQuat::Identity, ECC_Camera, FCollisionShape::MakeSphere(25), FCollisionQueryParams("Spot", true, this));
    APawn* SpottedPlayer = Cast<APawn>(HitResult.Actor.Get());
    
    if (SpottedPlayer!= nullptr)
    {
      OnPlayerSpotted(SpottedPlayer);
    }
    DrawDebugLine(GetWorld(), GetActorLocation(), EndLocation, FColor::Red);
  5. Compile and start the editor. Find your Spotter class in Content Browser, then left-click and drag a copy out into the game world.
  6. When you play the level, you'll see the red line showing the trace that the Actor is performing. However, nothing will happen, because we haven't implemented our OnPlayerSpotted event.
  7. In order to implement this event, we need to create a blueprint subclass of our Spotter.
  8. Right-click on Spotter in Content Browser, and select Create Blueprint class based on Spotter. Name the class BPSpotter.
    How to do it…
  9. Inside the Blueprint editor, click on the Override button in the Functions section of the My Blueprint panel:
    How to do it…
  10. Select On Player Spotted:
    How to do it…
  11. Left-click and drag from the white execution pin on our event. In the context menu that appears, select and add a Print String node so that it is linked to the event.
    How to do it…
  12. Play the level again, and verify that walking in front of the trace that the Spotter is using now prints a string to the screen.
    How to do it…

How it works…

  1. In the constructor for our Spotter object, we load one of the basic primitives, a cone, into our Static Mesh Component as a visual representation.
  2. We then rotate the cone so that it resembles a spotlight pointing to the X axis of the actor.
  3. During the Tick function, we get the actor's location, and then find a point 200 units away from the actor along its local X axis. We call the parent class implementation of Tick using Super:: to ensure that any other tick functionality is preserved despite our override.
  4. We convert a local position into a world space position by first acquiring the Actor-to-World transform for the Actor, then using that to transform a vector specifying the position.
  5. The transform is based on the orientation of the root component, which is the static mesh component that we rotated during the constructor.
  6. As a result of that existing rotation, we need to rotate the vector we want to transform. Given that we want the vector to point out of what was the bottom of the cone, we want a distance along the negative up axis, that is, we want a vector of the form (0,0,-d), where d is the actual distance away.
  7. Having calculated our end location for our trace, we actually perform the trace with the SweepSingleByChannel function.
  8. Once the sweep is performed, we try to cast the resulting hit Actor into a pawn.
  9. If the cast was successful, we invoke our Implementable Event of OnPlayerSpotted, and the user-defined Blueprint code executes.
..................Content has been hidden....................

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