HUD UI Groups

Announcements, support questions, and discussion for Quest Machine.
dlevel
Posts: 150
Joined: Wed Nov 16, 2016 6:17 pm

HUD UI Groups

Post by dlevel »

Hey,

I see there is a Use Groups in Unity UI Quest HUD component but the Quest Group Template is empty (using the demo), so nothing changes in the hud, is there a group hud template I can check this feature with? Or what are the specs if I have to create one? thanks

Image: https://ibb.co/nwgYhZr
User avatar
Tony Li
Posts: 21636
Joined: Thu Jul 18, 2013 1:27 pm

Re: HUD UI Groups

Post by Tony Li »

Hi,

Make sure you've assigned your quests' Group fields and that your HUD has a template UI assigned for groups.
dlevel
Posts: 150
Joined: Wed Nov 16, 2016 6:17 pm

Re: HUD UI Groups

Post by dlevel »

Yeap that was it, I didnt have a template attached.

1 more question, I m stuck, I have my journal scroll rect going out of the main panel when there are many quests in the journal, I have changed images etc but havent touched the actual game objects of the Quest Machine prefab, but obviously I have something done wrong. Demo one works fine. What property is responsible for this so I can go ahead and find the issue?

Thank you
User avatar
Tony Li
Posts: 21636
Joined: Thu Jul 18, 2013 1:27 pm

Re: HUD UI Groups

Post by Tony Li »

Hi,

Can you share a screenshot?

Is the text content extending outside of the scroll rect? If so, is the Mask component enabled?

Or is the entire scroll rect GameObject positioned in the wrong place?
dlevel
Posts: 150
Joined: Wed Nov 16, 2016 6:17 pm

Re: HUD UI Groups

Post by dlevel »

Yes the text extending out side the scroll rect, at what gameobject is the mask that should be on to check it? Thanks
User avatar
Tony Li
Posts: 21636
Joined: Thu Jul 18, 2013 1:27 pm

Re: HUD UI Groups

Post by Tony Li »

Hi,

It depends on how your scroll rect is set up. Yours may have a Scroll View in-between the Scroll Rect and the content. The prefab that ships with QM doesn't:
mask.png
mask.png (125.77 KiB) Viewed 42 times
Here's an example of how it masks the content when there's a lot of content:
mask2.png
mask2.png (207.79 KiB) Viewed 42 times
(Note that I enabled the Content Size Fitter manually because the default prefab keeps it disabled and only enables it at runtime. That's for some obscure edge cases that your UI almost certainly doesn't need to worry about.)

And if I disable the mask, it looks like this:
nomask.png
nomask.png (247.94 KiB) Viewed 42 times
dlevel
Posts: 150
Joined: Wed Nov 16, 2016 6:17 pm

Re: HUD UI Groups

Post by dlevel »

Ok perfect, had a weird issue that I had to have the mask's alpha >1 to work or else it would hide the quests in the main window but yeah I m good now.

One more question since I can't find it, is there a way to have max tracked quests in HUD? Since it overflows in th screen now
User avatar
Tony Li
Posts: 21636
Joined: Thu Jul 18, 2013 1:27 pm

Re: HUD UI Groups

Post by Tony Li »

Here are two ideas:

1. Write a script that listens for the message "Quest Track Toggle Changed" (defined in a const string QuestMachineMessages.QuestTrackToggleChangedMessage) and, if the max number of quests has been tracked, automatically untrack some other quest. See this post for an example of listening for messages.

2. Or make a subclass of UnityUIQuestJournalUI and override the behavior of the quest track checkbox toggles. Maybe set the unticked ones non-interactable if you're at the max. If the player UNticks a ticked checkbox, set the unticked ones interactable again.
dlevel
Posts: 150
Joined: Wed Nov 16, 2016 6:17 pm

Re: HUD UI Groups

Post by dlevel »

ok that helped, created this script if you d like to implemented in a future update that does this, but even though it tracks quests fine and tries to untrack some, this feature doesnt work, so it doesnt untrack quests, can you help me on that? Thanks

Code: Select all

using UnityEngine;
using PixelCrushers;
using PixelCrushers.QuestMachine;
using System.Collections.Generic;

public class QuestTrackingLimiter : MonoBehaviour, IMessageHandler
{
    public int maxTrackedQuests = 5; // Define your limit here
    private List<string> trackedQuests = new List<string>();

    private void OnEnable()
    {
        // Listen for Quest Track Toggle Changed messages:
        MessageSystem.AddListener(this, QuestMachineMessages.QuestTrackToggleChangedMessage, string.Empty);
        Debug.Log("QuestTrackingLimiter: Listening for quest track changes.");
    }

    private void OnDisable()
    {
        // Stop listening:
        MessageSystem.RemoveListener(this);
        Debug.Log("QuestTrackingLimiter: Stopped listening for quest track changes.");
    }

    public void OnMessage(MessageArgs messageArgs)
    {
        string questID = messageArgs.parameter;
        bool isTracked = (bool)messageArgs.values[0]; // This will tell if the quest is being tracked or untracked

        if (isTracked)
        {
            Debug.Log($"Quest '{questID}' is now being tracked.");

            // Check if max tracked quests limit is reached
            if (trackedQuests.Count >= maxTrackedQuests)
            {
                // Prevent tracking by immediately untracking the new quest
                Debug.Log($"Max tracked quests limit reached: {maxTrackedQuests}. Untracking quest '{questID}'.");
                UntrackQuest(questID);
                return;
            }

            // Add the new tracked quest if below the limit
            trackedQuests.Add(questID);
            Debug.Log($"Quest '{questID}' added to the tracked list. Current number of tracked quests: {trackedQuests.Count}/{maxTrackedQuests}.");
        }
        else
        {
            // Remove the untracked quest
            if (trackedQuests.Contains(questID))
            {
                trackedQuests.Remove(questID);
                Debug.Log($"Quest '{questID}' was untracked. Current number of tracked quests: {trackedQuests.Count}/{maxTrackedQuests}.");
            }
        }

        // Log the current list of tracked quests
        LogTrackedQuests();
    }

    private void UntrackQuest(string questID)
    {
        // Send a message to untrack the quest using the messaging system
        MessageSystem.SendMessage(this, QuestMachineMessages.QuestTrackToggleChangedMessage, questID, false);
        Debug.Log($"Quest '{questID}' untracked.");
    }

    private void LogTrackedQuests()
    {
        if (trackedQuests.Count == 0)
        {
            Debug.Log("No quests are currently being tracked.");
        }
        else
        {
            Debug.Log("Currently tracked quests:");
            foreach (var quest in trackedQuests)
            {
                Debug.Log($"- {quest}");
            }
        }
    }
}

Also another question, I ll be having like 100 quests on the game, is it better to have everything on the player with WaitingToStart and using variables to start quests (that would help with management), or just use "Give quest to player" from other finished quests? These quests will not be given by NPCs etc, will be like achievements. So I ask is the first method (just add all these quests to player prefab) is bad on performance or saves etc?
User avatar
Tony Li
Posts: 21636
Joined: Thu Jul 18, 2013 1:27 pm

Re: HUD UI Groups

Post by Tony Li »

Hi,

Try this version:
QuestTrackingLimiter.cs

Code: Select all

using UnityEngine;
using PixelCrushers;
using PixelCrushers.QuestMachine;
using System.Collections.Generic;

public class QuestTrackingLimiter : MonoBehaviour, IMessageHandler
{
    public int maxTrackedQuests = 5; // Define your limit here
    public List<string> trackedQuests = new List<string>();

    private void OnEnable()
    {
        // Listen for Quest Track Toggle Changed messages:
        MessageSystem.AddListener(this, QuestMachineMessages.QuestStateChangedMessage, string.Empty);
        MessageSystem.AddListener(this, QuestMachineMessages.QuestTrackToggleChangedMessage, string.Empty);
        Debug.Log("QuestTrackingLimiter: Listening for quest track changes.");
    }

    private void OnDisable()
    {
        // Stop listening:
        MessageSystem.RemoveListener(this);
        Debug.Log("QuestTrackingLimiter: Stopped listening for quest track changes.");
    }

    public void OnMessage(MessageArgs messageArgs)
    {
        string questID = messageArgs.parameter;
        if (QuestMachine.GetQuestState(questID) == QuestState.WaitingToStart) return;
        bool isTracked = false;
        if (messageArgs.message == QuestMachineMessages.QuestStateChangedMessage)
        {
            bool isMainQuestState = (messageArgs.values[0] == null);
            if (!isMainQuestState) return; // Only act if the main quest state has changed.
            QuestState questState = (QuestState)messageArgs.values[1];
            if (questState == QuestState.Disabled) return; // Quest giver disables its instance when given.
            if (questState == QuestState.Active) // Was just activated
            {
                var questInstance = QuestMachine.GetQuestInstance(questID);
                isTracked = questInstance.showInTrackHUD;
            }
        }
        else if (messageArgs.message == QuestMachineMessages.QuestTrackToggleChangedMessage)
        {
            isTracked = (bool)messageArgs.values[0]; // This will tell if the quest is being tracked or untracked
        }
        else
        {
            return; // Neither Quest State Changed nor Quest Track Toggle Changed, so exit.
        }

        if (isTracked)
        {
            Debug.Log($"Quest '{questID}' is now being tracked.");

            // Check if max tracked quests limit is reached
            if (trackedQuests.Count >= maxTrackedQuests)
            {
                // Prevent tracking by immediately untracking the new quest
                Debug.Log($"Max tracked quests limit reached: {maxTrackedQuests}. Untracking quest '{questID}'.");
                UntrackQuest(questID);
                return;
            }

            // Add the new tracked quest if below the limit
            trackedQuests.Add(questID);
            Debug.Log($"Quest '{questID}' added to the tracked list. Current number of tracked quests: {trackedQuests.Count}/{maxTrackedQuests}.");
        }
        else
        {
            // Remove the untracked quest
            if (trackedQuests.Contains(questID))
            {
                trackedQuests.Remove(questID);
                Debug.Log($"Quest '{questID}' was untracked. Current number of tracked quests: {trackedQuests.Count}/{maxTrackedQuests}.");
            }
        }

        // Log the current list of tracked quests
        LogTrackedQuests();
    }

    private void UntrackQuest(string questID)
    {
        // Send a message to untrack the quest using the messaging system
        // Not this: MessageSystem.SendMessage(this, QuestMachineMessages.QuestTrackToggleChangedMessage, questID, false);
        // Set the quest's showInTrackHUD property instead:
        QuestMachine.GetQuestInstance(questID).showInTrackHUD = false;
        Debug.Log($"Quest '{questID}' untracked.");
    }

    private void LogTrackedQuests()
    {
        if (trackedQuests.Count == 0)
        {
            Debug.Log("No quests are currently being tracked.");
        }
        else
        {
            Debug.Log("Currently tracked quests:");
            foreach (var quest in trackedQuests)
            {
                Debug.Log($"- {quest}");
            }
        }
    }
}
You can run a "diff" (e.g., using diffchecker.com or your code editor) to see the differences. Briefly, the script needs to also account for quest state changes.
dlevel wrote: Sun Sep 08, 2024 12:01 pmAlso another question, I ll be having like 100 quests on the game, is it better to have everything on the player with WaitingToStart and using variables to start quests (that would help with management), or just use "Give quest to player" from other finished quests? These quests will not be given by NPCs etc, will be like achievements. So I ask is the first method (just add all these quests to player prefab) is bad on performance or saves etc?
Putting 100 WaitingToStart quests on the player should be fine for performance and saves. It would really only be a concern if all of those quests had Autostart conditions that use polling, such as checking conditions every frame. Most of Quest Machine's built-in conditions are event-based -- that is, they only check when a specific message or event happens -- so they don't do polling.
Post Reply