Put it all together - Challenge - (Unity module)
Connect the UI to display challenges
-
Open the
ChallengeEntry_Starter
class and declare the variable below to reference the wrapper you created earlier.private ChallengeEssentialsWrapper_Starter challengeWrapper;
-
Then, add the code below to the predefined
OnEnable()
function to assign the wrapper reference when the menu entry is instantiated.private void OnEnable()
{
challengeWrapper ??= TutorialModuleManager.Instance.GetModuleClass<ChallengeEssentialsWrapper_Starter>();
} -
Create the function below to set up the menu entry by displaying the challenge goal information.
public void Setup(ChallengeGoalData goal)
{
ChallengeGoalMeta meta = goal.Meta;
GoalProgressionInfo progress = goal.Progress;
bool isRewardClaimed = (progress.ToClaimRewards?.Length ?? 0) <= 0;
bool isNotStarted = progress.Status.ToLower() == ChallengeGoalProgressStatus.Not_Started.ToString().ToLower();
bool isCompleted = progress.Status.ToLower() == ChallengeGoalProgressStatus.Completed.ToString().ToLower();
// Display basic information.
goalText.text = meta.Name;
remainingTimeText.text = goal.EndTimeDuration;
statusCheckBox.isOn = isCompleted;
// Display rewards.
rewardPanel.DestroyAllChildren();
foreach (ChallengeGoalRewardData reward in goal.Rewards)
{
Instantiate(rewardEntryPrefab, rewardPanel).GetComponent<ChallengeGoalRewardEntry>().Setup(reward);
}
// Set up claim reward button.
claimButton.text.text = isRewardClaimed ? ClaimedChallengeRewardLabel : ClaimableChallengeRewardLabel;
claimButton.button.enabled = !isRewardClaimed;
claimButton.button.onClick.RemoveAllListeners();
claimButton.button.onClick.AddListener(() => OnClaimButtonClicked(goal));
/* Select the progress with the highest progress value, as Byte Wars displays only one.
* If there is no player progress, set the default goal progress value from the requirement group.
* Otherwise, use the actual player progress value. */
int currentProgress = 0, targetProgress = 0;
if (isNotStarted)
{
ChallengePredicate predicate = progress.Goal.RequirementGroups
.SelectMany(x => x.Predicates)
.OrderByDescending(x => x.TargetValue)
.FirstOrDefault();
targetProgress = (int?)(predicate?.TargetValue) ?? 0;
}
else
{
ChallengeRequirementProgressionResponse requirement = progress.RequirementProgressions
.OrderByDescending(x => x.CurrentValue)
.FirstOrDefault();
currentProgress = (int?)(requirement?.CurrentValue) ?? 0;
targetProgress = (int?)(requirement?.TargetValue) ?? 0;
}
progressText.text = $"{currentProgress}/{targetProgress}";
// Display progress if not completed; otherwise, show the claim reward button.
progressText.gameObject.SetActive(!isCompleted);
claimButton.gameObject.SetActive(isCompleted);
} -
Next, create the function below to claim the challenge goal rewards by calling the function from the wrapper you created.
private void OnClaimButtonClicked(ChallengeGoalData goal)
{
// Abort if there are no rewards to claim.
if (goal.Progress.ToClaimRewards == null)
{
MenuManager.Instance.ShowInfo(EmptyClaimableChallengeRewardMessage, "Error");
return;
}
// Collect claimable reward IDs.
List<string> claimableRewardIDs = goal.Progress.ToClaimRewards.Select(x => x.Id).ToList();
// Claim rewards.
claimButton.button.enabled = false;
claimButton.text.text = ClaimingChallengeRewardLabel;
challengeWrapper.ClaimChallengeGoalRewards(claimableRewardIDs, (Result result) =>
{
claimButton.button.enabled = result.IsError;
claimButton.text.text = result.IsError ? ClaimableChallengeRewardLabel : ClaimedChallengeRewardLabel;
if (result.IsError)
{
MenuManager.Instance.ShowInfo(result.Error.Message, "Error");
}
});
} -
Open the
ChallengeMenu_Starter
class and declare the variable below to reference the wrapper you created earlier.private ChallengeEssentialsWrapper_Starter challengeWrapper;
-
Then, replace the code in the predefined
OnEnable()
function with the code below. Now, this function will assign the wrapper reference and use it to get and display the challenge goal list.private void OnEnable()
{
// Set menu title based on the selected challenge period.
challengeTitleText.text =
ChallengePeriodMenu.SelectedPeriod == ChallengeRotation.None ?
AllTimeChallengeTitleLabel :
string.Format(PeriodicChallengeTitleLabel, ChallengePeriodMenu.SelectedPeriod.ToString());
// Get and display the challenge goal list.
challengeWrapper ??= TutorialModuleManager.Instance.GetModuleClass<ChallengeEssentialsWrapper_Starter>();
if (challengeWrapper)
{
GetChallengeGoalList();
}
} -
Next, replace the
GetChallengeGoalList()
function with the code below. This implementation uses the wrapper you created to retrieve the challenge by period, and then uses its challenge code to get and display the list of goals.private void GetChallengeGoalList()
{
widgetSwitcher.SetWidgetState(AccelByteWarsWidgetSwitcher.WidgetState.Loading);
// Get challenge by period.
challengeWrapper.GetChallengeByPeriod(
ChallengePeriodMenu.SelectedPeriod,
(Result<ChallengeResponseInfo> infoResult) =>
{
if (infoResult.IsError)
{
widgetSwitcher.ErrorMessage = infoResult.Error.Message;
widgetSwitcher.SetWidgetState(AccelByteWarsWidgetSwitcher.WidgetState.Error);
return;
}
// Get and display the challenge goal list.
int rotationIndex = 0; // Zero indicates the current and latest active challenge rotation.
challengeWrapper.GetChallengeGoalList(
infoResult.Value,
(Result<List<ChallengeGoalData>> goalsResult) =>
{
if (goalsResult.IsError)
{
widgetSwitcher.ErrorMessage = goalsResult.Error.Message;
widgetSwitcher.SetWidgetState(AccelByteWarsWidgetSwitcher.WidgetState.Error);
return;
}
if (goalsResult.Value.Count <= 0)
{
widgetSwitcher.SetWidgetState(AccelByteWarsWidgetSwitcher.WidgetState.Empty);
return;
}
// Display challenge goal entries.
challengeListPanel.DestroyAllChildren();
foreach (ChallengeGoalData goal in goalsResult.Value)
{
Instantiate(challengeEntryPrefab, challengeListPanel).Setup(goal);
}
widgetSwitcher.SetWidgetState(AccelByteWarsWidgetSwitcher.WidgetState.Not_Empty);
},
rotationIndex);
});
}
Resources
-
The files used in this tutorial section are available in the Unity Byte Wars GitHub repository.