Video: Procedural Animation And AI, by Rama
It’s me Rama!
As you know I am working with Devero on Abatron, it’s a lot of fun!
**A Replicating Procedurely-Animated Flying Character With AI**
I wanted to walk you through one way you can do procedural animation in combination with AI in UE4!
See my video below for a demonstration of what I mean!
The entire animation and movement of the flying creature is procedural / AI !
There are no animations for this creature at all, other than 9 still poses!
Yet see how I can completely animate the flying creature by blending the aim offsets from my C++ AI code!
And as you can see in the video, my procedural animation system replicates to the client smoothly!
I use **interploation **to smoothly update the client creature's rotations to match the rotations being sent from the server!
Rama’s Procedurally Animated Flying AI Creature
I was given a static mesh of a flying creature looking straight ahead, and did the following:
1. Rigged the creature in 3ds max, doing all the manual bone weighting myself
2. Made 9 poses to serve as aim offsets for a blendspace
3. Brought the creature into UE4, setting up the blend space, the custom C++ anim instance, and imported the 9 pose animations
4. Wrote all the C++ to utilize the aim offsets in code and give the creature AI to move around to adjust itself to be able to always look at its target.
One of the key things to note is that I am updating the Animation Blueprint from C++ using a custom AnimInstance class!
Rigging in 3ds Max
If you’d like to do something like this for your own project, I can explain the 3ds max steps!
I used a simple bone chain, refined the bone weighting myself after using envelopes, and then made 9 poses!
As I made each pose and improved the vertex weighting, I reverted the bone chain to straight to update the neutral pose with the most recent vertex weighting info.
Bone Chain 1
Bone Chain 2
**C++ Code Sample**
Below I have included my main engine that controls how my procedurally animated creature works
It goes like this basically
1. if the target is too far away, the AI unit should move closer
2. if the target location is directly above/below the AI unit, AI unit should back up
3. if 1 and 2 work, check and see if the AI unit needs to change rotation to face target
4. if 1-3 work, then update the AI unit's aim offsets via custom C++ anim instance!
5. when #4 happens, send the updates over the network to all clients and have the clients smoothly interpolate to the new net am offset rotations.
**//Tracked Location! This is the Player Unit's location!**
FVector TrackedLocation = Tracking_GetTrackedLocation();
**//Is the location too far?**
const FVector EyeLocation = Mesh->GetSocketLocation("Tip"); **//EYE SOCKET**
**//Using Square Dist checks as they are more cpu efficient
// and these checks run every tick that the unit is doing tracking**
FVector(TrackedLocation.X,TrackedLocation.Y,0), **//discount Z**
) > MovePosition_TargetIsTooFarDistance * MovePosition_TargetIsTooFarDistance)
Tracking_TargetTooFar = true;
Tracking_TargetTooFar = false;
Location Under Ship?
FRotator AngleToShipCenter = UVictoryCore::StandardizeRotator((GetActorLocation() - TrackedLocation).Rotation());
**//Is the pitch angle from ship center to tracked unit too big?**
const float PitchToShip = FMath::Abs(AngleToShipCenter.Pitch);
if( PitchToShip >= MovePosition_AngleToShipMaxAllowedPitchBeforeMove)
Tracking_NeedToMove = true;
**//Using a bone further from head for better interp stability**
FVector StableBonePos = Mesh->GetSocketLocation("Bone011");
FRotator AngleTo = UVictoryCore::StandardizeRotator(
(TrackedLocation - StableBonePos).Rotation()
**//~~~ Get Local Space Rot of New Proposed Angle ~~~**
FVector AngleToDir = AngleTo.Vector();
AngleToDir = ActorToWorld().InverseTransformVectorNoScale(AngleToDir);
FRotator ActorSpaceRot = AngleToDir.Rotation();
**//Creature should adjust position!
// unit is too close or too far!**
if(FMath::Abs(ActorSpaceRot.Pitch) > 80)
Tracking_NeedToMove = true;
if(FMath::Abs(ActorSpaceRot.Yaw) > 80 )
**//Dont update if yaw is too big!
// Turn to face the player's unit!**
Tracking_NeedToTurn = true;
Tracking_NeedToMove = false;
**//Pass the new rotation to all clients!
// and update aim offsets!**