Beispiel #1
0
    // Use this for initialization
    void Start()
    {
        // Get access to the unit we are controlling
        unit = GetComponent <Unit>();

        // Install an on death function to remove all logic from the unit
        unit.installDeathListener(delegate() { root = new Leaf(delegate() { return(BehaviorReturnCode.Success); }); });

        ////////////////////////////////////////////////////////////////////
        /////////////////////   PATROLLING/IDLE   //////////////////////////
        ////////////////////////////////////////////////////////////////////

        Leaf checkIsPatrolling = new Leaf(delegate()
        {
            if (unit.patrolling == false)
            {
                return(BehaviorReturnCode.Failure);
            }

            return(BehaviorReturnCode.Success);
        });

        Leaf patrolPath = new Leaf(delegate()
        {
            // Check if we have a patrol path to make use of
            PatrolPath path = unit.GetComponent <PatrolPath>();
            if (path != null)
            {
                unit.setDestination(path.patrolPointHolder.transform.GetChild(path.nextPatrolPoint()).position);
                unit.patrolling = true;
                return(BehaviorReturnCode.Success);
            }
            return(BehaviorReturnCode.Failure);
        });

        Leaf patrolArea = new Leaf(delegate()
        {
            // If we have a patrol area use that to find our random position
            PatrolArea area = unit.GetComponent <PatrolArea>();
            if (area == null)
            {
                return(BehaviorReturnCode.Failure);
            }

            // Generate our patrol position
            Vector3 newTargetPosition = Vector3.zero;
            Vector3 patrolPosition    = area.patrolAreaObject.transform.position;
            float patrolRange         = area.patrolAreaObject.transform.localScale.x;
            if (unit.findRandomPointOnNavMesh(patrolPosition, patrolRange, out newTargetPosition))
            {
                // Start moving towards our new random point
                unit.setDestination(newTargetPosition);
                unit.patrolling = true;
                return(BehaviorReturnCode.Success);
            }
            return(BehaviorReturnCode.Failure);
        });

        Leaf manualPatrol = new Leaf(delegate()
        {
            // Check to see if the unit manually patrols
            ManualPatrol manualPatrolling = unit.GetComponent <ManualPatrol>();
            if (manualPatrolling == null)
            {
                return(BehaviorReturnCode.Failure);
            }

            // If the unit manually patrols wait for a new patrol position
            if (manualPatrolling.getPatrolConsumed())
            {
                return(BehaviorReturnCode.Running);
            }

            // If we have a new patrol position consume it
            unit.setDestination(manualPatrolling.getPatrolPosition());
            unit.patrolling = true;
            return(BehaviorReturnCode.Success);
        });

        Leaf patrolFollowLeader = new Leaf(delegate()
        {
            // Check to see if the unit has a leader to follow
            FollowLeader leaderToFollow = unit.GetComponent <FollowLeader>();
            if (leaderToFollow == null)
            {
                return(BehaviorReturnCode.Failure);
            }

            // If the unit has a leader follow it but don't start patrolling.  This allows
            // the unit to continuously follow the leader as it moves.
            unit.setDestination(leaderToFollow.getFollowPosition());
            return(BehaviorReturnCode.Success);
        });

        Leaf patrolRandom = new Leaf(delegate()
        {
            // If we don't have a defined path generate a random position
            Vector3 patrolCenterPosition = transform.position;
            float patrolRange            = unit.patrolSearchRange;
            Vector3 newTargetPosition    = Vector3.zero;

            // Generate our patrol position
            if (unit.findRandomPointOnNavMesh(patrolCenterPosition, patrolRange, out newTargetPosition))
            {
                // Start moving towards our new random point
                unit.setDestination(newTargetPosition);
                unit.patrolling = true;
                return(BehaviorReturnCode.Success);
            }
            return(BehaviorReturnCode.Failure);
        });

        Selector selectPatrolPath = new Selector(checkIsPatrolling, patrolPath, patrolArea, manualPatrol, patrolFollowLeader, patrolRandom);

        Leaf sendPatrolToSquad = new Leaf(delegate()
        {
            SquadLeader squad = unit.GetComponent <SquadLeader>();
            if (squad == null)
            {
                return(BehaviorReturnCode.Success);
            }

            // If the unit is part of a squad inform the subordinates of a new patrol position
            squad.issueNewTroopMovement();
            return(BehaviorReturnCode.Success);
        });

        Leaf waitToReachDestination = new Leaf(delegate()
        {
            if (unit.isMovingNavMesh() && unit.patrolling)
            {
                return(BehaviorReturnCode.Running);
            }
            // If the unit is a follower then don't bother waiting to reach a destination
            else if (unit.GetComponent <FollowLeader>() != null)
            {
                return(BehaviorReturnCode.Failure);
            }
            else
            {
                return(BehaviorReturnCode.Success);
            }
        });

        Leaf stopRunning = new Leaf(delegate()
        {
            unit.anim.SetBool("Running", false);
            unit.agent.isStopped = true;
            return(BehaviorReturnCode.Success);
        });

        Leaf playIdleAnim = new Leaf(delegate()
        {
            unit.anim.SetTrigger("PatrolIdleAnim1Trigger");
            return(BehaviorReturnCode.Success);
        });

        RandomBehavior idleRand = new RandomBehavior(.1f, playIdleAnim);

        Timer playIdleAnimTimer = new Timer(1.0f, idleRand);

        Leaf stopPatrolling = new Leaf(delegate()
        {
            unit.patrolling = false;
            return(BehaviorReturnCode.Success);
        });

        Timer stopPatrollingTimer = new Timer(unit.patrolWaitTime, stopPatrolling);

        StateSequence patrolLogic = new StateSequence(selectPatrolPath, sendPatrolToSquad, waitToReachDestination, stopRunning, playIdleAnimTimer, stopPatrollingTimer);

        ////////////////////////////////////////////////////////////////////
        /////////////////////   AGGRO/ATTACKING   //////////////////////////
        ////////////////////////////////////////////////////////////////////

        Leaf dropTargetLogic = new Leaf(delegate()
        {
            // If we don't have a target continue
            if (unit.target == null)
            {
                return(BehaviorReturnCode.Success);
            }

            // If our target is dying search for a new one
            if (unit.target.isUnitDying())
            {
                unit.target = null;
            }
            // If our target it outside of our aggro radius clear it
            if (unit.distanceToTarget() > unit.enemySearchRadius)
            {
                unit.target = null;
            }

            return(BehaviorReturnCode.Success);
        });

        Leaf acquireTarget = new Leaf(delegate()
        {
            // If we already have a living target just return success
            if (unit.target != null)
            {
                return(BehaviorReturnCode.Success);
            }

            // Search for the closest enemy
            IUnit foundTarget = unit.findClosestTarget();

            // If we were able to find a target return success, otherwise we failed
            if (foundTarget != null)
            {
                // If we find a new target stop patrolling
                unit.patrolling = false;
                unit.target     = foundTarget;
                return(BehaviorReturnCode.Success);
            }
            else
            {
                return(BehaviorReturnCode.Failure);
            }
        });

        Leaf checkToAttack = new Leaf(delegate()
        {
            // If we are already attacking continue
            if (unit.attacking)
            {
                return(BehaviorReturnCode.Success);
            }

            // Check if our target is within the attack radius and isn't already dying
            if (unit.distanceToTarget() <= unit.attackRadius)
            {
                // Face the target
                Quaternion lookRot      = Quaternion.LookRotation(unit.target.getGameObject().transform.position - unit.transform.position);
                unit.transform.rotation = Quaternion.Euler(0, lookRot.eulerAngles.y, 0);

                // Stop the navmesh agent
                unit.agent.isStopped = true;
                // Stop running
                unit.anim.SetBool("Running", false);
                // Play our attack animation
                unit.anim.SetTrigger("AttackTrigger");
                unit.attacking = true;
            }
            else
            {
                unit.attacking = false;
            }
            return(BehaviorReturnCode.Success);
        });

        Leaf moveToTarget = new Leaf(delegate()
        {
            // If we're still attacking wait to finish
            if (unit.attacking == true)
            {
                return(BehaviorReturnCode.Success);
            }

            // Start moving towards our target
            unit.setDestination(unit.target.getGameObject().transform.position);
            return(BehaviorReturnCode.Success);
        });

        Sequence attackSequence = new Sequence(dropTargetLogic, acquireTarget, checkToAttack, moveToTarget);

        ////////////////////////////////////////////////////////////////////
        //////////////////////////   ROOT   ////////////////////////////////
        ////////////////////////////////////////////////////////////////////

        root = new Selector(attackSequence, patrolLogic);
    }