Help with Replicating Tutorial Behaviour Tree

I’m having some issues with my enemy character (ie. the zombie), it’s set as Root Motion, has a RigidBody, isGravity is on. I also have for now just added a capsule collider to the whole zombie object. However the zombie just floats in the air a few centimetres off the floor. Even if I start the scene with placing him well above the floor he never drops to the floor?! Any idea why that’s happening? I also tried selecting isKinetic but that didn’t help.

Upon further investigation, disabling the NavMesh Component of the zombie, makes him fall down via gravity, but then his feet go into the ground?!

Any idea why NavMesh would affect the models y position? Cause as soon as i enable the NavMeshAgent component again, i can not manually even move the Y position of the model.
 
How can I access my controller class from the custom task? My controller class is just called AINavigator.
Take a look at this page for scripting a new task - the setup is really similar to a MonoBehaviour: https://opsive.com/support/documentation/behavior-designer/writing-a-new-action-task/

Upon further investigation, disabling the NavMesh Component of the zombie, makes him fall down via gravity, but then his feet go into the ground?!

Any idea why NavMesh would affect the models y position? Cause as soon as i enable the NavMeshAgent component again, i can not manually even move the Y position of the model.
The joys of creating a new character controller :) I don't know of any in particular but I imagine that there are a decent amount of guides on how to setup a NavMeshAgent with a rigidbody.
 
Take a look at this page for scripting a new task - the setup is really similar to a MonoBehaviour: https://opsive.com/support/documentation/behavior-designer/writing-a-new-action-task/


The joys of creating a new character controller :) I don't know of any in particular but I imagine that there are a decent amount of guides on how to setup a NavMeshAgent with a rigidbody.

Hi Justin, thanks I managed to sort out the floating issue, it was actually just a tick box for height nav mesh that needed to be ticked before baking the navmesh.

However, I’m having another issue that I was really hoping you might be able to help with as I’ve tried and searched for hours but can’t seem to solve this problem.

I have a zombie enemy, that has an Animator Controller. I have enabled Root Motion.
The zombie has a NavMeshAgent component and Behaviour Designer.

I created a script AINavigator, that basically handles some different states and sets parameters accordingly for idle, walking, running, attacking.

When I add this script onto my zombie, in the Animator component the Root Motion checkbox disappears and instead says “Handled By Script”.

This is due to me using the function OnAnimationMove() in my script.

However, when I do this the zombies animations are not Root Motion anymore and the feet are sliding on the floor even in the idle state. Disabling the OnAnimationMove() function in my script enables the Root Motion again.

Do you know why this happens and how to fix it?

As you suggested I used the mech warriors article to create the AINavigator script. Which uses the OnAnimatorMove function to update the position of the mesh.
 
Hi Justin, thanks I managed to sort out the floating issue, it was actually just a tick box for height nav mesh that needed to be ticked before baking the navmesh.

However, I’m having another issue that I was really hoping you might be able to help with as I’ve tried and searched for hours but can’t seem to solve this problem.

I have a zombie enemy, that has an Animator Controller. I have enabled Root Motion.
The zombie has a NavMeshAgent component and Behaviour Designer.

I created a script AINavigator, that basically handles some different states and sets parameters accordingly for idle, walking, running, attacking.

When I add this script onto my zombie, in the Animator component the Root Motion checkbox disappears and instead says “Handled By Script”.

This is due to me using the function OnAnimationMove() in my script.

However, when I do this the zombies animations are not Root Motion anymore and the feet are sliding on the floor even in the idle state. Disabling the OnAnimationMove() function in my script enables the Root Motion again.

Do you know why this happens and how to fix it?

As you suggested I used the mech warriors article to create the AINavigator script. Which uses the OnAnimatorMove function to update the position of the mesh.

I managed to solve that too actually it was just a line that says applyRootMotion that needs to be set to true in the method OnAnimatorMove(). Then Root motion works properly. I also have written my Attack Behaviour Node aswell now and thats almost working too.


However, hopefully this is the last part of the AI but Justin i really need your help with one problem i am having, when my agent seeks the player, he comes within the attack distance, starts attacking, however while attacking he is still seeking and hence moving around (even though for example when my player is not moving). I want him to stop moving all togather and just stand still and attack atleast until the player moves away. Ive spent hours trying to fix this issue in my behaviour tree but havent been able to solve it. Hopefully you can have a look at this attack and seek part of my behvaiour tree and know whats wrong with it or what i need to change to make it work correctly.

Please if you could take a look at the image and help me out. It was pretty much based originally on your tutorial tree with the soldier.

Thanks.Attack Behaviour Tree.png
 
I can't see anything wrong with your tree - the seek task will only return success when it has arrived at the destination so at that point the character should no longer be moving.
 
I can't see anything wrong with your tree - the seek task will only return success when it has arrived at the destination so at that point the character should no longer be moving.

Ive tried everything, but for some reason whenever agent reaches the seek position and then starts to attack, he always starts walking away from the agent and then attacking, so his back is mostly facing the player on attack :(

Its like hes seeking to the position, getting too close so trying to turn back around to keep a distance away from the player and then the attack happens. Ive pretty much tried everything on trying to fix this, spent almost all of my saturday and sunday on it and now im on the verge of giving up and going to another AI system, which would be a huge shame as ive invested alot of time and money into behaviour tree :( but im left with almost no other option.
 
BTW not sure if this might help or not, but here is my AIController class that updates the root motion of the zombie to animate correctly:

C#:
void Update()
    {
        // Character walks/runs if there is a navigation path set, idle all other times.
        if (_navAgent.hasPath)
        {
            if (CanRun)
                moveState = MoveState.Running;
            else
                moveState = MoveState.Walking;
        }
        else
            moveState = MoveState.Idle;

        // Send move state info to animator controller.
        _animController.SetFloat(_blendSpeedHash, (float)moveState);
    }
    
    void OnAnimatorMove()
    {
        _animController.ApplyBuiltinRootMotion();

        // Only perform if walking or running.
        if (moveState == MoveState.Walking || moveState == MoveState.Running)
        {
            // Set the navAgent's velocity to the velocity of the animation clip currently playing.
            _navAgent.velocity = _animController.deltaPosition / Time.deltaTime;

            // Smoothly rotate the character in the desired direction of motion.
            Quaternion lookRotation = Quaternion.LookRotation(_navAgent.desiredVelocity);
            transform.rotation = Quaternion.RotateTowards(transform.rotation, lookRotation, _navAgent.angularSpeed * Time.deltaTime);
        }
    }

    public bool Attack()
    {
        // Calculate random attackState.
        int randomAttack = UnityEngine.Random.Range(0, _attacksArray.Length);

        // Set the attack trigger state.
        _animController.SetTrigger(_attacksArray[randomAttack]);

        return true;
    }
 
You are getting into the integrates of creating a character controller :) If the seek task isn't active when the attack task is active then the seek has completed. Just glancing at your code I can't see anything obvious but if you set breakpoints when the character is firing you should be able to determine why the walk animation is playing. It may also be related to your animator since you are using root motion.
 
You are getting into the integrates of creating a character controller :) If the seek task isn't active when the attack task is active then the seek has completed. Just glancing at your code I can't see anything obvious but if you set breakpoints when the character is firing you should be able to determine why the walk animation is playing. It may also be related to your animator since you are using root motion.

The character controller I have is very basic just to enable root motion and the attack calls. You said it was the easiest way to do the animator controls like you recommended in the mech warriors article, that’s the reason I took that route as I didn’t know how else I could do it.

The seek task isn’t active when attack is called for about half a second but then straight after the attack the seek task lights up also!!!

The agent is a zombie so it’s just melee combat which is up close to the player, determined by a variable which links to the navmesh stopping distance. I use the same variable for attack distance also that gets set in one of your nodes.

Yeh I did think that the animator might be causing it so I had a look and the attack layer I did set with a mask to only effect the top half of the agent, so that he can continue walking and attacking, but I tried without this too and removed the mask on the attack later so that agent is basically idle and then attacks. But still even with this the agent sometimes faces the wrong way while attacking and it just looks bad.

It’s like the agent thinks it’s destinstion is somewhere else down south as he always seems to look at that direction while attacking then comes back to walking at me then turns around again and walks and attacks back down south direction. Or it’s like something is moving or making him walk always in that direction, I thought it might be the navmesh.velocity line in my class but even removing that he still acts weird.

I can’t really think of trying anything else, have you tried before with melee combat using behaviour designer? It’s like the agent rebounds off when he reaches the attack distance circle so he tries to get back out of that area and that’s when attack happens so it’s the wrong way, then he remembers that his destinstion is me so he turns around again to face me, tries to get close and then cause he’s too close he has to turn around again and face the wrong way?!??!
 
If the tree goes back to seek then that's likely your problem. Looking at your tree again I would change the both conditional abort on the sequence task to just a lower priority conditional abort. You can then increase the cooldown time to prevent the seek task from occurring again so quickly.
 
If the tree goes back to seek then that's likely your problem. Looking at your tree again I would change the both conditional abort on the sequence task to just a lower priority conditional abort. You can then increase the cooldown time to prevent the seek task from occurring again so quickly.
Okay thanks Justin, did you mean changing the sequence tasks for the two at the top, or the middle and bottom one? At the moment the top 2 sequence tasks currently had conditional aborts, so i assume you mean those ones and not the one at the bottom between the seek and wait task.

Going over the tree and script again last night, made me feel that it might be the mech warrior script which i followed thats causing things to mess up. More precisely the OnAnimatorMove() function, which sets the navAgent Velocity. As the Agent is pretty much locked in the direction he seems to want to travel which i think why seek is constantly being called.

So my next solution would be how to get this to work without using the AINavigator script at all? Is that possible? I know we can set the float parameters for Animator via behaviour nodes before the seek tasks, and then reset them back to 0 after the seek task finishes. But when i tried this its almost like Root Motion is not working/enabled anymore, as my zombie is sliding across the floor while walking?! Any idea why this happens? Do i need to set a Root Motion node/property in Behaviour Tree aswell or something?

thanks.
 
I'm not sure on your script without actually getting it in and debugging, but I can say that it's the bottom Sequence task that has the Both conditional abort that should be switched to Lower Priority. A Both conditional abort will keep reevaluating that branch even while it is active and you don't want this because when the character is attacking they should keep attacking instead of reverting back to the seek.
 
Top