Really enjoyed this lecture. Just posting my version of the code for feedback

This is what I came up with for the challenge solution (though I missed adding the Cancel() the first time 'round). Really liked this challenge! Let me know if this code would come up with anything odd, or if I’ve messed things up for future lectures.

using RPGTutorial.Movement;
using RPGTutorial.Combat;

namespace RPGTutorial.Control
{
    [RequireComponent(typeof(Fighter))]
    [RequireComponent(typeof(Mover))]
    public class AIController : MonoBehaviour
    {
        [SerializeField] float chaseDistance = 10f;
        GameObject player;
        Mover mover;
        Fighter fighter;

        /// <summary>
        /// Here, we are caching references to things we are going to use multiple times in the class. "Player", Mover, and Fighter are referenced more than once,
        /// and so it's generally a very good idea to make a reference to them rather than getting their components every time.
        /// 
        /// Others' tips: "In this case, it’s ok to cache the Player in Start(), but there are situations where it’s imperative that you cache an external reference in Awake() 
        /// to avoid a race condition with the Saving System (future lecture). It’s generally safe to cache the reference in Awake() but it’s seldom safe to actually access 
        /// the reference in Awake()."
        /// </summary>
        private void Awake()
        {
            mover = GetComponent<Mover>();
            fighter = GetComponent<Fighter>();
            player = GameObject.FindWithTag("Player");
        }

        /// <summary>
        /// Checks to see if the player does not exist, and if so, exits Update before doing anything else.
        /// Then, if the AI is busy in combat, it exits Update before checking if it is chasing the player.
        /// Finally, if the AI is busy chasing the player, it exits Update and checks it all again.
        /// This makes sure that the AI does not worry about chasing if it is in combat, or about combat if it is chasing.
        /// It's important that it checks if it's in combat first, otherwise it would never check to see if the AI is in 
        /// combat, since it's exiting Update if it's busy chasing.
        /// The same types of bools are in the PlayerController for the same reasons.
        /// </summary>
        private void Update()
        {
            if (player == null) { return; }
            if (IsBusyInCombat()) { return; }
            if (IsBusyChasing()) { return; }
        }

        /// <summary>
        /// Just like in the PlayerController, we want to make sure the AI isn't trying to move while it's in combat and vice versa.
        /// First we see if the distance between the AI's position and the player's position in world space is less than or equal to the 
        /// AI's chasingDistance variable. If it is in chasing distance of the player, we check to see if the AI can attack the player or not.
        /// If both are true, we tell the Fighter to allow the AI to attack the player, and return this bool true. The moment either of these two 
        /// statements (in chasing distance or can attack) are false, we tell the Fighter to cancel the attack and return false.
        /// </summary>
        bool IsBusyInCombat()
        {
            if (GetIsInChasingDistance() && fighter.CanAttack(player))
            {
                fighter.Attack(player);
                return true;
            }
            else
            {
                fighter.Cancel();
                return false;
            }
        }

        /// <summary>
        /// Much like in the PlayerController's InteractWithMovement bool, this checks to see if the AI is within chasing distance of the player, and
        /// if the player is not null, we tell the Mover to start a move action, setting the AI's destination to the player's position in world space.
        /// We then set the bool to true. Otherwise, we tell the mover to cancel the move action and return the bool false.
        /// </summary>
        bool IsBusyChasing()
        {
            if (GetIsInChasingDistance() && player != null)
            {
                mover.StartMoveAction(player.transform.position);
                return true;
            }
            else
            {
                mover.Cancel();
                return false;
            }
        }

        /// <summary>
        /// Pretty self-explanatory, but this bool returns true only if the distance between the AI's position and the player's position are less than or equal to
        /// the AI's chasing distance.
        /// </summary>
        private bool GetIsInChasingDistance()
        {
            float distanceToPlayer = Vector3.Distance(transform.position, player.transform.position);
            return distanceToPlayer <= chaseDistance;
        }
    }
}

I like this approach. It’s showing to me that you have an excellent understanding of race conditions, as well as exactly how our PlayerController’s psuedo state is working. Well done, and I don’t see anything off of the top of my head that is going to trip things up.

There may be some adjustments needed if you wanted your enemies to interact with each other or do some other form of behaviour, but we’d need to make similar adjustments in the existing code.

Well done!

1 Like

Thank you so much for the feedback! It’s incredible that you continue to so kindly respond to comments and questions on this forum. I don’t think I’ve ever experienced such a helpful welcome to a community. I’ve taken a few tutorials on YouTube and the toughest part was being unable to get any feedback from those involved. It kinda steered me away from tutorials and lectures…until now. So thanks again!

I’ve experienced tutorials (and even paid courses) like that. One of the reasons I was proud to join the support team here at GameDev.tv is the excellent support and feedback when I was a student!

1 Like

I agree whole heartedly.

I’ve been working my way through the whole gamedev catalog aha.

I learn as much through the comments as the videos, and if you include Brian’s amazing property drawer lesson then maybe more!

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms