Assignment Goals

The primary goals of this assignment are:

  1. Use a template code project.
  2. Extend an Unreal Engine Pawn with C++ code to add behavior.
  3. Use delegate functions to set up collision response.

For this assignment, you'll be creating C++ Pawn, which is Unreal's base class for anything that can be controlled by either a user or AI in a scene. Your pawn will be a rolling ball following a simple boid behavioral model. You'll use an expanded collision volume to detect other nearby boids, and based on their positions and velocities attempt to follow the avoidance, alignment and cohesion rules. There will also be one user-controlled pawn that you can use to influence flock behavior.

Details

Once again, this assignment leaves a little more of function discovery and engine navigation to you as compared to the previous assignments.

Create a project

  1. This time, create a C++ project using the Top Down template (with no starter content) called assn3, at the top level of your git repository.
  2. This project already has a C++ character pawn, with a Blueprint pawn derived from it solely for parameter tweaking. Look at its code in assn3Character.h and assn3Character.cpp.

C++ pawn

  1. Create a new C++ pawn.
  2. Give it a UStaticMeshComponent, and initialize it with the SM_Ball_01 mesh from the Engine content.
  3. UStaticMeshComponent is derived from USceneComponent, so set the static mesh as your RootComponent.
  4. Set the scale to 0.5 so the balls won't be quite as big.
  5. Turn on physics by calling SetSimulatePhysics(true) on the static mesh component. It inherits this from uPrimitiveComponent. Look there for more physics functions.
  6. You'll also need to set the static mesh component's collision profile to UCollisionProfile::PhysicsActor_ProfileName.
  7. So the balls will eventually stop rolling, set the linear and angular damping to 0.1.
  8. At this point, you can add one or more balls to your scene and kick them around.

Neighbors

  1. Tracking neighborhood
    • Add a new USphereComponent to detect nearby neighbors.
    • Add a radius parameter set to EditAnywhere. I found a radius of about 500 to work well.
    • Add an OnConstruction function to resize the sphere if the radius changes.
  2. Neighbor set
    • Create a TSet<APawn*> in your AI pawn to hold the list of neighboring pawns that overlap your USphereComponent.
    • This is transient data, and should not be serialized with your pawn.
      • You can just not mark it as a UPROPERTY at all.
      • If you want to make it visible for debugging, mark it UPROPERTY(VisibleAnywhere,Transient).
  3. Neighbor tracking
    • Create OnComponentBeginOverlap and OnComponentEndOverlap delegate functions to add pawns to the set as they come in range, and remove them when they leave.
    • You can find the signature for these in delegate declarations in PrimitiveComponent.h.
    • Register them with the USphereComponent using AddDynamic() in your AI Pawn's constructor.
    • You can find a few examples creating and registering ComponentBeginOverlap delegate functions in the engine code.
    • Note that each AI pawn will also register as overlapping itself (since the neighbor-detecting sphere and physical sphere overlap). Check if the "Other" Actor in the overlap function is equal to this to avoid adding yourself to your own neighbors list.
  4. Follow player
    • Add the player pawn to every boid pawn's neighbor list and make sure it's not removed even when the player leaves the boid's neighborhood.
    • Since the player is only added to the scene on play, you can find it using UGameplayStatics::GetPlayerPawn

Neighbor forces

  1. In your AI Pawn Tick() function, loop through the pawns in the TSet to drive the AI pawn direction.
  2. Add UPROPERTY's to your pawn class to control the strength of the forces: Cohesion, Avoidance, and Alignment.
    • You will need to tune these individually. Too small, and you won't get any motion at all. Too large, and the balls will fly off of the map. Increase by factors of 10 until you start to see some motion.
    • The scales may vary enormously. Include an extra scale multiplier for each in the Tick function code so the user-tweakable coefficients make sense in a range of about 0-50.
  3. Use AddForce() to apply the forces
    • Add the forces one at a time to debug the force direction and scale.
  4. For cohesion, apply a force toward the average position of all of the neighbors.
  5. For the avoidance force, scale the vector to each neighbor by 1/distance so the closest pawn will push hardest.
  6. For alignment, apply a force in the direction of the difference between the average velocity of the neighbors and your velocity.

Grad Students

Use an AI Controller class instead of having all of the behavior in the Pawn.

Submission

  1. For full credit, you must have multiple incremental commits during your development.
  2. Record a video of the player pawn interacting with at least a dozen AI balls. Put the video somewhere like google drive, box, or youtube (not checked directly into your repository).
  3. Add an assn3.txt. Tell us what works and what doesn't, and anything else you think we should know for grading. Include a link to video demonstrating your project.
  4. Push to your repository, and tag your final commit with an assn3 tag (git tag assn3 followed by git push origin assn3).