[Unity3D] Unity3D game development-Xml parsing for implementing the NPC conversation system, unity3dnpc
Dear friends, I'm Qin Yuanpei. Welcome to follow my blog. My blog address is blog.csdn.net/qinyuanpei. Today, let's talk about Xml parsing in Unity3D. Why do we want to talk about Xml parsing? In projects, we often need to read content from the outside or store the content in a certain form. Xml is the most common file form. It is a game that the blogger is currently working on ).
In this game, the blogger carefully designed a large number of interesting lines for the players, covering the stories of the past and related content of the legend of the ancient sword. If we directly write these lines into the code, even though the game can also run, once the game plans to modify the plot or some content, we have to re-compile the code, re-compile, and re-test. Therefore, RPG games like legend of the legend, because the script language is relatively simple, it is suitable for planners. Now, let's go back to Unity3D. Today we will use an Xml file to store our conversation content, and then read it through the script to implement the conversation with the NPC. The advantage of this is that we can modify the content of the Xml file anytime, anywhere without modifying the code of the entire project. In a previous article, his real-time blogger mentioned the implementation of the NPC dialogue system. However, at that time, the blogger was in a state of mutual understanding of Unity3D (in fact, it is still a matter of mutual understanding, haha ), therefore, the design at that time was a very immature idea. In fact, today's article was made only after a lot of improvements have been made. (However, the bloggers are still not satisfied, bloggers like to pursue perfection ). Well, let's talk about the principle first. We will launch a ray that passes through the mouse position from the camera, and then check whether the ray hits the NPC. if it hits the NPC, the mouse pointer will be changed to the dialog style. When the player presses the mouse key, the NPC and the player will face to face (the code here is a bit problematic and will be mentioned later) and the dialog box will be displayed, the player continues to press the Space key to continue the entire conversation with the NPC until all the conversations are displayed. The dialog box here is completed using the Unity3D GUI system. By default, the dialog box is hidden. the dialog box is displayed only after the player triggers the dialog. After the entire dialog is completed, the dialog box disappears. It is the dialog box designed by the blogger, Which is modeled in the style of "Legend of the legend of the fairy sword" (but there is no Avatar, haha). Here, the blogger does not want to say too much, unity3D's current GUI system is not completely unified.
First of all, let's talk about Xml parsing in Unity3D. The scripting language used by bloggers in Unity3D is C #, so the bloggers use it decisively. the Xml parsing API under. NET, that is, System. I believe I have learned the Xml namespace. NET. Let's take a look at the Xml file to be parsed today, a very simple Xml file (a line was designed as a conversation, but later we found that the conversation was too long to work, so it is divided into multiple lines, but the Unity3D GUI system cannot automatically wrap the lines, so the actual effect here is not very good. I really regret not using NGUI directly, can the official GUI system be used ):
<? Xml version = "1.0" encoding = "UTF-8"?> <Dialogs> <Dialog> elders of Qingyang: if we know that Xuan Xiao breaks the ice from the banned land, we will not tell him how to find the three cold containers </Dialog> <Dialog> method. I have nothing to say about how he wants to kill me and how powerful I am, but it is a great mistake for him to learn how to do so. </Dialog> <Dialog> remark: I don't know the person you said, but I know that once a person is lost, he will make a wrong thing. Jiang Cheng </Dialog> <Dialog> if it is not used by dead wood, he will not go that step. Gong Xuan has always wanted to help him with his friendship, but when he reaches the top of the day, he finds that no matter how hard he works, jiang Cheng has no way to go back. </Dialog> <Dialog> elders of Qingyang: I also participated in the ice freezing of Xuan Xiao. After all, the two of me were really right to one person. </Dialog> <Dialog> example: maybe you all have your own difficulties, but how can you understand the good and evil in this world? </Dialog> <Dialog> elders of Qingyang: there is no dispute or embarrassment in this area, I am here, but I am still alive. </Dialog> </Dialogs>
Parsing Xml in C # is relatively simple, so the code is provided here. The blogger found in Jin Zeng Xi's book Unity3D game development, the Xml parsing script recommended by the author in the book from the open-source community is not perfect, because the script class of js cannot be correctly read in C #, and then the blogger tries to add many references, the problem still cannot be solved, so I had to use it at the end.. NET parses the XmlDe class space.
// Parse the Xml array private NPC [] ReadXmls () {// initialize the NPC array mNPCs = new NPC [XmlDatas. length]; for (int I = 0; I <XmlDatas. length; I ++) {NPC mNPC = new NPC (); mNPC. ID = I. toString (); mNPC. data = ReadSingleXml (XmlDatas [I]); mNPCs [I] = mNPC;} return mNPCs;} private string [] ReadSingleXml (TextAsset mText) {XmlDocument mDocuemnt = new XmlDocument (); // load the Xml text mDocuemnt. loadXml (mText. text); // get the root node XmlElement mElement = mDocuemnt. documentElement; // read the node value XmlNodeList mNodeList = mElement. selectNodes ("/Dialogs/Dialog"); // create an array string [] mArray = new string [mNodeList. count]; for (int I = 0; I <mNodeList. count; I ++) {mArray [I] = mNodeList [I]. innerText;} // returns the array return mArray;} // returns an NPCprivate NPC getNPCByID (int ID) {NPC mResult = null; foreach (NPC mNPC in mNPCs) by ID) {if (mNPC. ID = ID. toString () {mResult = mNPC; break ;}} return mResult ;}}
After parsing the Xml, we can associate the content with the NPC. Let's look at the NPCScript. cs script of the NPC.
In this script, the game manager is responsible for global control, such as controlling the mouse style, displaying the control dialog box, and controlling the camera. The script is defined as follows:
Using UnityEngine; using System. collections; using System. xml; public class NPCScript: MonoBehaviour {// game manager private GameManager mManager; // Xml array public TextAsset [] XmlDatas; // conversation array private string [] mDialogs; // conversation index private int index = 0; // NPC array private NPC [] mNPCs; public int ID; void Start () {// obtain the game manager mManager = GameObject. find ("GameManager "). getComponent <GameManager> (); // read NPCmNPCs = ReadXmls ();} void Update () {// The Conversation triggers RaycastHit mHit; Ray mRay = mManager. manager_Camera.ScreenPointToRay (Input. mousePosition); bool isHit = Physics. raycast (mRay, out mHit); if (isHit & mHit. collider. gameObject. tag = "NPC") {// obtain the corresponding NPC conversation mNpc = getNPCByID (ID) based on the ID; if (mNpc! = Null) {mDialogs = new string [mNpc. data. length]; for (int I = 0; I <mDialogs. length; I ++) {mDialogs [I] = mNpc. data [I] ;}} mManager. mangager_Cursor.SetCursor (Cursor. cursorType. talk); // calculate the distance between the player and the NPC Transform NPC = mHit. collider. gameObject. transform; Vector3 v1 = NPC. position; Vector3 v2 = mManager. player. position; if (Vector3.Distance (v1, v2) <= 2.0F & Input. getMouseButtonDown (0) {// make v1, v2 common v1 = new Vector3 (v1.x, 0, v1.z); v2 = new Vector3 (v2.x, 0, v2.z ); // calculate the vector Vector3 mDir = (V1-V2) of v1 and v2 connections ). normalized; // calculate the Rotation Angle float NpcAngle = getAngle (new Vector3 (, 1), mDir); float PlayerAngle = getAngle (new Vector3 (, 1 ), mDir); // rotate the NPC to the main character. forward = mDir; // dialog control mManager. setDialogBox (mDialogs [0]. toString (); mManager. setDialogBoxActive (true); // sets the game status mManager. setGameState (GameState. inEvent) ;}} else {mManager. mangager_Cursor.SetCursor (Cursor. cursorType. default);} // press the Space key to perform the if (mManager. manager_State = GameState. inEvent & Input. getKeyDown (KeyCode. space) {index + = 1; if (index> mDialogs. length-1) {// hide the mManager dialog box. setDialogBoxActive (false); mManager. setGameState (GameState. normal); // reset the NPC angle to transform. rotate (new Vector3 (0,180, 0); // reset index = 0 for arrays and indexes; mDialogs = null;} else {mManager. setDialogBox (mDialogs [index]. toString (); mManager. setDialogBoxActive (true); mManager. setGameState (GameState. inEvent) ;}}// parse private NPC [] ReadXmls () {// initialize the NPC array mNPCs = new NPC [XmlDatas. length]; for (int I = 0; I <XmlDatas. length; I ++) {NPC mNPC = new NPC (); mNPC. ID = I. toString (); mNPC. data = ReadSingleXml (XmlDatas [I]); mNPCs [I] = mNPC;} return mNPCs;} private string [] ReadSingleXml (TextAsset mText) {XmlDocument mDocuemnt = new XmlDocument (); // load the Xml text mDocuemnt. loadXml (mText. text); // get the root node XmlElement mElement = mDocuemnt. documentElement; // read the node value XmlNodeList mNodeList = mElement. selectNodes ("/Dialogs/Dialog"); // create an array string [] mArray = new string [mNodeList. count]; for (int I = 0; I <mNodeList. count; I ++) {mArray [I] = mNodeList [I]. innerText;} // returns the array return mArray;} // returns an NPCprivate NPC getNPCByID (int ID) {NPC mResult = null; foreach (NPC mNPC in mNPCs) by ID) {if (mNPC. ID = ID. toString () {mResult = mNPC; break ;}} return mResult ;}}
Here, we first use the SetDialogBox () method to set the dialog content to be displayed in the dialog box, and then use the SetDialogBoxActive () method to activate the dialog box, in this way, we can see the story dialogue carefully designed by the blogger.
Finally, let's take a look at the fact that bloggers are not satisfied with this solution, that is, they can only have one NPC at any time in the current game, this is because the blogger binds all the NPCs to the same script. In this script, it first reads all the NPC conversation data, then, in the ray detection area, obtain the specified NPC conversation data based on the ID. Theoretically, this should be fine, but in actual testing, if there are multiple NPCs in the scenario, the dialog box is hidden when the conversation is not completed, or the NPC does not match the dialog content. At first, the blogger thought that multiple NPCs shared the same game script, causing internal variables to conflict. But how does the blogger feel that a private variable is influenced by the outside? The blogger once tried to write a script for each NPC, that is, each NPC is only responsible for its own part, but this still shows the Bug mentioned above, this Bug almost makes the blogger lose confidence in completing this game. Currently, the blogger's idea is to manually change the Enable of each script to ensure that there is only one NPC in any time scenario, the Bug is being easily modified. A more effective solution that the blogger came up with was to add the following script:
Using UnityEngine; using System. colleach; public class NPCManager: MonoBehaviour {// NPCpublic Transform [] NPCs; // Player public Transform Player; // initialize NPCvoid Awake () {foreach (Transform mTrans in NPCs) {mTrans. getComponent <NPCScript> (). enabled = false ;}/// enpcvoid Update () {// The foreach (Transform mTrans in NPCs) dialog is triggered only when the player enters the dialog range) {// calculate the float mDistance = Vector3.Distance (mTrans. position, Player. position); // trigger the Dialog script when the distance is less than 4.0. if the distance is greater than 4.0, the Dialog Script if (mDistance <= 4.0F) {mTrans. getComponent <NPCScript> (). enabled = true;} else {mTrans. getComponent <NPCScript> (). enabled = false ;}}}}
This script is actually a little tricky. It is used to determine the distance between the player and the NPC. When the distance is smaller than the distance triggered by the conversation, the script bound to the NPC is activated, in this scenario, only one NPC is activated at any time.
In the face of your own bugs, if you know what is going on, it is best to solve it in the first place; if you do not know what is going on, you can only solve it by unusual means. This is mainly because the bloggers like the two series of games, "Legend of the fairy sword" and "Legend of the ancient sword". In many cases, we are only an ordinary member of the ordinary world, but it is because of the ordinary, we want to change, the game always hits the customs clearance moment, but our life has just begun. The little game "fairy ancient realm" tells the story of a transitional world connecting the Fairy sword world and the ancient sword world in the virtual world, similar to the setting of the magic well in "Legend of the fairy sword. Maybe it's because I like the blue-and white-shirt swordsman too much, maybe it's because I like the white-haired, lonely back. In short, when the lights of jimo night are exhausted, when the qionghuafai is in a twinkling of an eye, the teenager is still dreaming of his youth.
Okay. Let's take a look at the game scenario:
Well, today's content is like this. I hope you will like it.
Daily rumors: I prefer to turn into a fallen leaf, so that the wind and the rain are everywhere; or a cloud, in the clear blue sky, and the Earth is no longer related. -- Lin Huiyin
If you like my blog, please remember my name: Qin Yuanpei. My blog address is blog.csdn.net/qinyuanpei.
Reprinted please indicate the source, Author: Qin Yuanpei, the source of this article: http://blog.csdn.net/qinyuanpei/article/details/38982335
Unity3D game development instances, source code recommendation books, or download Source Code addresses
Unity 3D Game Development
[Unity3D] mobile 3D Game Development: how to use gravity sensing in Unity3D
Wang wanghai's laboratory, Shanghai laboratory-various graphics experiments, data structure experiments, and other trivial little notes are all gathered here for 0-various graphics experiments and data structures the lab and all other trivial notes are gathered here for 0 error (s ), 0 warning (s) the arrival of this magic moment error (s), 0 warning (s) the arrival of this magic moment learning Unity script is recommended: unity3D indexing gravity sensing is very common in mobile game development. Unity3D is a collection of gravity sensing related content. A simple JS script demonstrates the use of gravity sensing. CSDNGravity. js: // object texture var round: Texture2D; // The x y coordinate var x = 0 displayed on the screen; var y = 0; // maximum x y range displayed on the Object Screen var cross_x = 0; var cross_y = 0; function Start () {// initialization value cross_x = Screen. width-round. width; cross_y = Screen. height-round. height;} function OnGUI () {// The overall x y z gravity sensing gravity component GUI is displayed. label (Rect (0,0, 480,100), "position is" + Input. acceleration); // draw the object GUI. drawTexture (Rect (x, y, 256,256), round);} function Update ( ) {// Modify the object position based on the gravity component. Multiply the value by 30 here to make the object move faster x ++ = Input. acceleration. x * 30; y + =-Input. acceleration. y * 30; // avoid an object exceeding the screen if (x <0) {x = 0;} else if (x> cross_x) {x = cross_x ;} if (y <0) {y = 0;} else if (y> cross_y) {y = cross_y ;}} the Input here refers to the Input in Unity, acceleration is its gravity, and x and y represent its gravity. After creating the image, you only need to add the texture image: 12