This website uses cookies to improve our services and deliver relevant ads.
By interacting with this site, you agree to this use. For more information, see our Cookies Policy
The Oculus Avatar SDK for Unreal Beta download file contains an Unreal Engine (UE) C++ sample project illustrating and implementing all the features available to Oculus Avatars in UE.
The example project demonstrates:
Oculus Avatars for UE are implemented as a plugin. Avatars are embodied within UOvrAvatar ActorComponents that you can attach to the UE actors you desire. This lets you keep your game-side code separate from our implementation of avatars.
Some of the files and folders in our example project and their primary functions include:You should see the hands of your avatar. This first person view is also called the local avatar.

The code that spawns your first-person avatar is in LocalAvatar.cpp:
ALocalAvatar::ALocalAvatar()
{
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("LocalAvatarRoot"));
PrimaryActorTick.bCanEverTick = true;
AutoPossessPlayer = EAutoReceiveInput::Player0;
BaseEyeHeight = 170.f;
AvatarComponent = CreateDefaultSubobject<UOvrAvatar>(TEXT("LocalAvatar"));
AvatarComponent->SetVisibilityType(ovrAvatarVisibilityFlag_FirstPerson);
AvatarComponent->SetPlayerHeightOffset(BaseEyeHeight / 100.f);
}Squeeze the right Touch trigger to spawn avatars in a circle around you. Squeeze the left Touch trigger to destroy them. These third-person avatars with hands, heads, and base cones are called remote avatars.
The remote avatars in this sample mimic your movements because we hooked them up to our avatar packet recording and playback system. This system records both your movements and your microphone amplitude, letting us transmit them to remote avatars and animate them accordingly. Speak or sing to see the voice animations on the remote avatars.

The packet recording is handled by ALocalAvatar::UpdatePacketRecording(float DeltaTime) in LocalAvatar.cpp.
Packet playback on remote avatars is handled by ARemoteAvatar::Tick in RemoteAvatar.cpp. You might notice a small delay in the response between your local avatar movements and the corresponding movement in the remote avatars. This is an artificial delay we added to the sample to simulate network latency.
To toggle packet recording and playback:
Press the thumbsticks to cycle through the following hand poses:
a built-in pose for gripping a sphere:
AvatarComponent->SetRightHandPose(ovrAvatarHandGesture_GripSphere);
a built-in pose for gripping a cube:
AvatarComponent->SetRightHandPose(ovrAvatarHandGesture_GripCube);
a custom hand gesture built from an array of joint transforms, gAvatarRightHandTrans:
AvatarComponent->SetCustomGesture(ovrHand_Right, gAvatarRightHandTrans, HAND_JOINTS);
a built-in pose depicting Touch controllers:
AvatarComponent->SetRightHandPose(ovrAvatarHandGesture_Default); AvatarComponent->SetControllerVisibility(ovrHand_Right, true);
The code snippets above are from LocalAvatar.cpp and set the poses for the right hand. For the left hand, substitute the appropriate left hand functions and constants.
Press Y on the left Touch or press B on the right Touch to detach the avatar hands from Touch tracking. You can then use the thumbsticks to drive the avatar hand movements.
The following code in LocalAvatar.cpp detaches the hands:
AvatarHands[ovrHand_Right] = AvatarComponent->DetachHand(ovrHand_Right);
ALocalAvatar::DriveHand drives the hand movement after detaching.
Copy the Plugins folder to the root folder of your project. It contains our OvrAvatar plugin.
Update your project's Config/DefaultInput.ini file with content from the sample project's Config/DefaultInput.ini file.
Update the Modules and Plugins sections of your .uproject file with additional items. Remember to add a comma (,) to the last item in any existing Modules or Plugins sections before pasting the additional lines:
"Modules": [
{
"AdditionalDependencies": [
"Engine",
"OnlineSubsystem",
"OnlineSubsystemUtils"
]
}
],
"Plugins": [
{
"Name": "OnlineSubsystemOculus",
"Enabled": true
},
{
"Name": "OvrAvatar",
"Enabled": true
}
]Update your project's Config/DefaultEngine.ini file with the following:
[OnlineSubsystem]
DefaultPlatformService=Oculus
[OnlineSubsystemOculus]
bEnabled=true
OculusAppId=YOUR_APP_IDGet YOUR_APP_ID from the Oculus Developer Dashboard: https://dashboard.oculus.com
In your code, the local user actor must implement the SetupPlayerInputComponent function, as the component needs controller input sent to it to animate the hands properly. A set of macros define these repetitive functions. Two things to consider are that:
You also need to replace the ALocalAvatar:: entries with the name of your own Actor class.
// LocalAvatar.cpp
void ALocalAvatar::SetupPlayerInputComponent(UInputComponent* Input)
{
Super::SetupPlayerInputComponent(Input);
#define INPUT_ENTRY(entry, hand, flag) \
Input->BindAction(#entry, IE_Pressed, this, &ALocalAvatar::##entry##_Pressed); \
Input->BindAction(#entry, IE_Released, this, &ALocalAvatar::##entry##_Released);
INPUT_COMMAND_TUPLE
#undef INPUT_ENTRY
#define AXIS_ENTRY(entry, hand, flag) \
Input->BindAxis(#entry, this, &ALocalAvatar::##entry##_Value);
AXIS_INPUT_TUPLE
#undef AXIS_ENTRY
#define CUSTOM_ENTRY(entry, hand, field, invert) \
Input->BindAxis(#entry, this, &ALocalAvatar::##entry##_Value);
CUSTOM_AXIS_TUPLE
#undef CUSTOM_ENTRY
}
#define CUSTOM_ENTRY(entry, hand, field, invert) \
void ALocalAvatar::##entry##_Value(float value) { AvatarComponent->##entry##_Value(value); }
CUSTOM_AXIS_TUPLE
#undef CUSTOM_ENTRY
#define INPUT_ENTRY(entry, hand, flag) \
void ALocalAvatar::##entry##_Pressed() { AvatarComponent->##entry##_Pressed();}\
void ALocalAvatar::##entry##_Released() { AvatarComponent->##entry##_Released(); }
INPUT_COMMAND_TUPLE
#undef INPUT_ENTRY
#define AXIS_ENTRY(entry, hand, flag) \
void ALocalAvatar::##entry##_Value( float value) { AvatarComponent->##entry##_Value(value); }
AXIS_INPUT_TUPLE
#undef AXIS_ENTRYNote in LocalAvatar.h where these functions are declared:
private:
#define INPUT_ENTRY(entry, hand, flag) \
void entry##_Pressed();\
void entry##_Released();
INPUT_COMMAND_TUPLE
#undef INPUT_ENTRY
#define AXIS_ENTRY(entry, hand, flag) \
void entry##_Value( float value);
AXIS_INPUT_TUPLE
#undef AXIS_ENTRY
#define CUSTOM_ENTRY(entry, hand, field, invert) \
void entry##_Value( float value);
CUSTOM_AXIS_TUPLE
#undef CUSTOM_ENTRYPlace your request to fetch the avatar wherever you have set up online login functionality. For example:
void ALocalAvatar::OnLoginComplete(int32 LocalUserNum, bool bWasSuccessful, const FUniqueNetId& UserId, const FString& Error)
{
IOnlineIdentityPtr OculusIdentityInterface = Online::GetIdentityInterface();
OculusIdentityInterface->ClearOnLoginCompleteDelegate_Handle(0, OnLoginCompleteDelegateHandle);
if (AvatarComponent)
{
AvatarComponent->RequestAvatar(10149999027226798);
}
}