Example #1
0
        //a method that stops the unit's movement.
        public void Stop()
        {
            DisablePendingMovement(true);
            AudioManager.Stop(unit.AudioSourceComp);                   //stop the movement audio from playing

            if (unit.HealthComp.IsDead() == true || isMoving == false) //if the unit is already dead or not moving, do not proceed.
            {
                return;
            }

            SetMaxSpeed(speed); //set the movement speed to the default one in case it was changed by the Attack on Escape component.

            if (!useNavAgent)   //if we're using the NavAgent to move the unit, it will handle keeping the height of the unit in check
            {
                StopCoroutine(heightCheckCoroutine);
            }

            isMoving = false;                      //marked as not moving

            unit.SetAnimState(UnitAnimState.idle); //get into idle state

            //unit doesn't have a target APC or Portal to move to anymore
            targetAPC    = null;
            targetPortal = null;

            rotationTarget = RTSHelper.GetLookRotation(transform, lookAtTarget); //update the rotation target using the registered lookAt position.

            UpdateTargetPositionCollider(transform.position);                    //set the target position's collider to the current unit position since the movement has stopped.
        }
        //a method that stops the unit's movement.
        /// <summary>
        /// Stops the current unit's movement.
        /// </summary>
        /// <param name="prepareNextMovement">When true, not all movement settings will be reset since a new movement command will be followed. Default value: false.</param>
        public void Stop(bool prepareNextMovement = false)
        {
            DisablePendingMovement(true);
            AudioManager.Stop(unit.AudioSourceComp); //stop the movement audio from playing

            if (isMoving == false)                   //if the unit is not moving already then stop here
            {
                return;
            }

            isMoving = false;   //marked as not moving

            SetMaxSpeed(speed); //set the movement speed to the default one in case it was changed by the Attack on Escape component.

            //unit doesn't have a target APC or Portal to move to anymore
            targetAPC    = null;
            targetPortal = null;

            if (!resetPendingMovement && prepareNextMovement) //if we're preparing for another movement command that will follow this call here, then no need to reset some of the params
            {
                return;
            }

            if (!useNavAgent) //if we're using the NavAgent to move the unit, it will handle keeping the height of the unit in check
            {
                StopCoroutine(heightCheckCoroutine);
            }
            else
            {
                navAgent.isStopped = true;                                       //using the NavAgent component? then stop updating the unit's position.
            }
            rotationTarget = RTSHelper.GetLookRotation(transform, lookAtTarget); //update the rotation target using the registered lookAt position.

            UpdateTargetPositionCollider(transform.position);                    //set the target position's collider to the current unit position since the movement has stopped.

            if (!unit.HealthComp.IsDead())                                       //if the unit is not dead
            {
                unit.SetAnimState(UnitAnimState.idle);                           //get into idle state
            }
        }
Example #3
0
        //moving the unit along its computed path
        private void MoveAlongPath()
        {
            float currentDistance = (transform.position - currentDestination).sqrMagnitude; //compute the distance between the current unit's position and the next corner in the path

            //update the rotation as long as the unit is moving to look at the next corner in the path queue.
            transform.rotation = Quaternion.Slerp(transform.rotation, RTSHelper.GetLookRotation(transform, currentDestination), Time.deltaTime * rotationDamping);

            //if the unit can't move before it faces a certain angle towards its next destination in the path
            if (canMoveRotate == false && facingNextDestination == false)
            {
                //keep checking if the angle between the unit and its next destination
                Vector3 lookAt = currentDestination - transform.position;
                lookAt.y = 0.0f;

                //as long as the angle is still over the min allowed movement angle, then do not proceed to keep moving
                if (Vector3.Angle(transform.forward, lookAt) > minMoveAngle)
                {
                    return;
                }
                else
                {
                    facingNextDestination = true;
                }
            }

            //if this is the last corner or the player's distance to the next corner reaches a min value, move to the next corner, if not keep moving the player towards the current corner.
            if (currentDistance > stoppingDistance || navPathCornerQueue.Count == 0)
            {
                //acceleration:
                CurrentSpeed = CurrentSpeed >= maxSpeed ? maxSpeed : CurrentSpeed + acceleration * Time.deltaTime;

                //move the unit on the x and z axis using the assigned speed
                transform.position += new Vector3(currentDirection.x * CurrentSpeed * Time.deltaTime, 0.0f, currentDirection.z * CurrentSpeed * Time.deltaTime);
            }
            else
            {
                GetNextCorner();
            }
        }
        //moving the unit along its computed path
        private void MoveAlongPath()
        {
            if (!useNavAgent || navAgent.isStopped) //only if not using the NavAgent component for movement or when the nav agent is stopped.
            //update the rotation as long as the unit is moving to look at the next corner in the path queue.
            {
                transform.rotation = Quaternion.Slerp(
                    transform.rotation,
                    RTSHelper.GetLookRotation(transform, currentDestination),
                    Time.deltaTime * mvtAngularSpeed);
            }

            //if the unit can't move before it faces a certain angle towards its next destination in the path
            if (canMoveRotate == false && facingNextDestination == false)
            {
                //keep checking if the angle between the unit and its next destination
                Vector3 lookAt = currentDestination - transform.position;
                lookAt.y = 0.0f;

                //as long as the angle is still over the min allowed movement angle, then do not proceed to keep moving
                if (Vector3.Angle(transform.forward, lookAt) > minMoveAngle)
                {
                    if (useNavAgent && !navAgent.isStopped) //using NavAgent movement? stop it if it's not already stopped
                    {
                        navAgent.isStopped = true;
                    }
                    return;
                }
                else
                {
                    facingNextDestination = true;
                }
            }

            if (useNavAgent)                                         //not using the NavAgent to move the unit, stop here since the NavAgent component will handle actual movement
            {
                if (currentDestination != navAgent.steeringTarget)   //if the next corner/destination on path has been updated
                {
                    facingNextDestination = false;                   //to trigger checking for correct rotation properties
                    currentDestination    = navAgent.steeringTarget; //assign new corner in path
                }

                if (navAgent.isStopped) //using NavAgent movement? start mvt if it has been stopped
                {
                    navAgent.isStopped = false;
                }
                return;
            }

            float currentDistance = (transform.position - currentDestination).sqrMagnitude; //compute the distance between the current unit's position and the next corner in the path

            //if this is the last corner or the player's distance to the next corner reaches a min value, move to the next corner, if not keep moving the player towards the current corner.
            if (currentDistance > stoppingDistance || navPathCornerQueue.Count == 0)
            {
                //acceleration:
                CurrentSpeed = CurrentSpeed >= maxSpeed ? maxSpeed : CurrentSpeed + acceleration * Time.deltaTime;

                //move the unit on the x and z axis using the assigned speed
                transform.position += new Vector3(currentDirection.x * CurrentSpeed * Time.deltaTime, 0.0f, currentDirection.z * CurrentSpeed * Time.deltaTime);
            }
            else
            {
                GetNextCorner();
            }
        }
        void FixedUpdate()
        {
            if (unit.HealthComp.IsDead()) //if the unit is already dead
            {
                return;                   //do not update movement
            }
            if (isMoving == false || (canMoveRotate == false && facingNextDestination == false))
            {
                //deceleration (when either the unit is not moving or rotating to face next destination)
                if (CurrentSpeed > 0.0f)
                {
                    CurrentSpeed -= acceleration * Time.deltaTime;
                }

                if (isMoving == false && canIdleRotate == true && rotationTarget != Quaternion.identity)                          //can the unit rotate when idle (and the unit is not moving) + there's a valid rotation target
                {
                    if (lookAtTransform != null)                                                                                  //if there's a target object to look at
                    {
                        rotationTarget = RTSHelper.GetLookRotation(transform, lookAtTransform.position);                          //keep updating the rotation target as the target object might keep changing position
                    }
                    transform.rotation = Quaternion.Slerp(transform.rotation, rotationTarget, Time.deltaTime * idleAngularSpeed); //smoothly update the unit's rotation
                }
            }

            if (isMoving == true && unit.IsInMvtState()) //if the unit is currently moving
            {
                if (navPath == null)                     //if the unit's path is invalid
                {
                    Stop();                              //stop the unit movement.
                }
                else //valid path
                {
                    //only if either the unit can move and rotate at the same time or it can't move and rotate and it's still hasn't faced its next destination in the path
                    if (canMoveRotate == false || facingNextDestination == true)
                    {
                        if (mvtCheckTimer > 0) //movement check timer -> making sure the unit is not stuck at its current position
                        {
                            mvtCheckTimer -= Time.deltaTime;
                        }
                        if (mvtCheckTimer < 0)                                              //the movement check duration is hardcoded to 2 seconds, while this is only a temporary solution for the units getting stuck issue, a more optimal solution will be soon presented
                        {
                            if (Vector3.Distance(transform.position, lastPosition) <= 0.1f) //if the time passed and we still in the same position (unit is stuck) then stop the movement
                            {
                                Stop();
                                unit.CancelJob(Unit.jobType.all); //cancel all unit jobs.
                            }
                            ReloadMvtCheck();
                        }
                    }

                    MoveAlongPath(); //move the unit along its path using this component

                    //if the unit is currently moving towards an APC, check whether the APC has moved by the stopping distance
                    if (targetAPC != null && Vector3.Distance(lastAPCInteractionTarget, targetAPC.GetInteractionPosition()) > stoppingDistance)
                    {
                        APC nextAPC = targetAPC;
                        Stop(); //stop current movement

                        //we need to recalculate the unit's path so it can move towards the new APC's interaction position
                        nextAPC.Move(unit, false);
                        return;
                    }

                    if (DestinationReached == false) //check if the unit has reached its target position or not
                    {
                        DestinationReached = Vector3.Distance(transform.position, finalDestination) <= stoppingDistance;
                    }
                }

                if (DestinationReached == true)
                {
                    APC    nextAPC    = targetAPC;
                    Portal nextPortal = targetPortal;

                    Stop();                      //stop the unit mvt

                    if (nextAPC != null)         //if the unit is looking to get inside a APC
                    {
                        nextAPC.Add(unit);       //get in the APC
                        lookAtTransform = null;  //so that the unit won't look at the APC when leaving it
                    }
                    else if (nextPortal != null) //if the unit is moving to get inside a portal
                    {
                        nextPortal.Add(unit);    //go through the portal
                    }
                }
            }
        }
Example #6
0
        void FixedUpdate()
        {
            if (pendingBuildings.Count > 0)                       //if that are pending buildings to be placed:
            {
                if (pendingBuildings[0].buildingInstance == null) //invalid building instance:
                {
                    StopPlacingBuilding();                        //discard this pending building slot
                    return;                                       //do not continue
                }

                float centerDistance = Vector3.Distance(pendingBuildings[0].buildingInstance.transform.position, pendingBuildings[0].buildingCenter.transform.position);
                //if building center of the current pending building is destroyed while building is getting placed:
                //or if the building is too far away or too close from the center
                if (pendingBuildings[0].buildingCenter == null || centerDistance > pendingBuildings[0].buildingCenter.BorderComp.Size)
                {
                    StopPlacingBuilding(); //Stop placing building.
                    return;
                }

                //building movement timer:
                if (timer > 0)
                {
                    timer -= Time.deltaTime;
                }
                else
                {
                    //reset timer:
                    timer = moveTimer + (timerInc * incVal);
                    incVal++;

                    //move building away from build around pos.
                    Vector3 mvtDir = (pendingBuildings[0].buildingInstance.transform.position - pendingBuildings[0].buildAroundPos).normalized;
                    mvtDir.y = 0.0f;
                    if (mvtDir == Vector3.zero)
                    {
                        mvtDir = new Vector3(1.0f, 0.0f, 0.0f);
                    }
                    pendingBuildings[0].buildingInstance.transform.position += mvtDir * moveDistance;
                }

                //move the building around its build around position:
                Quaternion buildingRotation = pendingBuildings[0].buildingInstance.transform.rotation; //save building rotation
                //this will move the building around the build around pos which what we want but it will also affect the build rotation..
                pendingBuildings[0].buildingInstance.transform.RotateAround(pendingBuildings[0].buildAroundPos, Vector3.up, rotationSpeed * Time.deltaTime);

                if (pendingBuildings[0].rotate == true) //if the building should be rotated to face its center object
                {
                    pendingBuildings[0].buildingInstance.transform.rotation = RTSHelper.GetLookRotation(pendingBuildings[0].buildingInstance.transform, pendingBuildings[0].buildAroundPos, true);
                }
                else
                {
                    pendingBuildings[0].buildingInstance.transform.rotation = buildingRotation; //set initial rotation
                }
                //placement delay timer:
                if (placementDelay > 0)
                {
                    placementDelay -= Time.deltaTime;
                }
                else //if the placement delay is through, NPC faction is now allowed to place faction:
                {
                    //Check if the building is in a valid position or not:
                    pendingBuildings[0].buildingInstance.PlacerComp.CheckBuildingPos();

                    //can we place the building:
                    if (pendingBuildings[0].buildingInstance.PlacerComp.CanPlace == true)
                    {
                        PlaceBuilding();
                        return;
                    }
                }
            }
        }
        /// <summary>
        /// Updates the current pending building position to find a suitable placement position.
        /// </summary>
        private void FixedUpdate()
        {
            if (!IsActive)
            {
                return;
            }

            if (currPendingBuilding.instance == null) //invalid building instance:
            {
                StopPlacingBuilding();                //discard this pending building slot
                return;                               //do not continue
            }

            //if building center of the current pending building is destroyed while building is getting placed:
            //or if the building is too far away or too close from the center
            if (currPendingBuilding.center == null ||
                Vector3.Distance(currPendingBuilding.instance.transform.position, currPendingBuilding.center.transform.position) > currPendingBuilding.center.BorderComp.Size)
            {
                StopPlacingBuilding(); //Stop placing building.
                return;
            }

            //when the pending building movement timer is through:
            if (placementMoveTimer <= 0.0f)
            {
                //reset timer:
                placementMoveTimer = placementMoveReload.getRandomValue()
                                     + (placementMoveReloadInc.getRandomValue() * placementMoveReloadIncCount);
                placementMoveReloadIncCount++;

                //move building away from build around position by the defined movement distance
                Vector3 mvtDir = (currPendingBuilding.instance.transform.position - currPendingBuilding.buildAroundPos).normalized;
                mvtDir.y = 0.0f;
                if (mvtDir == Vector3.zero)
                {
                    mvtDir = new Vector3(1.0f, 0.0f, 0.0f);
                }
                currPendingBuilding.instance.transform.position += mvtDir * moveDistance.getRandomValue();
            }

            //move the building around its build around position:
            Quaternion buildingRotation = currPendingBuilding.instance.transform.rotation; //save building rotation

            //this will move the building around the build around pos which what we want but it will also affect the build rotation..
            currPendingBuilding.instance.transform.RotateAround(currPendingBuilding.buildAroundPos, Vector3.up, rotationSpeed * Time.deltaTime);

            if (currPendingBuilding.rotate == true) //if the building should be rotated to face its center object
            {
                currPendingBuilding.instance.transform.rotation = RTSHelper.GetLookRotation(currPendingBuilding.instance.transform, currPendingBuilding.buildAroundPos, true);
            }
            else
            {
                currPendingBuilding.instance.transform.rotation = buildingRotation; //set initial rotation
            }
            if (placementDelayTimer <= 0)                                           //if the placement delay is through, NPC faction is now allowed to place faction:
            {
                //Check if the building is in a valid position or not:
                currPendingBuilding.instance.PlacerComp.CheckBuildingPos();

                //can we place the building:
                if (currPendingBuilding.instance.PlacerComp.CanPlace == true)
                {
                    PlaceBuilding();
                    return;
                }
            }
        }