private void Update()
    {
        //Forward raycast checking for a possible blocked agent inside the avoid radius
        //Makes this agent a stationary obstacle if they have been blocked for a certain time
        if (Physics.Raycast(new Vector3(transform.position.x, 1f, transform.position.z), transform.forward, out hit, navAgent.radius + .5f) &&
            navAgent.isOnNavMesh && !initialSpawn)
        {
            if (hit.transform.tag == "Civillian" && hit.transform != this.transform)
            {
                stuckTimer += Time.deltaTime;

                if (hit.transform.GetComponent <CivillianController>().isStationary == false && stuckTimer >= 2f)
                {
                    //Stop this agent and wait until the other one repaths around you
                    stuckTimer = 0;
                    m_Animator.SetBool("idle", true);
                    navAgent.isStopped = true;

                    currentDest = navAgent.destination;

                    navAgent.ResetPath();
                    navAgent.enabled = false;
                    isStationary     = true;

                    //Create nav obstacle
                    if (gameObject.GetComponent <NavMeshObstacle>() == null)
                    {
                        NavMeshObstacle obstacle = gameObject.AddComponent <NavMeshObstacle>();
                        obstacle.shape   = NavMeshObstacleShape.Capsule;
                        obstacle.radius  = 0.3f;
                        obstacle.center  = new Vector3(0, 1, 0);
                        obstacle.carving = true;
                    }
                    else //Obstacle has already been added first time around so enable from here on out
                    {
                        gameObject.GetComponent <NavMeshObstacle>().enabled = true;
                    }

                    //Storing the hit agent
                    otherAgent = hit.transform;
                }
            }

            if (hit.transform.tag == "GPatrol" && hit.transform != this.transform)
            {
                stuckTimer += Time.deltaTime;

                if (this.transform.GetComponent <CivillianController>().isStationary == false && stuckTimer >= 2f)
                {
                    //Stop this agent and wait until the other one repaths around you
                    stuckTimer = 0;
                    m_Animator.SetBool("idle", true);
                    navAgent.isStopped = true;

                    currentDest = navAgent.destination;

                    navAgent.ResetPath();
                    navAgent.enabled = false;
                    isStationary     = true;

                    //Create nav obstacle
                    if (gameObject.GetComponent <NavMeshObstacle>() == null)
                    {
                        NavMeshObstacle obstacle = gameObject.AddComponent <NavMeshObstacle>();
                        obstacle.shape   = NavMeshObstacleShape.Capsule;
                        obstacle.radius  = 0.3f;
                        obstacle.center  = new Vector3(0, 1, 0);
                        obstacle.carving = true;
                    }
                    else //Obstacle has already been added first time around so enable from here on out
                    {
                        gameObject.GetComponent <NavMeshObstacle>().enabled = true;
                    }

                    //Storing the hit agent
                    otherAgent = hit.transform;
                }
            }
        }
        else
        {
            stuckTimer = 0;
        }

        //Turns on Wander once initial destination has been hit otherwise resample the location and continue moving there
        if (initialSpawn && navAgent.enabled)
        {
            //distance check? test if we have reached near the firstspawn dest?
            //What if its no longer reachable? possible error
            //if we have reached our destination (hopefully on the same path) then enable wander and disable this block
            if (navAgent.hasPath)
            {
                if (Vector3.Distance(transform.position, firstSpawnDest) <= 1.0f)
                {
                    initialSpawn = false;
                    enableWander = true;
                }
            }
            else //Check incase one of the items update the navmesh and breaks the current agents pathing
            {
                //Debug.Log("Else called initialSpawn");
                NavMeshHit navHit;
                NavMesh.SamplePosition(firstSpawnDest, out navHit, wanderRadius, -1);
                navAgent.SetDestination(navHit.position); //No error checking so possible error if SamplePosition fails
            }
        }

        //If otherAgent was found we wait until its out of the way before we repath
        if (otherAgent != null)
        {
            Vector3 dirToOther = otherAgent.position - transform.position;

            if (dirToOther.magnitude >= 2f)
            {
                //Re-enable the stationary agent - Prevents agent not being placed on navmesh error
                if (isStationary)
                {
                    stationaryTimer += Time.deltaTime;

                    if (stationaryTimer >= .5f)
                    {
                        stationaryTimer = 0;
                        gameObject.GetComponent <NavMeshObstacle>().enabled = false;
                        isStationary = false;
                    }
                }
                else //Turn the nav agent back on in the next update frame
                {
                    otherAgent       = null;
                    navAgent.enabled = true;
                    navAgent.ResetPath(); //Clear any paths somehow created during the time navagent was turned off
                    navAgent.isStopped = false;

                    //Calculate a new path to the same destination from when the agent was stopped
                    navAgent.SetDestination(currentDest);

                    //Destroy(gameObject);

                    //NavMeshPath path = new NavMeshPath();
                    //navAgent.CalculatePath(currentDest, path);
                    //navAgent.SetPath(path);


                    m_Animator.SetBool("idle", false);
                }
            }
        }
        else
        {
            if (isStationary)
            {
                Debug.Log("stationaryNull");
            }
        }
        //Reset the path if we have arrived
        //Maybe check the distance between current corner we are on and last corner in the path to check if we have arrived?
        if (navAgent.hasPath && navAgent.remainingDistance <= navAgent.stoppingDistance)
        {
            //Debug.Log(name + " Reset Called");
            navAgent.ResetPath();
        }

        //Timing estimation, Reset path if the time it took to reach path end point is greater than the estimated time give or take 4 seconds for avoidance?
        //Distance / Speed = Time
        //if(currentState == State.State_Wander)
        //{
        if (navAgent.hasPath)     //Added retreat state check to turn off repathing causing issues atm
        {
            if (!estimTimeSet)
            {
                estimationTime = Vector3.Distance(transform.position, navAgent.pathEndPosition) / navAgent.speed;
                estimationTime = estimationTime + 2.0f;     //Adding a little leway
                estimTimeSet   = true;
            }

            currTimeOnPath += Time.deltaTime;

            if (currTimeOnPath >= estimationTime)
            {
                navAgent.ResetPath();
            }
        }
        else
        {
            currTimeOnPath = 0;
            estimationTime = 0;
            estimTimeSet   = false;
        }
        //}

        isOnNavMesh = navAgent.isOnNavMesh;

        //if(navAgent.pathStatus == NavMeshPathStatus.PathInvalid)
        //{
        //    Debug.Log(name + " invalid path.");
        //}

        //Debug.Log(Vector3.Distance(navAgent.transform.position, currentDest));

        //Update the animator
        //if (navAgent.enabled)
        //{
        //    if (navAgent.remainingDistance > navAgent.stoppingDistance)
        //        Move(navAgent.desiredVelocity, false, false);
        //    else
        //        Move(Vector3.zero, false, false);
        //}

        //State changing to Retreat because we have spotted an item and is spooked
        if (sid.GetComponent <playerPossession>().IsPossessed() == true && TRIGGERED_floating == false && sid.GetComponent <playerPossession>().IsHidden() == false && currentState != State.State_Retreat)
        {
            if (isInLineOfSight() == true)
            {
                //Debug.Log("In sight!");
                ItemScaryRating    = sid.GetComponent <playerPossession>().PossessedItem.GetComponent <ItemController>().ItemScaryRating;
                TRIGGERED_floating = true; //This needs to be set to update the code in CIV_Retreat
                                           //Debug.Log("TRIGGERED FLOATING");
                FMODUnity.RuntimeManager.PlayOneShot(GameManager.Instance.audioCivSpotted, transform.position);

                m_stateMachine.ChangeState(this, new CIV_Retreat());
            }
        }

        //State changing to INTRIGUED if an itemPosition has been set, that means the ai has been in range of a recent lure mechanic used by the player
        if (alertedByItem && currentScareValue != scareThreshHoldMax)
        {
            alertedByItem = false;
            m_stateMachine.ChangeState(this, new CIV_Alert());
        }

        //State changing to Retreat, because the repel mechanic was used in playerPosession
        if (TRIGGERED_repel && currentScareValue != scareThreshHoldMax && currentState != State.State_Retreat)
        {
            ItemScaryRating = target.GetComponent <ItemController>().ItemScaryRating; //Target at this point is the object we are HIDING in - Set in playerPossesion
            m_stateMachine.ChangeState(this, new CIV_Retreat());
        }

        //Call update from this agents FSM
        if (m_stateMachine != null)
        {
            m_stateMachine.Update(this, Time.deltaTime);
        }


        //this.transform.rotation = Quaternion.Lerp(this.transform.rotation, Quaternion.LookRotation(new Vector3(this.velocity_.x, 0.0f, this.velocity_.y), Vector3.up), Time.deltaTime * 10f);
        //Debug.DrawLine(transform.position, transform.position + transform.forward, Color.green);

        //transform.Translate(Vector3.forward * Time.deltaTime);
    }
예제 #2
0
    public void STATE_Update(CivillianController agent, StateMachine_CIV stateMachine, float deltaTime)
    {
        //Check if we reached the scare threshold other wise continue with normal retreat state
        RunScaredExit();

        if (agent.hasDroppedEcto == false)
        {
            agent.hasDroppedEcto = true;
            Vector3 dropPos = new Vector3(currentAgent.transform.position.x, currentAgent.transform.position.y + 1f, currentAgent.transform.position.z);
            GameObject.Instantiate(ectoplasm, dropPos, currentAgent.transform.rotation);
        }

        //This is the code that makes the agent run away from whatever target has been set
        if (scared == false)
        {
            Debug.Log("Scared");
            //Get the direction away from the target object that they are trying to flee from
            if (currentAgent.TRIGGERED_hit)
            {
                dirAwayFromObject = currentAgent.transform.position - currentAgent.collidedItemPos;
            }
            else
            {
                dirAwayFromObject = currentAgent.transform.position - currentAgent.target.transform.position;
            }

            //Just minus a default value for now from the scared score
            //Overtime minus 1 from the scared value - possibly change in the future
            if (currentAgent.currentScareValue <= 0)
            {
                currentAgent.currentScareValue = 0;
            }
            else
            {
                scareDecreaseTimer -= Time.deltaTime;

                if (scareDecreaseTimer <= 0f)
                {
                    currentAgent.currentScareValue = currentAgent.currentScareValue - 1;
                    scareDecreaseTimer             = 3.0f;
                }
            }
            //Update the debug text
            currentAgent.txtScaredValue.text = currentAgent.currentScareValue.ToString();

            //If will is not close to the agent then don't flee
            if (dirAwayFromObject.magnitude > scaredRadius)
            {
                currentAgent.navAgent.velocity = Vector3.zero; //Stop the agent from moving

                currentAgent.m_Animator.SetBool("idle", true);

                //Debug.Log(timer);
                timer -= Time.deltaTime; //minus the time
                if (timer <= 0f)
                {
                    currentAgent.m_Animator.SetBool("idle", false);
                    stateMachine.ChangeState(agent, new CIV_Wander()); //Change back to wander
                    timer = 3.0f;                                      //Reset timer
                }
            }
            else //The player has moved close to the agent so move the agent
            {
                timer = 3.0f; //Reset the timer
                currentAgent.m_Animator.SetBool("idle", false);

                if (agent.navAgent.hasPath == false)
                {
                    agent.navAgent.SetDestination(RandomNavSphere(currentAgent.transform.position, 10, -1));
                }
            } //End else
        }     //End Scared if

        //Hack to turn back on the agent because we lost the reference of the otherAgent because they left the scene
        if (currentAgent.isStationary)
        {
            Debug.Log("stationay");
            currentAgent.GetComponent <NavMeshObstacle>().enabled = true;
            currentAgent.m_Animator.SetBool("idle", false);
            currentAgent.navAgent.enabled = true;
            currentAgent.isStationary     = false;
        }
    } //End update
    public Color civilianTop2Colour  = Color.black;     // 31/01/2018 Added by Mark - For custom colours

    // Use this for initialization
    void Start()
    {
        //Debug.Log("GetInstanceID: " + GetInstanceID());
        id = GetInstanceID();
        //Debug.Log("GetID: " + GetID());

        //Temporary possibly - shouldnt need to setup an enum for currentState when i already  have a way to detect it in statemachine but cant actually seem to get that working...
        currentState      = State.State_Wander;
        lineOfSight       = Camera.main.GetComponent <valueController>().civillianLineOfSight;
        hasDroppedEcto    = false;
        currentScareValue = 0;
        navAgent          = gameObject.GetComponent <NavMeshAgent>();
        m_Animator        = GetComponent <Animator>();
        //m_Rigidbody = GetComponent<Rigidbody>();

        //Find EndPoint
        endPoint = GameObject.FindWithTag("EndPoint").transform;

        //Assign a random priority to this agent, hopefully fixing the random npcs getting caught on eachother
        //navAgent.avoidancePriority = Random.Range(1, 99);

        //Increment the NPC count
        GameManager.Instance.NPCcount++;

        //If the text canvas is not in this position - will throw an error
        txtState       = transform.GetChild(0).GetChild(0).GetComponent <Text>(); //Accesses the txtState Text object in the heirachy attached to this Agent
        txtScaredValue = transform.GetChild(0).GetChild(1).GetComponent <Text>();

        //Show the debug states in editor
#if UNITY_EDITOR
        {
            txtState.enabled       = true;
            txtScaredValue.enabled = true;
        }
#else
        {
            txtState.enabled       = false;
            txtScaredValue.enabled = false;
        }
#endif

        //Set target to run away from
        target = GameManager.Instance.player.gameObject;
        sid    = target.gameObject;

        civIconStateScript         = GetComponent <script_civilianIconState>(); // 19-12-2017 Added by Mark
        civIconStateScript.myState = script_civilianIconState.gameState.normal; // 19-12-2017 Added by Mark

        //Fmod instance creation
        FMOD_ScaredInstance = FMODUnity.RuntimeManager.CreateInstance(GameManager.Instance.audioCivScared);

        //StateMachine creation - Setting Default State - Will inherit this from inspector
        m_stateMachine = new StateMachine_CIV();
        m_stateMachine.ChangeState(this, new CIV_Wander());

        rend = rendererGeo.GetComponent <Renderer>();                // 31/01/2018 Added by Mark - For custom colours
        rend.material.SetColor("_PantsColour", civilianPantsColour); // 31/01/2018 Added by Mark - For custom colours
        rend.material.SetColor("_Top1Colour", civilianTop1Colour);   // 31/01/2018 Added by Mark - For custom colours
        rend.material.SetColor("_Top2Colour", civilianTop2Colour);   // 31/01/2018 Added by Mark - For custom colours


        //DEBUGGING
        name = "Civ " + id;
    }