Unity3D game development-update method, unity3d Game Development

Source: Internet
Author: User

Unity3D game development-update method, unity3d Game Development

The Role in the game, like a paper doll, is a very popular feature that allows players to change the appearance of their roles. In general, we have built a 3D model, if you want to replace one of the parts with another shape, the most direct thing is to replace the Mesh of the parts of the object, then the appearance changes, however, if this method is applied to a model that requires action, it will find that the replaced part does not work normally. Worse, the position and direction displayed by the model may be wrong, therefore, the direct Mesh change method is only applicable to static model objects. Therefore, we must find a more in-depth method for the update function. Fortunately, this part of Unity has provided examples for reference.


You can download Character Customization from the official website, or enable the Window> Asset Store in the Unity editor to download Character Customization from Complete Projects> Tutorials and import it to your project. This example provides a complete example. Considering that it is impossible to load all the resources at a time when you are playing a game, you can package resources such as models, materials, and textures into Asset bundle, the required parts are loaded only when they are used. Because of this, it is relatively difficult to directly learn the plug-in through this example if you do not know about Asset bundle. In addition, the naming rules in specific forms are also standardized for resources. They are designed to create Asset bundle content and retrieve resources from Asset bundle. Before you understand these rules, it is difficult to learn the costumes through this example. Of course, if you are willing to use the naming rules and file configuration methods that are identical to the models, materials, and textures of the two characters in the characters directory in the examples, you can almost directly apply them to your own games, it is not necessary to understand the internal operation mode.


Enable Asset store in Unity and find the Character Customization Example in Asset store.


Although this official example can be applied directly, there are usually different customization requirements for making games. If you do not understand the relevant principles and procedures, you may not be able to use them freely and flexibly, the following example is used to remove the parts of Asset bundle side by side to directly replace paper dolls in the scene.


First, let's take a look at the model structure. Pull CharacterCustomization> characters> Female from the Projects window to the scenario, and expand the object in the Hierarchy window, several objects with the same name and different numbers are found. They represent the models of different parts of the character. Therefore, we can see that the entire character model file contains multiple models of the same part, famale_Hips is the skeleton structure of the entire character, and the action of the character is the Animation of the object (Female) on the top. Therefore, this model file is a model resource, instead of actually placing the object in the scenario.


Each part has multiple model objects.


After learning about the model file content, create a C # program named TestChar to control the update. To facilitate testing, in the Projects window, change the Animation Wrap Mode of CharacterCustomization> characters> Female @ walk to Loop, and add animation to the Start () of the program file. play ("walk"), so in the execution status will make the characters continue to walk. Source of the article [DOG planing learning network]


Select Female @ walk

Animation Wrap Mode select Loop


The official example of Unity is to use the model file as the source model resource, and then combine all parts into a new target model as required, therefore, we directly pull the character model Female into two scenes and name them "Source" and "Target" respectively. Follow these steps to make preparations:


From the Projects window, pull CharacterCustomization> characters> Female> Per Texture Materials to each part of the Source (excluding Female_Hips and its sub-objects) according to the name ).


The Source object is used as a Source resource and does not need to be operated in the actual scenario. Therefore, you can click the Source object directly and deselect the box before the Source Name field in the Inspector window to disable it.


Deselect the box in front of Source. After the box is deselected, the dialog window appears asking if you want to disable all the sub-objects. Click Deactivate Chidren. Delete all child objects except Famale_Hips from the Target object. Drag the TestChar program file to the Target object. The name of each part in Source must be numbered (for example, face-1). If not, add the number.


After completing the above preparations, we will start to write the program. The main task of the program is to first extract the SkinnedMeshRenderer data of each object in the Source and store it in the data variable, data is classified by location

Next, add SkinnedMeshRenderer to the Target, and retrieve a specified data in each part, and use CombineInstance class and Mesh. combineMeshes () combines models of various parts, and sorts the materials again. Then, based on the name of the bone of the retrieved SkinnedMeshRenderer, find the object that corresponds to the name of the Target Female_Hips sub-object and rebuild the skeleton list. Finally, combine the created data to the Target SkinnedMeshRenderer, so that the update can be completed, the program description is as follows:


  1. // The object of the source model Resource

  2. Public Transform source;

  3. // Target object

  4. Public Transform target;

  5. // Model Resource Information

  6. Private Dictionary <string, Dictionary <string, SkinnedMeshRenderer> data = new Dictionary <string, Dictionary <string, SkinnedMeshRenderer> ();

  7. Void Start (){

  8. // Extract the SkinnedMeshRenderer of each part from the source model Resource

  9. SkinnedMeshRenderer [] parts = source. GetComponentsInChildren <SkinnedMeshRenderer> (true );

  10. Foreach (SkinnedMeshRenderer part in parts ){

  11. // Use? The delimiter name is the key of the data structure. Is it the location? The data is stored as [Part] [number] = SkinnedMeshRenderer

  12. String [] partName = part. name. Split ('? ');

  13. // Add materials to data

  14. If (! Data. ContainsKey (partName [0]) data. Add (partName [0], new Dictionary <string, SkinnedMeshRenderer> ());

  15. Data [partName [0]. Add (partName [1], part );

  16. }

  17. // Add the target object to SkinnedMeshRenderer.

  18. SkinnedMeshRenderer targetSmr = target. gameObject. AddComponent <SkinnedMeshRenderer> ();

  19. // Obtain the skeleton data from the target object (all objects of Female_Hips)

  20. Transform [] hips = target. GetComponentsInChildren <Transform> ();

  21. /** Start restructuring the model */

  22. // Initialize the data list

  23. List <CombineInstance> combineInstances = new List <CombineInstance> ();

  24. List <Material> materials = new List <Material> ();

  25. List <Transform> bones = new List <Transform> ();

  26. Foreach (KeyValuePair <string, Dictionary <string, SkinnedMeshRenderer> _ part in data ){

  27. // Obtain the SkinnedMeshRenderer of the specified part from the data

  28. SkinnedMeshRenderer smr = new SkinnedMeshRenderer ();

  29. Switch (_ part. Key ){

  30. Case "eyes ":

  31. Smr = _ part. Value ["1"];

  32. Break;

  33. Case "face ":

  34. Smr = _ part. Value ["1"];

  35. Break;

  36. Case "hair ":

  37. Smr = _ part. Value ["1"];

  38. Break;

  39. Case "pants ":

  40. Smr = _ part. Value ["1"];

  41. Break;

  42. Case "shoes ":

  43. Smr = _ part. Value ["1"];

  44. Break;

  45. Case "top ":

  46. Smr = _ part. Value ["1"];

  47. Break;

  48. }

  49. // Prepare the Mesh to be combined

  50. CombineInstance ci = new CombineInstance ();

  51. Ci. mesh = smr. sharedMesh;

  52. CombineInstances. Add (ci );

  53. // Arrange the new material list

  54. Materials. AddRange (smr. materials );

  55. // Obtain the skeleton object corresponding to the name to create a new skeleton list

  56. Foreach (Transform bone in smr. bones ){

  57. Foreach (Transform hip in hips ){

  58. If (hip. name! = Bone. name) continue;

  59. Bones. Add (hip );

  60. Break;

  61. }

  62. }

  63. }

  64. // Merge the Mesh and write it to the Target's SkinnedMeshRenderer

  65. TargetSmr. sharedMesh = new Mesh ();

  66. TargetSmr. sharedMesh. CombineMeshes (combineInstances. ToArray (), false, false );

  67. // Target's SkinnedMeshRenderer writes to the new skeleton list

  68. TargetSmr. bones = bones. ToArray ();

  69. // The Target's SkinnedMeshRenderer writes the new material list

  70. TargetSmr. materials = materials. ToArray ();

  71. /** End of restructuring model */

  72. // Specifies the playback walk.

  73. Animation. Play ("walk ");

  74. }
Copy code

After writing the program, remember to pull the Source and Target objects in the scenario to the source and Target columns of TestChar script attached to the target object respectively;


All Program actions are performed in Start () because the target object does not have data such as a model at first, you must first create a character based on the data of the specified parts and make the action, while smr = _ part. "1" of Value ["1"]; indicates that the "1" model data of this part is specified, so as long as this Value of each part is changed, you can configure different shapes for the characters. Of course, the prefix is that the source model resource must have an object with this number. The above code is mainly used for testing and commenting, in practice, the logo/** restructuring model */program should be released independently, and each part should be assigned a specified number to execute the code when a new package is required.


The above is the update method in the official Unity example. It combines the models and materials of various parts into a single model and recreates the skeleton list, in this way, even if one of the parts of a character is replaced, it can continue to work normally. When you view the Target object, you will find that its sub-objects remain unchanged, only the Component of the Target object in the Inspector window has the Skinned Mesh Renderer and the Material of each part. If you view the Mesh field of the SkinnedMeshRenderer, you cannot see any Mesh.


Target object content


The source model of this method must correspond to the number of materials, otherwise the texture of the model will become abnormal, that is, if there are two material pants and only one materail in other parts, the textures in the result model will be different from expected. In order to make the material of each part more flexible, the previous program will make some modifications so that each part of the model is an independent GameObject, as follows:


  1. // The object of the source model Resource

  2. Public Transform source;

  3. // Target object

  4. Public Transform target;

  5. // Model Resource Information

  6. Private Dictionary <string, Dictionary <string, Transform> data = new Dictionary <string, Dictionary <string, Transform> ();

  7. // Skeleton of the target object

  8. Private Transform [] hips;

  9. // SkinnedMeshRenderer information of each part of the target object (refer)

  10. Private Dictionary <string, SkinnedMeshRenderer> targetSmr = new Dictionary <string, SkinnedMeshRenderer> ();

  11. Void Start (){

  12. // Extract the SkinnedMeshRenderer of each part from the source model Resource

  13. SkinnedMeshRenderer [] parts = source. GetComponentsInChildren <SkinnedMeshRenderer> (true );

  14. Foreach (SkinnedMeshRenderer part in parts ){

  15. // Use? The delimiter name is the key of the data structure. Is it the location? The part number is stored as [Part] [number] = Transform data

  16. String [] partName = part. name. Split ('? ');

  17. // Add materials to data

  18. If (! Data. ContainsKey (partName [0]) {

  19. Data. Add (partName [0], new Dictionary <string, Transform> ());

  20. // Create a new GameObject and name it using the part name. Specify it as a child object of the target object.

  21. GameObject partObj = new GameObject ();

  22. PartObj. name = partName [0];

  23. PartObj. transform. parent = target;

  24. // Add SkinnedMeshRenderer to the newly created GameObject and save the SkinnedMeshRenderer to targetSmr.

  25. TargetSmr. Add (partName [0], partObj. AddComponent <SkinnedMeshRenderer> ());

  26. }

  27. Data [partName [0]. Add (partName [1], part. transform );

  28. }

  29. // Obtain the skeleton data from the target object (all objects of Female_Hips)

  30. Hips = target. GetComponentsInChildren <Transform> ();

  31. /** Start restructuring the model */

  32. Foreach (KeyValuePair <string, Dictionary <string, Transform> _ part in data ){

  33. Switch (_ part. Key ){

  34. Case "eyes ":

  35. ChangePart ("eyes", "1 ");

  36. Break;

  37. Case "face ":

  38. ChangePart ("face", "1 ");

  39. Break;

  40. Case "hair ":

  41. ChangePart ("hair", "1 ");

  42. Break;

  43. Case "pants ":

  44. ChangePart ("pants", "1 ");

  45. Break;

  46. Case "shoes ":

  47. ChangePart ("shoes", "1 ");

  48. Break;

  49. Case "top ":

  50. ChangePart ("top", "1 ");

  51. Break;

  52. }

  53. }

  54. /** End of restructuring model */

  55. // Specifies the playback walk.

  56. Target. animation. Play ("walk ");

  57. }

  58. Private void ChangePart (string part, string item ){

  59. // Obtain the SkinnedMeshRenderer of the specified part from the data

  60. SkinnedMeshRenderer smr = data [part] [item]. GetComponent <SkinnedMeshRenderer> ();

  61. // Obtain the skeleton object corresponding to the name to create a new skeleton list

  62. List <Transform> bones = new List <Transform> ();

  63. Foreach (Transform bone in smr. bones ){

  64. Foreach (Transform hip in hips ){

  65. If (hip. name! = Bone. name) continue;

  66. Bones. Add (hip );

  67. Break;

  68. }

  69. }

  70. // Update the SkinnedMeshRenderer content of the specified GameObject

  71. TargetSmr [part]. sharedMesh = smr. sharedMesh;

  72. TargetSmr [part]. bones = bones. ToArray ();

  73. TargetSmr [part]. materials = smr. materials;

  74. }
Copy code

When creating the data variable content, you can also create a GameObject for each part. In addition, the Code of the changed part content is also independent of the ChangePart method, so that each time you need to change this part, you only need to specify the part name and number to directly replace the part without recreating each part. Because each part is a GameObject object, you can click this part in the Hierarchy or Scene window to clearly view the content of this part from the Inspector window. As a result, you can configure the number of Material for each part.


In the above Code, we will find that in addition to retrieving the Mesh and Material from the source to the target replacement, the key is to re-build the skeleton list. Why should we re-build the skeleton list? The most important thing is after the Mesh change


SkinnedMeshRenderer. bones and SkinnedMeshRenderer. sharedMesh. The Number of bindposes may vary with the number of bones in the bind poses doesn't match Number of bones in the skinned mesh


No error message even if the number is the same


SkinnedMeshRenderer. sharedMesh. the Matrix4x4 [] data in bindposes may also cause the execution model to be distorted into a strange shape due to incorrect values. This part can import the Female model file to 3DS Max for viewing, take shoes as an example. In the Modify window, we can see that the Bones list content of shoes-1 and shoes-2 is different, therefore, when you change the Mesh of a model object, you must recreate the skeleton list.


The above description is mainly used to understand the practices required for the dress-up. In practice, it is unlikely that all model data of all parts of the role in the game will be loaded as the source data, for example, there are 100 types of weapons in the game and 3 types of weapons in the role backpack, but in order to replace the game, all 100 types of weapons are loaded into the game, in fact, this role can only change at most three weapons in the backpack, which is undoubtedly a waste of resources occupied by 97 weapons. Therefore, after learning how to replace with another weapon, during actual implementation, we should try to pack the source resources as the official example, and only retrieve the required resources for replacement.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.