/// <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; } }
/// <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; } }