using System.Collections; using System.Collections.Generic; using UnityEngine; public class AI : Character { public List frontier = new List(); public List explored = new List(); public int sensingRange = 6; //感知范围 public int attackRange = 1; //攻击范围 public int attackCost = 4; //攻击消耗 public AISkill skill; Character goal = null; Cell cell; float timer = 0.5f; public IEnumerator ApplyAI() { //Debug.Log("StartAI"); if(FindNearestEnemy() > sensingRange) //观测周围是否有敌人 yield return null; //Debug.Log("The goal is " + goal.transform.position.x + "," + goal.transform.position.y); RaycastHit2D hit = Physics2D.Raycast(transform.position,Vector2.up,1.0f,LayerMask.GetMask("Cells")); cell = hit.collider.GetComponent(); cell.parent = null; cell.gCost = 0; cell.hCost = 1000; frontier.Add(cell); yield return StartCoroutine(SearchEnemy()); //发现敌人并向敌人移动 //TestThePath(path); } IEnumerator SearchEnemy() { int nearestCell = 1000; List path = new List(); Cell endNode = null; while(frontier.Count != 0) { Cell node = LowestCost(); //总是找出fCost最低的节点 //Debug.Log("Node =" + node.transform.position.x + "," + node.transform.position.y); frontier.Remove(node); //若找到目标所在Cell,则返回其父结点 if(node.currentCharacter != null && node.currentCharacter.groupNumber != groupNumber) { //Debug.Log(node.transform.position.x + "," + node.transform.position.y); endNode = node.parent; break; } //Debug.Log("node is " + node.transform.position.x + "," +node.transform.position.y + " hCost is " + node.hCost); //找到离目标预测最近的单元格 if(node.hCost < nearestCell) { endNode = node; nearestCell = node.hCost; } explored.Add(node); List neighbors = node.GetNeighbor(); foreach (var neighbor in neighbors) { if(!frontier.Contains(neighbor) && !explored.Contains(neighbor)) { if(neighbor.currentCharacter != null && neighbor.currentCharacter.groupNumber == groupNumber) continue; neighbor.parent = node; neighbor.CalculateCosts(goal.transform.position); if(neighbor.gCost <= maxMovement) frontier.Add(neighbor); } } } // if(endNode != null) // Debug.Log("endNode is " + endNode.transform.position.x + "," +endNode.transform.position.y); int count = 0; // if(!found) // endNode = frontier[frontier.Count - 1]; while(endNode != null) { path.Add(endNode); endNode = endNode.parent; count ++; if(count > 10) break; } frontier.Clear(); explored.Clear(); //if(found == true) { for(int i = 0; i < attackRange - 1; i++) path.RemoveAt(0); path.Reverse(); if(path.Count > 0) path.RemoveAt(0); //Debug.Log("path.Count = " + path.Count); } yield return StartCoroutine(ActionAI(path)); } void TestThePath(List path) //测试用函数 { Debug.Log("The path :"); foreach(var node in path) { Debug.Log(node.transform.position.x + "," + node.transform.position.y); } } int FindNearestEnemy() //找到最近距离的敌人 { int minDistance = 1000; GameObject[] pieces = GameManager.instance.pieces; foreach(var piece in pieces) { Character character = piece.GetComponent(); int distance = GameSettlement.Manhattan(transform.position,character.transform.position); if(character.groupNumber != groupNumber && distance < minDistance) { minDistance = distance; goal = character; } } //Debug.Log("minDistance = " + minDistance); return minDistance; } Cell LowestCost() //找出frontier里fCost最低的节点 { Cell lowestCost = frontier[0]; foreach(var node in frontier) { if(node.fCost < lowestCost.fCost) lowestCost = node; } return lowestCost; } IEnumerator ActionAI(List path) { Selected(); //移动阶段 foreach(var node in path) { Vector2 position1 = cell.transform.position; Vector2 position2 = node.transform.position; float deltaX = position2.x - position1.x; float deltaY = position2.y - position1.y; Vector2 deviation = new Vector2(deltaX,deltaY); yield return StartCoroutine(Move(deviation, 0.1f)); cell = node; } //攻击阶段 if(GameSettlement.Manhattan(goal.transform.position,transform.position) <= attackRange) while(currentMovement >= attackCost) { yield return new WaitForSeconds(0.2f); AIAttack(); } yield return new WaitForSeconds(2 * timer); Cancel(); } void AIAttack() { if(skill.CheckRequest(currentMana, currentMovement, goal)) { Debug.Log("AISkill released"); skill.ApplySkill(this, goal); return; } int damage = GameSettlement.AIAttackSettlement(this, goal); goal.ChangeHealth(damage); goal.ChangePoise(-str); ChangeMovement(-attackCost); ChangeMana(inte/3 + san/5); //buffManager.ApplyActiveSpecial(goal); goal.buffManager.ApplyPassiveSpecial(this); } public override void Selected() //AI不需要武器 { if(GameManager.instance.selected != null) return; if(GameManager.instance.currentGroup != groupNumber) return; animator.SetFloat("selected", 1); GameManager.instance.SetSelected(gameObject.GetComponent()); movementBar.SetMovementActive(true); } public override void Cancel() //AI不需要武器 { animator.SetFloat("selected", 0); GameManager.instance.SetSelected(null); movementBar.SetMovementActive(false); } protected override void OnMouseOver() { //鼠标右键点击查看角色信息 if(Input.GetMouseButton(1) && GameManager.instance.GetSelected() == null) { GameManager.instance.CheckDetailInformation(str,inte,dex,san,vig,def, currentHealth,maxHealth,currentPoise,maxPoise,currentMana,maxMana); } } }