//function to be performed in idle state, containes transitions to other states void idle() { posTimer = 30; posTimer2 = 25; if (FleeInu(LevelMask, home)) { State = OniState.Flee; return; } seen = false; seen = SeeObject(PlayerObject, LevelMask, home); if (seen) { //if player has been seen chase awake = true; State = OniState.Chase; return; } foundFootprint = SeeFootprint(allNodes, LevelMask, home); if (foundFootprint != null) { //if footprints found follow nextFootprint = foundFootprint; State = OniState.Follow; return; } if (root != null) { //if neither and root exist, attempt to patrol State = OniState.Patrol; return; } }
//function to execute in stun state, containes transitions, and decrements stun timer void stun() { posTimer = 30; posTimer2 = 25; //decrement stun timer stunTimer -= Time.deltaTime; //if enough timer has passed transition to appropiate state if (stunTimer <= 0) { animState = OniAnim.Idle; seen = false; seen = SeeObject(PlayerObject, LevelMask, home); foundFootprint = SeeFootprint(allNodes, LevelMask, home); if (seen) { State = OniState.Chase; return; } else if (foundFootprint != null && awake == true) { nextFootprint = foundFootprint; State = OniState.Follow; return; } else { State = OniState.Idle; return; } } }
//if oni recieves stun message execute the following code void Stun() { //transition to stun state State = OniState.Stun; animState = OniAnim.Stunned; //set timer stunTimer = 15; //stop motion agent.SetDestination(transform.position); //stun has priority over fleeing inu fleeingInu = false; }
void look() { posTimer = 30; posTimer2 = 25; lookTimer -= Time.deltaTime; if (TestDebug) { print("lookTimer" + lookTimer); } if (FleeInu(LevelMask, home)) { State = OniState.Flee; return; } seen = false; seen = SeeObject(PlayerObject, LevelMask, home); if (seen) { //if player has been seen chase awake = true; State = OniState.Chase; return; } foundFootprint = SeeFootprint(allNodes, LevelMask, home); if (foundFootprint != null) { //if footprints found follow nextFootprint = foundFootprint; State = OniState.Follow; return; } transform.Rotate(Vector3.up * (360 * Time.deltaTime)); if (lookTimer <= 0) { if (root != null) { lookBlocker = 10; //old destination reached, update patrol path closest = null; closest = UpdateClosest(closest, nodes, currentNode, previous, previous2, rb); if (closest != null) { previous2 = previous; previous = currentNode; currentNode = closest; } State = OniState.Patrol; return; } } }
//function called at initialization of oni void Start() { //intialize variables anim = GetComponentInChildren <Animator>(); rb = GetComponent <Rigidbody>(); home = gameObject.transform.position; startingRotation = gameObject.transform.rotation; actorID = GetComponent <Actor>(); State = OniState.Idle; animState = OniAnim.Idle; awake = false; PlayerObject = GameObject.FindGameObjectWithTag("Player"); oldPosition = home; posTimer = 6; posTimer2 = 23; root = MazeGenerator.getSectionBasedOnLocation(home); if (root != null) { nodes = MazeGenerator.GetIntersectionNodes(root); } fleeTimer = 5; fleeingInu = false; currentNode = StartingNode; //find home node based on location, a nodes location is its individual values - 8 and then divided by 6 column = (int)((home.x - 8) / 6); row = (int)((home.z - 8) / 6); //print("oni home: x " + home.x + " col: " + column + " z: " + home.z + " row: " + row); allNodes = MazeGenerator.nodesInSection(root); foreach (MazeNode n in allNodes) { if (n.Col == column && n.Row == row) { homeNode = n; } } floor = homeNode.Floor; agent = GetComponent <NavMeshAgent>(); //turn of default nav mesh movement as it doesn't include gravity agent.updatePosition = false; agent.updateRotation = true; agent.nextPosition = transform.position; //transform.position = agent.nextPosition; agent.Warp(transform.position); //print("trans" + transform.position); //print("nav" + agent.nextPosition); }
public void BeginLeave() { GetComponent <Collider>().enabled = false; state = OniState.Leave; }
//if oni collides with a safe zone it will flee back to home void SafeZoneCollision() { State = OniState.Flee; }
//function to execute in follow state, contains transitions, and code to follow footprints towards player void follow() { //agent.ResetPath(); if (FleeInu(LevelMask, home)) { State = OniState.Flee; return; } if (Vector3.Distance(transform.position, home) < 2) { //if positions have not changed enough determine Oni to be stuck and change behavior pattern //reset timers to give chance to move before checking again if (stuckBlocker <= 0) { if (IsStuck(newPosition, oldPosition, oldPosition2)) { posTimer = 0; posTimer = 5; if (TestDebug) { print("resetting path in patrol"); } agent.ResetPath(); previous2 = previous; previous = currentNode; currentNode = null; State = OniState.Flee; stuckBlocker = 30; return; } } } seen = false; seen = SeeObject(PlayerObject, LevelMask, home); if (seen) { State = OniState.Chase; nextFootprint = null; return; } //if there is no next footprint try to find a new footprint to follow if (nextFootprint == null) { foundFootprint = SeeFootprint(allNodes, LevelMask, home); if (foundFootprint == null) { State = OniState.Idle; return; } if (foundFootprint != null) { nextFootprint = foundFootprint; agent.SetDestination(foundFootprint.transform.position); } } //else move towards next footprint else { if (Vector3.Distance(transform.position, nextFootprint.gameObject.transform.position) < 2) { //update next footprint to continue following the trail nextFootprint = nextFootprint.getNext(); if (nextFootprint == null) { //print("next dne"); } } if (nextFootprint != null) { //print("nextfootprint " + nextFootprint.gameObject.transform.position); agent.SetDestination(nextFootprint.gameObject.transform.position); } } }
//function to execute in flee state, contains transitions, and code to return to spawn position void flee() { posTimer = 30; posTimer2 = 10; //if enough time has passed the oni may interrupt flee to chase player or follow footprints fleeTimer -= Time.deltaTime; if (fleeTimer <= 0) { seen = false; seen = SeeObject(PlayerObject, LevelMask, home); if (seen) { awake = true; State = OniState.Chase; return; } foundFootprint = SeeFootprint(allNodes, LevelMask, home); if (foundFootprint != null) { nextFootprint = foundFootprint; State = OniState.Follow; return; } } //return to home position agent.ResetPath(); foreach (MazeNode n in currentPath) { n.EnemyPathNode = false; } //make sure that all the current pathnodes are made not enemy path nodes //check iterate through to see if there is an obstacle in the way //if there is, set the new destination as the spot right before the obstacle //otherwise, set the home as destination //either way, set path to location as enemy path nodes targetPos = new Vector3(); if (fleeTarget == null) { presentNode = new MazeNode(); obstacle = false; column = homeNode.Col; row = homeNode.Row; foreach (MazeNode n in MazeGenerator.nodesInSection(root)) { if (n.Col == column && n.Row == row) { presentNode = n; } } possiblePath = MazeGenerator.GetPath2(presentNode, homeNode); prevCheckNode = presentNode; foreach (MazeNode n in possiblePath) { if (n.EnemyPathNode || GameManager.trapNode(n)) { if (homeNode.Col == 9 && homeNode.Row == 2) { print(column + " " + row); } fleeTarget = prevCheckNode; obstacle = true; break; } prevCheckNode = n; } if (!obstacle) { fleeTarget = homeNode; } fleePath = MazeGenerator.GetPath2(presentNode, fleeTarget); foreach (MazeNode n in fleePath) { n.EnemyPathNode = true; } } targetPos = new Vector3(fleeTarget.Col * 6 + 8, fleeTarget.Floor * 30, fleeTarget.Row * 6 + 8); if (homeNode.Col == 9 && homeNode.Row == 2) { print(fleeTarget.Col + " " + fleeTarget.Row); } agent.SetDestination(targetPos); if (Vector3.Distance(transform.position, targetPos) < 2) { //undo path nodes except the one she ends on foreach (MazeNode n in fleePath) { if (n.Col != fleeTarget.Col || n.Row != fleeTarget.Row) { n.EnemyPathNode = false; } } fleeTarget = null; State = OniState.Idle; gameObject.transform.rotation = startingRotation; return; } }
//function to execute in chase state, contains transitions, code to move towards player, and code to kill player void chase() { //ensure old path is cleared //agent.ResetPath(); if (FleeInu(LevelMask, home)) { State = OniState.Flee; return; } if (Vector3.Distance(transform.position, home) < 2) { //if positions have not changed enough determine Oni to be stuck and change behavior pattern //reset timers to give chance to move before checking again if (stuckBlocker <= 0) { if (IsStuck(newPosition, oldPosition, oldPosition2)) { posTimer = 0; posTimer = 5; if (TestDebug) { print("resetting path in patrol"); } agent.ResetPath(); previous2 = previous; previous = currentNode; currentNode = null; State = OniState.Flee; stuckBlocker = 30; return; } } } //check if oni can still see player seen = false; seen = SeeObject(PlayerObject, LevelMask, home); if (!seen) { foundFootprint = SeeFootprint(allNodes, LevelMask, home); if (foundFootprint != null) { nextFootprint = foundFootprint; State = OniState.Follow; return; } else { State = OniState.Idle; return; } } //rayDirection = playerTransform.position - transform.position; //rayDirection.y = 0; //check if player is within the kill distance playerCloseToEnemy = Vector3.Distance(playerTransform.position, transform.position) < KillDistance; if (playerCloseToEnemy) { //if VR device is present the player's actor component is in its parent if (UnityEngine.XR.XRDevice.isPresent) { player = PlayerObject.GetComponentInParent <Actor>(); GameManager.Instance.ActorKilled(actorID, player); } else { //otherwise the player's actor component is a part of the player object GameManager.Instance.ActorKilled(actorID, PlayerObject.GetComponent <Actor>()); } State = OniState.GameOver; //let game manager know that the game should end GameManager.Instance.GameOver(); if (TestDebug) { print("GameOver"); } } //have oni set the player's current position to be its destination agent.SetDestination(playerTransform.position); }
//function to execute in patrol state, contains transitions as well as code to navigate patrol nodes void patrol() { if (FleeInu(LevelMask, home)) { State = OniState.Flee; return; } if (Vector3.Distance(transform.position, home) < 2) { //if positions have not changed enough determine Oni to be stuck and change behavior pattern //reset timers to give chance to move before checking again if (stuckBlocker <= 0) { if (IsStuck(newPosition, oldPosition, oldPosition2)) { posTimer = 0; posTimer = 5; if (TestDebug) { print("resetting path in patrol"); } agent.ResetPath(); previous2 = previous; previous = currentNode; currentNode = null; State = OniState.Flee; stuckBlocker = 30; return; } } } seen = false; seen = SeeObject(PlayerObject, LevelMask, home); if (seen) { awake = true; State = OniState.Chase; return; } foundFootprint = SeeFootprint(allNodes, LevelMask, home); if (foundFootprint != null) { nextFootprint = foundFootprint; State = OniState.Follow; return; } //if nodes exist if (root != null) { //container for current node's position //bool to check if current was set and not updated bool setCurrent = false; if (currentNode == null) { //if current does not exist closest = null; //call set to start patrol path closest = SetClosest(closest, homeNode, nodes, rb); //update current currentNode = closest; //update previous if (previous == null) { previous = currentNode; previous2 = previous; } //indicate current was set setCurrent = true; } //if current exists if (currentNode != null) { //get current node's position currentNodePosition = new Vector3(currentNode.Col * 6 + 8, currentNode.Floor * 30, currentNode.Row * 6 + 8); //if current was not set this game loop, check to see if updating is necessary if (setCurrent == false) { if (Vector3.Distance(transform.position, currentNodePosition) < 2) { if (lookBlocker <= 0) { lookTimer = 4; agent.SetDestination(transform.position); state = OniState.LookAround; } else { MazeNode closest = null; closest = UpdateClosest(closest, nodes, currentNode, previous, previous2, rb); if (closest != null) { /*closest = null; * closest = UpdateClosest(closest, nodes, currentNode, previous, previous2, rb); * if (closest != null) * { * previous2 = previous; * previous = currentNode; * currentNode = closest; * }*/ previous2 = previous; previous = currentNode; currentNode = closest; } } } //update current node's postion if (currentNode != null) { currentNodePosition = new Vector3(currentNode.Col * 6 + 8, currentNode.Floor * 30, currentNode.Row * 6 + 8); } } //set A.I. to move to current node agent.SetDestination(currentNodePosition); } } }
//determin oni's actions for the current game loop void LateUpdate() { /*if(Time.deltaTime > (2/100)) * { * print("onistate" + state); * }*/ agent.nextPosition = transform.position; if (TestDebug) { print("onistate" + state); //print("trans2" + transform.position); //print("nav2" + agent.nextPosition); /*agent.destination = new Vector3(0, 0, 0); * MoveYokai(controller, agent); * return;*/ } //print("Oni state " + state); if (state == OniState.Flee) { print(homeNode.Col + " " + homeNode.Row); } if (actorID == null) { actorID = GetComponent <Actor>(); } if (controller == null) { controller = GetComponent <CharacterController>(); } //update player transform if (PlayerObject != null) { playerTransform = PlayerObject.transform; } else { playerTransform = null; } if (stunTimer > 0) { if (state != OniState.Stun) { state = OniState.Stun; } } if (stuckBlocker > 0) { stuckBlocker -= Time.deltaTime; } //determine action to take based on state in state machine switch (state) { case OniState.Idle: idle(); break; case OniState.Patrol: patrol(); break; case OniState.LookAround: look(); break; case OniState.Search: search(); break; case OniState.Chase: chase(); break; case OniState.Flee: flee(); break; case OniState.Dead: dead(); break; case OniState.Follow: follow(); break; case OniState.Stun: stun(); break; case OniState.GameOver: gameOver(); break; } //update animations switch (animState) { case OniAnim.Idle: animIdle(); break; case OniAnim.Walk: animWalk(); break; case OniAnim.Run: animRun(); break; case OniAnim.Attack: animAttack(); break; case OniAnim.Stunned: animStunned(); break; case OniAnim.Look: animLook(); break; } //if aware of player turn towards them if (awake == true) { TurnTowardsPlayer(PlayerObject); } //if enough timer has passed update recordings of positions posTimer -= Time.deltaTime; if (posTimer <= 0) { posTimer = 30; oldPosition = newPosition; newPosition = transform.position; } posTimer2 -= Time.deltaTime; if (posTimer2 <= 0) { posTimer2 = 25; oldPosition2 = oldPosition; oldPosition = transform.position; } if (lookBlocker > 0) { lookBlocker -= Time.deltaTime; if (TestDebug) { print("look blocker" + lookBlocker); } } //move yokai based on state MoveYokai(controller, agent); }