AVI

My website code stuff


Project maintained by Locust0 Hosted on GitHub Pages — Theme by mattgraham

HOME


Converting a blueprint to C++

November 13, 2018

This week I converted some blueprint visual scripting to actual C++ code. There’re a few reasons why you’d want to do this, mainly:

Visual Scripting

First up, here’s a look at my “lookingAt” function built with visual scripting (note this is basically the same as the blueprint I showed from earlier):

Image

Here’s a quick refresher on exactly what’s happening:

Basically, starting from the left, I grab the camera. I extract its position and forward vector. Its forward vector is multiplied by 1000 (to cover what’s in front of us) then added to the starting position. This creates our starting and ending positions for the vector trace. From there I do the vector cast with that giant function. Next I take what that raycast hit and break it up into only the actor we hit (if any). Finally, I assign the variable lookingAt to whatever actor we hit and if we didn’t hit anything, it becomes null.

C++ Code

First up, Unreal has a weird requirement that every function in a class explicitly refer to the class it’s a part of, in this case: ADruidCharacter.

void ADruidCharacter::LookingAt()
{

Next, we’ve got two empty variables, hit stores the result of the raycast and collisionParams is just there to act as the default parameters for the raycast.

  // Stores what we hit
  FHitResult hit;
  // Stores the parameters needed for the raycast
  FCollisionQueryParams collisionParams;

Next we assign UCamera which is the camera component. The U prefix denotes the fact that the CameraComponet is a subclass of ActorComponent (Documentation).

  // Our camera component
  UCameraComponent *UCamera = this->FindComponentByClass<UCameraComponent>();

Now we assign ACamera which is the Actor UCamera is attached to. The A prefix denotes a subclass of Actor (or in the case, just Actor) (Documentation).

  // Camera's owner (us)
  AActor *ACamera = UCamera->GetOwner();

Next we find the starting location for the raycast, the position of the camera.

  // Start at our location
  FVector start = ACamera->GetActorLocation();

The ending location is found the same way, with the forward vector of the camera component * 1000 + the starting location.

  // End at where we are looking plus our location
  FVector end = (UCamera->GetForwardVector() * 1000) + start;

There’s a green debugging line draw here to make sure everything works.

  // Debug line drawing
  DrawDebugLine(GetWorld(), start, end, FColor::Green, false, 0.1, 0, 1)

Now we cast the actual ray from start to end. It outputs to the variable hit and also needs collisionParams as an input despite it being basically empty.

  // Actual line cast
  if (GetWorld()->LineTraceSingleByChannel(hit, start, end, 
    ECC_Visibility, collisionParams))

The inside of the if statement activates on any hit, so we first need to make sure we hit something actually solid. If we did, we then assign lookingAt to the Actor we hit. Otherwise, it’s set to nullptr. Additionally, if the raycast completely failed to hit anything, the bottom else statement catches that and assigns lookingAt to still be null. Note that Unreal uses nullptr instead of NULL for performance reasons.

  {
    // If we hit something solid
    if (hit.bBlockingHit)
      lookingAt = hit.GetActor();
    else
      lookingAt = nullptr;
  }
  else
    lookingAt = nullptr;
}

Conclusion

The general workflow for designing new features in Unreal tends to involve first prototyping with blueprints and then actually coding to ensure speed.

Next I’ll be figuring how to make interactable objects glow when looked at. I already have a shader which will work and a way to tell that object its being looked at, but I don’t know how to access its shader or affect those shader’s parameters.

After that I’ll be adding a new class of interactable objects - trees. These should freeze the player and change their position to inside of themselves when interacted with. Basically, so you can “merge” with the tree. From inside, you should be able to exit in any direction or transfer to another nearby tree.


HOME