In this part of my video game tutorial I will continue making Zelda. I’ll focus this time on something I have not covered before which is how to create the AI for our villain so that he will travel on his own around the game board looking for Link. The villain will travel around using very few system resources. He will be able to locate Link any place on the map. We will use multidimensional arrays to store travel nodes. We will also learn how to find out which node game objects are closest to.
All of the code used follows the video below.
If you like videos like this consider donating $1, or simply turn off AdBlocker. Either helps a lot.
[googleplusone]
Code From the Video
Villain.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
using System.Collections; using System.Collections.Generic; using UnityEngine; // Create empty called TravelNodes with 0, 0 position // Create Node0 - Node10 and add collider with is trigger // with size .2 and Y off set at .25 public class Villain : MonoBehaviour { public float speed = 2f; // The villains will all start going right when loaded Vector2 direction = Vector2.right; // Keeps track of if Villain is chasing or not bool chasing = true; // Get reference to the Animator so I can change animations private Animator animator; // Reference to Link GameObject linkGO; // Reference to rigidbody Rigidbody2D rb; // NEW STUFF 1 // Create array of all nodes villains travel to int[,] villainNodes = new int[,] { { 1, 1 }, { 10, 2 }, { 5, 9 }, { 7, 15 }, {13, 15}, {15, 10}, {15, 3}, {22, 3}, {24, 5}, {21, 9}, {23, 13}}; // Set the closest node here public int currentNode = 1; // Track the target node public int targetNode = 2; // END OF NEW STUFF 1 // NEW STUFF 2 // Will hold all Villain Nodes GameObject[] villainNodeGOs; // Stores the node Link is the closest to GameObject linksClosestNodeGO; // END OF NEW STUFF 2 void Awake(){ // Get reference to Link linkGO = GameObject.Find("Link"); // Get reference to rigid body rb = GetComponent<Rigidbody2D> (); animator = GetComponent<Animator> (); // NEW STUFF 2 Get villainNodes villainNodeGOs = GameObject.FindGameObjectsWithTag("VillainNode"); } void FixedUpdate(){ // NEW STUFF 1 if (Input.GetKeyUp ("f")) { if (targetNode < 10) { // Increments through the villain nodes targetNode = targetNode + 1; // Move the villain to the node GoForwardToNode (); // NEW STUFF 2 Get Links closest node linksClosestNodeGO = LinksClosestNode (); Debug.Log ("Links closest node " + GetIndexForLinksClosestNode(linksClosestNodeGO)); } } if (Input.GetKeyUp ("b")) { if (targetNode > 0) { // Decrements through the villain nodes targetNode = targetNode - 1; // Move the villain to the node GoForwardToNode (); } } // END OF NEW STUFF 1 /* transform.position = Vector3.MoveTowards (transform.position, linkGO.transform.position, .03f); */ } // NEW STUFF 1 void GoForwardToNode(){ if (!AtTargetNode ()) { // Define target x y position Vector2 targetPosition = new Vector2 (villainNodes [targetNode, 0] - transform.position.x, villainNodes [targetNode, 1] - transform.position.y); Debug.Log ("Target X : " + villainNodes [targetNode, 0] + "Y : " + villainNodes [targetNode, 1]); Debug.Log ("Target Node : " + targetNode); direction = targetPosition; } } // Gets the target node which stores the x / y values for the target // and compares that to the villains current position bool AtTargetNode(){ if (transform.position.x == villainNodes [targetNode, 0] && transform.position.y == villainNodes [targetNode, 1]) { return true; } else { return false; } } void Update(){ // Change the direction as needed rb.velocity = direction; } // END OF NEW STUFF 1 // NEW STUFF 2 // Returns the node Link is closest to GameObject LinksClosestNode(){ // Will hold the closest node GameObject closestNodeGO = null; foreach (GameObject nodeGO in villainNodeGOs) { if (closestNodeGO == null) { closestNodeGO = nodeGO; } if (Vector3.Distance (linkGO.transform.position, nodeGO.transform.position) <= Vector3.Distance (linkGO.transform.position, closestNodeGO.transform.position)) { // Assign the closest gameobject for comparison closestNodeGO = nodeGO; } } return closestNodeGO; } // Returns the index in the node array for Links closest node int GetIndexForLinksClosestNode(GameObject linksNodeGO){ int nodeIndex = 0; for (int i = 0; i <= villainNodes.GetUpperBound (0); i++) { Debug.Log ("X : " + villainNodes [i, 0]); Debug.Log ("Y : " + villainNodes [i, 1]); if (linksNodeGO.transform.position.x == villainNodes [i, 0] && linksNodeGO.transform.position.y == villainNodes [i, 1]) { nodeIndex = i; } } return nodeIndex; } // END OF NEW STUFF 2 // Handles changing direction when we hit VillainStart and end void OnTriggerEnter2D(Collider2D col){ if (!chasing) { // When we collide make the Villain go in the opposite direction transform.localScale = new Vector2 (-1 * transform.localScale.x, transform.localScale.y); // Change direction direction = new Vector2 (-1 * direction.x, direction.y); } else { } // NEW STUFF 1 // Give all Villain travel nodes the tag VillainNode // Add box colliders and Is Trigger to all nodes if (col.tag == "VillainNode") { // If the villain collides with a node stop if (col.transform.position.x == villainNodes [targetNode, 0] && col.transform.position.y == villainNodes [targetNode, 1]) { direction = Vector3.zero; } } // if(col.gameObject.name == "Link") } // END OF NEW STUFF 1 } |
Leave a Reply