/// <summary>
    /// While the person is in the working state, Check if the work is done
    /// pop back to idle. Otherwise, keep working at the problem
    /// </summary>
    private void WorkingState()
    {
        if (currentTask == null)
        {
            return;
        }

        if (!currentTask.DoesWork)
        {
            currentTask.GetWorkDoneFunction?.Invoke();
            currentState = FinishState();
            return;
        }
        if (isCloseToFire && currentTask.Isinterruptible)
        {
            animatorController.ChangeState(currentTask.GetWorkAnimationType);
            ReturnSelectedTaskToTaskList();

            currentState = FinishState();
            return;
        }

        currentTask.UpdateWorkTimer(Time.deltaTime);
        if (currentTask.IsWorkDone)
        {
            currentTask.GetWorkDoneFunction?.Invoke();
            animatorController.ChangeState(currentTask.GetWorkAnimationType);
        }
    }
 public void WorkingAnimationDone()
 {
     if (isWaitingForAnimationEnd && currentTask != null && currentTask.IsWorkDone)
     {
         debugHolder.Log("Waiting for animation finished", eDebugImportance.Unimportant);
         isWaitingForAnimationEnd = false;
         currentState             = FinishState();
     }
 }
    /// <summary>
    /// While the person is in the GoToState, check the distance,
    /// if the person is close, pop the state
    /// if the person is far away, walk to the position
    /// </summary>
    private void WalkingState()
    {
        if (currentTask == null)
        {
            return;
        }
        if (isCloseToFire && currentTask.Isinterruptible)
        {
            ReturnSelectedTaskToTaskList();
            currentState = FinishState();
        }
        // No path was found to the target task
        if (path == null)
        {
            ReturnSelectedTaskToTaskList();

            currentState = FinishState();
        }
        else
        {
            //Check if the target is a open vertex
            if (associatedVertexTarget == null || (associatedVertexTarget != null && associatedVertexTarget.isPassable))
            {
                float distanceToTaskPosition = GetDistanceToPosition(target);
                if (distanceToTaskPosition >= minDistanceToTaskPosition)
                {
                    WalkToTarget();
                }
                else
                {
                    if (path != null && path.Count == 0)
                    {
                        this.transform.position = currentTask.GetInteractionPosition;
                        currentState            = FinishState();
                    }
                    else if (path != null)
                    {
                        target = path[0].point;
                        associatedVertexTarget = path[0].associatedVertex;
                        path.RemoveAt(0);
                    }
                    else if (path == null)
                    {
                        currentState = FinishState();
                    }
                }
            }
            // The vertex is not passable, so we cancel the task
            else
            {
                associatedVertexTarget = null;
                path.Clear();
                ReturnSelectedTaskToTaskList();
                currentState = FinishState();
            }
        }
    }
 private ePersonState GoToState(ePersonState state)
 {
     if (stateStack.Count > 0)
     {
         CallExitForState(stateStack.Peek());
     }
     stateStack.Push(state);
     CallEntryForState(state);
     return(state);
 }
    private void CallExitForState(ePersonState state)
    {
        switch (state)
        {
        case ePersonState.Idle:
            IdleExit();
            break;

        case ePersonState.GoTo:
            GoToExit();
            break;

        case ePersonState.Working:
            WorkingExit();
            break;
        }
    }
Beispiel #6
0
    /// <summary>
    /// Changes to specified behaviour, or a random one if no valid behaviour is specified
    /// </summary>
    /// <param name="behaviour">Valid ePersonState to switch to, or -1 to change to random behaviour.</param>
    private void changeToSpecificBehaviour(int behaviour)
    {
        chatPartner = null;
        nextBehaviourChangeCounter = CityStreamManager.Instance.BehaviourChangeInterval;

        switch (behaviour)
        {
        case (int)ePersonState.TALK_TO_NEIGHBOUR:

            Transform tempNeighbour = findNearestNeighbour(5.0f);

            if (tempNeighbour != null && tempNeighbour.gameObject.GetComponent <Person>().willStartConversation(this))
            {
                startConversationWithNeighbour(tempNeighbour.gameObject.GetComponent <Person>());
                currentState = ePersonState.TALK_TO_NEIGHBOUR;
            }
            else
            {
                // Look at my shoes and be idle for a bit
                myHead.transform.localRotation = Quaternion.Euler(new Vector3(30.0f, Random.Range(-5.0f, 5.0f), 0.0f));
                currentState = ePersonState.IDLE;
            }

            break;

        case (int)ePersonState.DISTRACTED:

            lookTarget                 = distractedLookTarget;
            distractedLookTarget       = null;
            nextBehaviourChangeCounter = CityStreamManager.Instance.DistractionDuration;
            endConversationWithNeighbour();
            currentState = ePersonState.DISTRACTED;
            break;

        case (int)ePersonState.WATCH_PARADE:
        default:

            lookTarget = Camera.main.gameObject.transform;
            // When watching parade, it keeps focus for a little longer than other behaviours
            nextBehaviourChangeCounter *= 1.5f;
            currentState = ePersonState.WATCH_PARADE;
            break;
        }
    }
    public void StartUp()
    {
        health = GetComponent <Health>();
        if (health == null)
        {
            Debug.LogError("Could not find Health component", this);
        }
        debugHolder     = ScriptableObject.CreateInstance <PersonAIDebugHolder>();
        levelGeneration = FindObjectOfType <LevelGeneration>();

        animatorController   = GetComponent <AnimationCommandController>();
        traversalGraphHolder = FindObjectOfType <TraversalGraphHolder>();
        traversalAStar       = new TraversalAStarNavigation(traversalGraphHolder);

        personalTasks = ScriptableObject.CreateInstance <TaskListHolder>();
        currentState  = GoToState(startingState);

        FindCurrentRoom();
    }
    /// <summary>
    /// The Idle state checks the transitions to go to the next states
    /// If the person is too far from the position, change states,
    /// If the person is at the position, change states
    /// </summary>
    private void IdleState()
    {
        if (currentTask == null || !currentTask.IsTaskValid)
        {
            return;
        }
        if (isCloseToFire && currentTask.Isinterruptible)
        {
            ReturnSelectedTaskToTaskList();
            return;
        }
        float distanceToTaskPosition = GetDistanceToTaskPosition(currentTask);

        if (distanceToTaskPosition >= minDistanceToTaskPosition)
        {
            currentState = GoToState(ePersonState.GoTo);
        }
        else
        {
            currentState = GoToState(ePersonState.Working);
        }
    }
        private void Update()
        {
            switch (_personState)
            {
            case ePersonState.Idling:
                Transform pointToJump = null;

                if (_jump)
                {
                    var nextJumpPointIdx = _currentJumpPointIdx + 1;
                    nextJumpPointIdx %= jumpingPoints.Count;
                    pointToJump       = jumpingPoints[nextJumpPointIdx];

                    _jump = false;
                }

                var jumpDir = Input.GetAxis("Horizontal");
                if (jumpDir > 0)
                {
                    Transform closestRight = null;
                    for (int i = 0; i < jumpingPoints.Count; i++)
                    {
                        if (jumpingPoints[i] == jumpingPoints[_currentJumpPointIdx] ||
                            jumpingPoints[i].position.x < jumpingPoints[_currentJumpPointIdx].position.x)
                        {
                            continue;
                        }

                        if (closestRight == null)
                        {
                            closestRight = jumpingPoints[i];
                        }

                        if (jumpingPoints[i].position.x - _transform.position.x <
                            (closestRight.position.x - _transform.position.x))
                        {
                            closestRight = jumpingPoints[i];
                        }
                    }

                    pointToJump = closestRight;
                }
                else if (jumpDir < 0)
                {
                    Transform closestLeft = null;
                    for (int i = 0; i < jumpingPoints.Count; i++)
                    {
                        if (jumpingPoints[i] == jumpingPoints[_currentJumpPointIdx] ||
                            jumpingPoints[i].position.x > jumpingPoints[_currentJumpPointIdx].position.x)
                        {
                            continue;
                        }

                        if (closestLeft == null)
                        {
                            closestLeft = jumpingPoints[i];
                        }

                        if (_transform.position.x - jumpingPoints[i].position.x <
                            (_transform.position.x - closestLeft.position.x))
                        {
                            closestLeft = jumpingPoints[i];
                        }
                    }

                    pointToJump = closestLeft;
                }

                if (pointToJump != null && pointToJump != jumpingPoints[_currentJumpPointIdx])
                {
                    _personState = ePersonState.Jumping;

                    _startJumpPos     = jumpingPoints[_currentJumpPointIdx].position;
                    _endJumpPos       = pointToJump.position;
                    _jumpTimeProgress = 0;
                    var startToEndVector = (_endJumpPos - _startJumpPos);
                    _jumpDirNormal = new Vector3(startToEndVector.normalized.y, Mathf.Abs(startToEndVector.normalized.x), 0);

                    _currentJumpPointIdx = jumpingPoints.IndexOf(pointToJump);

                    personAnimator.SetTrigger("Jump");
                    _personReflectionAnimator.SetTrigger("Jump");
                }

                break;

            case ePersonState.Jumping:
                _jumpTimeProgress += Time.deltaTime;
                var jumpTimeProgressNorm     = _jumpTimeProgress / jumpDuration;
                var jumpDistanceProgressNorm = jumpSpeedCurve.Evaluate(jumpTimeProgressNorm);
                if (jumpTimeProgressNorm >= 1)
                {
                    _transform.position = _endJumpPos;
                    _personState        = ePersonState.Idling;
                    _jump = false;
                    _personModel.NumJumps++;
                    _transform.localScale = new Vector3(_transform.localScale.x * -1, _transform.localScale.y, _transform.localScale.z);
                }
                else
                {
                    var jumpDisplacement = Mathf.Sin(jumpDistanceProgressNorm * Mathf.PI) * jumpCurveHeight * _jumpDirNormal;
                    var travelPosition   = Vector3.Lerp(_startJumpPos, _endJumpPos, jumpDistanceProgressNorm);
                    _transform.position = travelPosition + jumpDisplacement;
                    reflection.transform.localPosition = _reflectionDefaultLocalPos - reflectionDisplacement * jumpDisplacement;
                }

                break;

            default:
                break;
            }
        }