Client
.NET/Unity C++/Unreal/Cocos2d-x JavaScript/Cocos2d-js Godot 3 Godot 4 Java/Android Defold cURL REST Swift Dart/Flutter
Server
TypeScript Go Lua
Challenges
# Challenges enable social and competitive experiences by allowing players to compete in time-bound events with friends. Learn more in the Challenges concept guide .
Overview
# Challenges provide time-bound competitive experiences where players can:
Compete against friends or other players Track progress through leaderboards Earn rewards for participation and performance Prerequisites
# Unreal project set up with Hiro SDK Nakama System integrated Managing Challenges
# Creating a Challenge
# Create new challenges with custom parameters:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FHiroChallengeCreateRequest CreateRequest ;
CreateRequest . TemplateId = TEXT ( "daily_race" );
CreateRequest . Name = TEXT ( "Daily Race Challenge" );
CreateRequest . Description = TEXT ( "Compete for top daily times" );
CreateRequest . Invitees = { TEXT ( "player2" ), TEXT ( "player3" ) };
CreateRequest . Open = true ;
CreateRequest . MaxScores = 3 ;
CreateRequest . StartDelaySec = 0 ; // Start immediately
CreateRequest . DurationSec = 86400 ; // 24 hours
CreateRequest . MaxParticipants = 10 ;
CreateRequest . Category = TEXT ( "racing" );
FHiroOnChallengeCreate OnChallengeCreate ;
OnChallengeCreate . AddDynamic ( this , & AMyActor :: OnChallengeCreate );
FOnError OnError ;
HiroClient -> ChallengeCreate ( Session , CreateRequest , OnChallengeCreate , OnError );
void AMyActor :: OnChallengeCreate ( const FHiroChallenge & Challenge )
{
UE_LOG ( LogTemp , Log , TEXT ( "%s" ), * Challenge . ToJson ());
}
Parameters:
Open
: Allow any player to join without an invitationMaxScores
: Max submissions per playerDurationSec
: 0 = unlimited durationListing Challenges
# Get active challenges with optional filtering:
1
2
3
4
5
6
7
8
9
FHiroChallengeListRequest Request ;
Request . Categories . Add ( TEXT ( "racing" ));
Request . WithScores = true ;
FHiroOnChallengesList OnChallengesList ;
OnChallengesList . AddDynamic ( this , & AMyActor :: OnChallengesList );
FOnError OnError ;
HiroClient -> ChallengesList ( Session , Request , OnChallengesList , OnError );
Searching Challenges
# Find public challenges by name/category:
1
2
3
4
5
6
7
8
9
10
FHiroChallengeSearchRequest SearchRequest ;
SearchRequest . Name = TEXT ( "weekly" );
SearchRequest . Category = TEXT ( "racing" );
SearchRequest . Limit = 5 ;
FHiroOnChallengesSearch OnChallengesSearch ;
OnChallengesSearch . AddDynamic ( this , & AMyActor :: OnChallengesSearch );
FOnError OnError ;
HiroClient -> ChallengesSearch ( Session , SearchRequest , OnChallengesSearch , OnError );
Inviting Players
# Add participants to existing challenges:
1
2
3
4
5
6
7
8
9
FHiroChallengeInviteRequest InviteRequest ;
InviteRequest . ChallengeId = TEXT ( "CHALLENGE_123" );
InviteRequest . Invitees = { TEXT ( "player4" ) };
FHiroOnChallengeInvite OnChallengeInvite ;
OnChallengeInvite . AddDynamic ( this , & AMyActor :: OnChallengeInvite );
FOnError OnError ;
HiroClient -> ChallengeInvite ( Session , InviteRequest , OnChallengeInvite , OnError );
Tracking Progress
# Submitting Scores
# Update player standings in a challenge:
1
2
3
4
5
6
7
8
9
10
11
FHiroChallengeSubmitScoreRequest SubmitScoreRequest ;
SubmitScoreRequest . ChallengeId = TEXT ( "CHALLENGE_123" );
SubmitScoreRequest . Score = 1500 ;
SubmitScoreRequest . Subscore = 0 ;
SubmitScoreRequest . Metadata = TEXT ( "{ \" lap_times \" :[120]}" );
FHiroOnChallengeSubmitScore OnSubmitScore ;
OnSubmitScore . AddDynamic ( this , & AMyActor :: OnSubmitScore );
FOnError OnError ;
HiroClient -> ChallengeSubmitScore ( Session , SubmitScoreRequest , OnSubmitScore , OnError );
Joining/Leaving
# Manage player participation:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Join an open challenge
FHiroChallengeJoinRequest JoinRequest ;
JoinRequest . ChallengeId = TEXT ( "CHALLENGE_456" );
FHiroOnChallengeJoin OnChallengeJoin ;
OnChallengeJoin . AddDynamic ( this , & AMyActor :: OnChallengeJoin );
FOnError OnError ;
HiroClient -> ChallengeJoin ( Session , JoinRequest , OnChallengeJoin , OnError );
// Leave a challenge
FHiroChallengeLeaveRequest LeaveRequest ;
LeaveRequest . ChallengeId = TEXT ( "CHALLENGE_456" );
FHiroOnChallengeLeave OnChallengeLeave ;
OnChallengeLeave . AddDynamic ( this , & AMyActor :: OnChallengeLeave );
HiroClient -> ChallengeLeave ( Session , LeaveRequest , OnChallengeLeave , OnError );
Rewards
# Claiming Rewards
# Claim earned rewards after challenge completion:
1
2
3
4
5
6
7
8
9
10
11
FHiroChallengeClaimRequest ClaimRequest ;
ClaimRequest . ChallengeId = TEXT ( "CHALLENGE_123" );
FHiroOnChallengeClaim OnChallengeClaim ;
OnChallengeClaim . AddDynamic ( this , & AMyActor :: OnChallengeClaim );
FOnError OnError ;
HiroClient -> ChallengeClaim ( Session , ClaimRequest , OnChallengeClaim , OnError );
// Refresh the economy system to see new rewards
HiroClient -> EconomyRefresh ( Session , OnEconomyRefresh , OnError );