Muse Behaviour - Getting started | Issues |

Hey!
I wanted to create this thread to help people get started with Muse behavior.
For people landing on this thread, Muse Behavior is currently free to use and does not need a subscription.

How to get Muse installed : Muse behavior package install

Muse Behaviour sample: Unity asset store package + video

Furthermore, this thread is meant to grow with people posting issues + solutions to creating behavior.

So currently I have not been able to get a transition happening to the next state.


The patrol state works great. Triggers when it needs to and also has a success state when expecting it, however, I can’t seem to get the investigate running.

I think you may be either missing a node to set your current AIState enum or having the graph Repeat; either with Start toggled to repeat or a Repeat node. If the graph finishes a branch from a switch and there’s a Repeat it should go from the Repeat back down. If it’s missing a node to set the state it’ll repeat the same default one.

Adding the repeat node below the onStart worked great! I do have a few more questions.
I think it’s more of a node structure question. So when thinking about AI you want it to behave as much as a real human as possible.

I need to be able to rotate the NPC over X amount of time and I need to have the NPC idle for X amount of time before making decisions or before actually realizing something has happened etc.

Currently, the Look at the target is immediate. and I need the NPC to rotate over time. Would coroutines be used here? If so how would I get monoBehaviours working in action classes?


20240220-1457-11.4723290-ezgif.com-video-to-gif-converter

That depends on how you’d like to go about it. You can have a timer within the rotate and idle independently, use the Wait node, or make a call to an external timer helper which could use coroutines or any other kind of timer. I’ve made use of the Wait node in a few spots as a placeholder since I’ve got my own external timer class, but it works great by itself. The Wait node is from the example graph, but it is easy to replicate should you not have it and want to use it:
image

public class WaitAction : Action
{
    public BlackboardVariable<float> SecondsToWait;
    float m_Timer = 0.0f;

    protected override Status OnStart()
    {
        m_Timer = 0.0f;
        return Status.Running;
    }

    protected override Status OnUpdate()
    {
        m_Timer += Time.deltaTime;
        if (m_Timer >= SecondsToWait)
        {
            return Status.Success;
        }
        return Status.Running;
    }
}

If you’d like you have a MonoBehavior working for the Action you’d have to use a helper class. Depending on the helper you can have it on the agent, a reference to another object, use an event, or use a singleton to call it.

If it’s on the agent you can have a node need a reference to the Agent / Self and call Self.Value.GetComponent in the action class like with your sensory system.

For one of my managers that spawns my agents, I have it put the spawned agents into a list and then cycle through them to assign some values. Example:

public class NPCManager : MonoBehaviour
{
    [SerializeField] private Transform _npcParent;
    [SerializeField] private List<BehaviorGraphAgent> _npcGraphs;
    private void SpawnTest()
    {
        SpawnNPCs();
        _npcGraphs = _npcParent.GetComponentsInChildren<BehaviorGraphAgent>().ToList();
    }
    private void SetStates(int start, int length, AIState state)
    {
        for (int i = start; i < start + length; i++)
        {
            _npcGraphs[i].Blackboard.TrySetVariableValue("AIState", state);
            _npcGraphs[i].Blackboard.TrySetVariableValue("NPCManager", transform.gameObject);
        }
    }
}

The Agents then sometimes use that reference to the manager to keep track of certain things in the world and could easily call a coroutine that way if wanted. They have to have that Blackboard variable already for the TrySetVariableValue to work.

You should be able to call any Singleton MonoBehavior or event from the Action as well and you could just call it that way.

public class ExampleTimers : Action
{
    TimerUtil _timer;
    bool _doneRotate = false;

    protected override Status OnStart()
    {
        _timer = TimerManagerUtil.onTimerCreated?.Invoke();
        _timer.SetupTimer(3.0f, ()=> TimerDone(_timer));
        return Status.Running;
    }

    protected override Status OnUpdate()
    {
        if (_doneRotate)
        {
            return Status.Success;
        }
        return Status.Running;
    }
    private void TimerDone(TimerUtil timer)
    {
        TimerManagerUtil.onTimerRemove?.Invoke(timer);
        _doneRotate = true;
    }
    protected override void OnEnd()
    {
    }
}

I don’t have a singleton example but it’d be similar. Essentially though you can get a reference to any monobehavior pretty easily and use that for an external one if you want to use a coroutine or any other kind of timer. Alternatively use a timer node or make a timer within the wanted node.

This is super helpful. I have the sensory system working for hearing, seeing, and attacking. Getting the NPC to turn over X amount of seconds is super helpful. I will post a few things here later tonight or tomorrow once I get things working. I think the key takeaway here is:

When creating an action, that action should do nothing but one thing.

Example:
CanSee focuses on just seeing the player and nothing more.

Also, using the agent to get all the other scripts attached to the NPC is super handy as well. I will then create a coroutine helper to get access to monoBehaviour.

Update:
The wait node works wonders. Is there a specific way to set variables on the blackboard? I can see the actual variables in the IDE get set but the console is complaining and the Debug shows that the self-move to LastKnowsPosition does not get set in the graph.

I am also getting this warning :

This error appears when the NPC tries to move to last known location

When creating an action, that action should do nothing but one thing.

The simpler a node the more re-useable it can be. I do have a number of nodes that vary greatly in complexity that do more than one thing. Some are only used in a couple of places.

That LastKnownPosition looks like it should work. I usually use .Value = instead of .Value.Set but they look to operate the same. It may be that an error is occurring before and causing it to not be able to continue with a valid value, the actual vector3 that the GetLastKnownPositon() returns isn’t the same as the variable, another node or script is overwriting the LastKnowValue with a vector3.zero or new vector3, the agent has had it’s navmeshagent or object disabled, or the gameobject being used for getting the NavMeshAgent isn’t the right GameObject. A little tough to tell from what’s visible

I’m getting the hang of this, however when switching from Patrol state to Investigate state, even after the NPC saw me, looked at me, it still moves towards the last set navmeshAgent destination. Am I correct in assuming I need to get a reference to the navmesh and reset it myself? NPC

So node flow question.

Currently have have 3 nodes checking for hearing, sight, and attack range. the 4th node is a patrol node that is under a repeat flow-node.

When the player is heard/seen I expect the Patrol branch to stop everything and switch as per my code . What I am seeing is, the NPC still tries to patrol for a second or 2 before switching course to the player-seen position.


20240220-2135-14.5870040-ezgif.com-optimize

Yes, a NavMeshAgent will continue going to it’s current destination until it gets there or unless you call isStopped = true;.

NavMeshAgent _navAgent = Agent.Value.GetComponent<NavMeshAgent>();
_navAgent.isStopped = true;

I think it may be a problem with the Patrol and the sight going a bit too close together. If you are setting the Destination in the OnUpdate of Patrol it would override the destination you want and there would be about 5 seconds more travel time with the Wait before it changes again from the new branch. So if I had to guess I think that the Patrol Node just needs some small tweaks. If possible, you can probably move it’s code from the OnUpdate to the OnStart.

I managed to get it working. Order in the graph matters.

20240220-2247-45.3473607-ezgif.com-optimize

I am writing a bunch of actions myself and I’t getting easier and easier to script out logic. Quite happy.

Thanks so much for the help. I think it would be great to write a small overview on the nodes the execution flow etc. I might just make some YouTube videos on it and post it in there in the Getting started main post.

Nice, glad you got it working :smiley:

I have an interesting question. I am currently creating nodes and I would like to create a generic node that will allow me to play audio. How have you gone about managing audio? I could simply make 1 node to play one sound when I call the node , however I think it would be great to be able to set the audio to be played directly in the graph

I haven’t done any audio yet for the project that’s making use of Muse Behavior, but when I do any sound for the Agent will probably go through a helper script. That way I can call the wanted effect by either it’s name or index and to handle any potential sound overlap and make it easier to call different sounds. That way I can just call it from a node or script and it’ll play the effect on an audio source that’s not currently playing. For global sound, if it’s a node, I’d have it the same with calling the name or index but doing a call to a main audio manager and not a helper script

I managed to create a nice sound node that allows you to turn on or off certain once-off sounds with a boolean. Works great. I tried passing in a FmodEventReference into the blackboard variable and it broke unity. I used a singleton pattern to gain access to my sounds and created a group of sounds to be selected randomly in Fmod.


Nice work! Currently blackboard variables only support certain types which may be why it broke Unity. Making use of GameObjects passed in from a node to call components or helper scripts and events or singletons to get to other data is how I do most things too. It’s not too difficult to work around but I am very much looking forward to the list supporting being added for blackboard variables in the future!

1 Like

I have run into a pretty big issue.


In the image under patrol I am currently checking if the player is heard, seen or attackable. These kinda need to be checked in all states other than Attack and pursue.

Right now I feel I have written all actions but I am not sure how to put them in the graph.

I think what I am trying to say is, If the player is heard, switch to investigate, but during investigate if seen, switch to pursue or attack. So the checks need to run throughout any or all branches or certain branches

Hello there, @Reaper210! You’re facing a common difficulty with authoring interruptible states of behavior inside of a behavior tree. In fact, there’s a GDC talk by Bobby Anguelov that covers a similar scenario.

To handle this use case in Muse Behavior today, you’ll want to add to your graph some mechanisms of interrupting the various branches representing your patroll/investigate/etc states. We have abort nodes planned (but not completed) which will concisely help with this. For now, I’ll show you how you can get similar behavior using the built-in events system.

Here, I’ve created an interrupt event channel with no message parameters and set a node which will wait for the event to be issued. Once the event occurs, the wait node’s parent will interrupt the right side of the tree and reevaluate.

So let’s take a look at how we might structure the logic for switching states and sending this signal. Elsewhere in the same asset, I’ve created a second graph (you can have as many as you’d like!), which looks like this:

In your use case, it seems the states are strictly ordered in priority of which should occur. I’ve added a TryInOrder node to evaluate one branch at a time. Then, if the state has changed, send the interrupt signal, which will be picked up by the original graph.

Now, if you want to constrain which transitions can occur from specific states, it becomes more hairy. As a best practice, you should likely just use a state machine tool, but I’ll show you how you could structure a tree with similar behavior:

In this variant, the Patrol state behavior manages its own monitoring of conditions to
transition to another state. With more states and more complex transition conditions, this will grow to become unmanageable. So, avoid it if possible.

I hope that helps!

1 Like

Thank you so much for the info. I sorta get the jist of it and I think right now I am building the last graph and that is not desirable. (Each state manages its own conditions)

  1. I am a little lost. I have an AI Graph. Are you saying that I can have more than one On Start node per graph?
  2. I am not too sure how to create the interrupt behavior channel node.
  3. I have created an action class per NPC action like Can see, can hear, can attack. Is this the correct approach?

I am trying to NPCs to the level of METAL GEAR SOLID 1 for the PlayStation 1, so I am having a hard time trying to get the NPCs to behave how I want them to.

In most cases In the investigate state, I would need to check if I can see the player and if the player is attackable or not. Based on that info the NPC would run to try to get closer to attack. In this instance, I want from the Investigate state to the Puruse state.

I think the alert state would also be a huge undertaking. Once the player has escaped there will be a 100sec cooldown. The alert state needs to set all guards to alert.

For reference my state transition matrix