How unity loads torch light

Source: Internet
Author: User

Due to some basic mathematical problems, I studied it for four or five days before and after. Today I finally got a little eye off and kept a note.

I. Analysis of torch lighting configuration file

The torch light scenario involves several parts: 1. resource files, including basic models, particles, and monsters. For the moment, we only look at the model and create a mesh file. In the same time, each model has an image file (xxxthumb.jpg) and a collision file (xxxcollision. mesh ). 2. tileset configuration. This is a dat file, for example, cataco MB. dat, which contains thousands of piece, and piece corresponds to the actual resource file and Some editor-related parameter configurations, such as alignment. The relationship between piece and resources can be one-to-many, which is used for random Scenario Generation. 3. layout, which is under the layouts folder, is the configuration of the actual scenario. You can use the guts editor to open the layout file to view the scenario. In the configuration file, [baseobject] is an element in the actual scenario. The most common thing is to specify a roompiece through guid, which is also an element in tileset.

There is no difficulty in parsing this configuration file. You can retrieve the content of each element by traversing each line and parsing one line.

 

Ii. Automatic unity Loading

Instead of dynamic Scenario Generation, we select a layout configuration file and create the corresponding object. The core code is as follows:

[Menuitem ("tools/import scenario (TEST)")] Static void loadtestscene () {dictionary <string, leveltileset> allpieces = loadallpiece (); levellayout layout = new levellayout (); layout. parsefile ("assets/model/MAP/layouts/testroom/1x1single_room_a/testroom. layout "); buildlayout (allpieces, layout. alltiles);} static void buildlayout (Dictionary <string, leveltileset> allpieces, list <levellayouttile> alltiles) {foreach (VAR I TEM in alltiles) {foreach (VAR tileset in allpieces) {If (item. pieceguid = NULL | item. pieceguid. length = 0) {continue;} leveltilepiece = tileset. value. searchpiece (item. pieceguid); If (piece! = NULL & piece. filepath. count> 0) {string assetpath = getrealfilepath (piece. filepath [0]); debug. log (piece. filepath [0] + "" + assetpath); // break; gameobject OBJ = assetdatabase. loadassetatpath (assetpath, typeof (gameobject) as gameobject; debug. log (OBJ); gameobject obj2 = instantiate (OBJ) as gameobject; obj2.transform. position = new vector3 (item. position. x, item. position. y, item. position. z *-1); float anglex =-mathf. asin (item. rotationforward. y)/mathf. pI * 180; float angley = mathf. atan2 (item. rotationforward. x,-item. rotationforward. z)/mathf. pI * 180; float anglez = mathf. atan2 (item. rotationright. y, item. rotationup. y)/mathf. pI * 180; debug. log (string. format ("rforward: {0} rRight: {1} RUP: {2} ax: {3} ay: {4} AZ: {5}", item. rotationforward, item. rotationright, item. rotationup, anglex, angley, anglez); obj2.transform. rotation = Quaternion. euler (New vector3 (anglex, angley, anglez); obj2.transform. localscale = new vector3 (item. scale. x, item. scale. y, item. scale. z );}}}}


 

Here, an fbx model is instantiated directly. In actual application, we should first create a prefab And then instantiate the Prefab. This is helpful both in the optimization and engineering aspects.

 

Iii. Resources for loading torch light:

I have previously written an article about how to export resources from torch light, but I have made several updates to the actual problems after a long time. For example, you can write a script to perform batch conversion. You can determine the existence of an XML file in advance and delete it if the conversion is not completed. This greatly improves the speed of batch conversion; animation-free files can be exported using the latest blender, which has no obvious advantages. However, because you are not familiar with the blender API, the blender API has been significantly modified in version 2.5, so the export scripts or functional scripts of the two versions cannot be converted to each other. The following is my current script:

Auto_covert_mesh.py

import glob,sys,osBLENDER = r"E:\MyProj\blender-2.49b-windows\blender";DUMMY_BLEND = r"E:\MyProj\unity3d\arpg36\ARPG\Tool\dummy.blend"CONVERT_SCRIPT = r"E:\MyProj\unity3d\arpg36\ARPG\Tool\convert_mesh.py"BLENDER259 = r"E:\MyProj\blender-2.71-windows64\blender";DUMMY_BLEND259 = r"E:\MyProj\unity3d\arpg36\ARPG\Tool\dummy.blend"CONVERT_SCRIPT259 = r"E:\MyProj\unity3d\arpg36\ARPG\Tool\convert_mesh_259.py"def convert_path(path, animation):    for root, dirs, files in os.walk(path):        for dir in dirs:            strDir = os.path.join(root, dir);            #print(strDir);        for file in files:            file = file.lower();            strFile = os.path.join(root, file);            #print(strFile);            if strFile.find(".mesh") != -1 and strFile.find(".meta") == -1 and strFile.find(".xml") == -1:                output = strFile.replace(".mesh", ".fbx");                if not os.path.exists(output):                    print("--------------" + strFile);                    if animation:                        os.system("{0} -b {1} -P {2} -- {3}".format(BLENDER, DUMMY_BLEND, CONVERT_SCRIPT, strFile));                    else:                        os.system("{0} -b {1} -P {2} -- {3}".format(BLENDER259, DUMMY_BLEND259, CONVERT_SCRIPT259, strFile));        #return    for root, dirs, files in os.walk(path):        for file in files:            file = file.lower();            if file.find(".mesh") != -1 or file.find(".skeleton") != -1 or file.find(".xml") != -1 or file.find(".material") != -1 or file.find(".adm") != -1:                strFile = os.path.join(root, file);                os.remove(strFile);convert_path(r"E:\Backup\MEDIA_png\levelsets\props\test", False);


Convert_mesh.py

import Blenderimport bpyimport sysimport os,globsys.path.append(r"E:\MyProj\blender-2.49b-windows\.blender\scripts\torchlight");sys.path.append(r"E:\MyProj\blender-2.49b-windows\.blender\scripts");import importTL,export_fbxdef ImportMesh(file):    print file;    scn = bpy.data.scenes.active    #Scene.Unlink(scn);    importTL.ImportOgre(file);    file = file.lower();    output = file.replace(".mesh", ".fbx");    export_fbx.fbx_default_setting();    export_fbx.fbx_write(output);    return True;ImportMesh(sys.argv[6]);


Convert_mesh_259.py

########################################################### Custom Blender -> Unity Pipeline# http://www.mimimi-productions.com, 2014# Version: 1.9# Only for Blender 2.58 and newer## Thanks to kastoria, jonim8or and Freezy for their support!# Special thanks to Sebastian hagish Dorda for implementing the sort methods.# http://www.blenderartists.org########################################################### Fixes the -90 degree (x-axis) problem for Unity.# Artists and coders simply work as they should.# -> No more custom rotation-fixes in Unity or Blender.########################################################### HISTORY# 1.9, CLEANUP -- removed support for old Blender versions, only support 2.58 and newer# 1.8, FIX -- applies transforms in order (parents prior childs)# 1.7, FIX -- shows hidden objects prior importing# 1.6b, FIX -- Apply mirror modifiers before rotating anything else# 1.6a, FIX -- deselect all objects, otherwise deleting wrong objects when using UNITY_EXPORT flag# 1.6, FEATURE -- support UNITY_EXPORT flag --> set via MiBlender-Tools or e.g.: bpy.data.objects['enemy_small']['UNITY_EXPORT'] = False# 1.6, FIX -- now import empties# 1.5, FIX -- make all objects single user, otherwise instances can't be imported# 1.4, FIX -- show all layers, necessary for rotation fix# 1.3, FIX -- location constraints are now deactivated (due to rotation prior to export)# 1.2, FIX -- apply rotation worked only on selection! (thx jonim8or)# 1.1, FIX -- object mode doesn't need to be set in file anymore########################################################### TO DO# ISSUE -- do not use empties as parents (rotation can't be applied to them!)# ISSUE -- transform animations are missing because we are not exporting the default take --> thus only bone-animations are working?!# ISSUE -- LIMIT_LOCATION animation constraint is forbidden! Will be muted and not work in engine (anim might look different compared to Blender)# 2.0, FEATURE -- support UNITY_EXPORT_DEFAULT_TAKE --> can export no-bone-animations to Unity##########################################################import bpyimport sysimport os,globimport osimport timeimport math  # math.pifrom mathutils import Vector, Matrixfrom functools import cmp_to_keysys.path.append(r"E:\MyProj\blender-2.71-windows64\2.71\scripts\addons\torchlight");sys.path.append(r"E:\MyProj\blender-2.71-windows64\2.71\scripts\addons\io_scene_fbx");import TLImport,export_fbxOGRE_XML_CONVERTER = r"E:\MyProj\unity3d\arpg36\OgreCommandLineTools_1.7.2\OgreXmlConverter.exe"def ImportMesh(file):    print(file);    TLImport.load(None, bpy.context, file, OGRE_XML_CONVERTER, False);    # SORTING HELPERS (sort list of objects, parents prior to children)    # root object -> 0, first child -> 1, ...    def myDepth(o):         if o == None:            return 0        if o.parent == None:            return 0        else:            return 1 + myDepth(o.parent)    # compare: parent prior child    def myDepthCompare(a,b):        da = myDepth(a)        db = myDepth(b)        if da < db:            return -1        elif da > db:            return 1        else:            return 0    # Operator HELPER    class FakeOp:        def report(self, tp, msg):            print("%s: %s" % (tp, msg))    # Rotation matrix of -90 around the X-axis    matPatch = Matrix.Rotation(-math.pi / 2.0, 4, 'X')    # deselect everything to close edit / pose mode etc.    bpy.context.scene.objects.active = None    # activate all 20 layers    for i in range(0, 20):        bpy.data.scenes[0].layers[i] = True;    # show all root objects    for obj in bpy.data.objects:        obj.hide = False;    # make single user (otherwise import fails on instances!) --> no instance anymore    bpy.ops.object.make_single_user(type='ALL', object=True, obdata=True)    # prepare rotation-sensitive data    # a) deactivate animation constraints    # b) apply mirror modifiers    for obj in bpy.data.objects:        # only posed objects        if obj.pose is not None:            # check constraints for all bones            for pBone in obj.pose.bones:                for constraint in pBone.constraints:                    # for now only deactivate limit_location                    if constraint.type == 'LIMIT_LOCATION':                        constraint.mute = True        # need to activate current object to apply modifiers        bpy.context.scene.objects.active = obj        for modifier in obj.modifiers:            # if you want to delete only UV_project modifiers            if modifier.type == 'MIRROR':                bpy.ops.object.modifier_apply(apply_as='DATA', modifier=modifier.name)    # deselect again, deterministic behaviour!    bpy.context.scene.objects.active = None    # Iterate the objects in the file, only root level and rotate them    for obj in bpy.data.objects:                if obj.parent != None:            continue        obj.matrix_world = matPatch * obj.matrix_world    # deselect everything to make behaviour deterministic -- instead of "export selected" we use the UNITY_EXPORT flag    for obj in bpy.data.objects:        obj.select = False;    # apply all(!) transforms     # parent prior child    for obj in sorted(bpy.data.objects, key=cmp_to_key(myDepthCompare)):        obj.select = True;        # delete objects with UNITY_EXPORT flag        # if flag not saved, then assume True        if obj.get('UNITY_EXPORT', True) == False:            bpy.ops.object.delete()        # apply transform if not deleted        else:            bpy.ops.object.transform_apply(rotation=True)        # deselect again        obj.select = False;    file = file.lower();    output = file.replace(".mesh", ".fbx");    export_fbx.save(None, bpy.context, filepath=output, global_matrix=None, use_selection=False, object_types={'ARMATURE', 'EMPTY', 'MESH'}, use_mesh_modifiers=True, use_armature_deform_only=True, use_anim=True, use_anim_optimize=False,use_anim_action_all=True, batch_mode='OFF', use_default_take=False);    return True;ImportMesh(sys.argv[6])


Iv. Difficulties and problems encountered

1. The Z axis is up or Y axis is up. Blender and 3dmax are both Z axis up, while unity3d is Y axis up. Some other software such as Maya uses the Y axis by default but can be set by itself; unreal seems to be the Z axis up. The specific axis is not absolutely good or bad, but incompatibility between different animation production software and game engines is indeed disgusting. In most cases, the blender or 3dmax export plug-in will help us make this adjustment to ensure that the visual effects of the software and engine are consistent. But blender is not good enough, its fbx export has set the global rotation matrix, In the 2.4 version of the export plug-in, we can directly set the RotX-90, in the latest version 2.7, the Axis corresponding to the forward direction and Y direction is selected, and a global matrix is set in essence in the code. However, the problem is that the exported object shows the X axis rotation-90 in unity. Although the visual effects are consistent, however, the setting of this axis of rotation makes our actual code operations somewhat uncomfortable. If you export both camera and lamp, there will be a parent node, which is the actual model, while the parent node does not rotate, because this problem was not found earlier, because everything looks correct. In convert_mesh_259 above, there is a large amount of code to fix this problem, that is, we rotate the model directly in the blender without setting the rotation matrix, so that the blender and unity are completely correct. This is a perfect solution.

2. The rotation matrix is also the ouarla corner. The torch light configuration file uses three vector directions to represent the orientation, namely, forward (corresponding to the Z axis) Right (corresponding to the X axis) and up (corresponding to the Y axis ). The vectors in these three directions form a rotation matrix (This matrix is obtained by multiplying the rotation matrix around each axis by a fixed order, and the matrix should be arranged in the order of x y z, then multiply by Z x Y). Assume that the Z angle is rotated by the Z axis, the X angle is rotated by the X axis, and the Y angle is rotated by the Y axis, then the matrix formula is (in which CZ represents cos (z) SZ represents sin (z )):

CZ * Cy + SX * Sy * SZ * CX-sy * CZ + SZ * SX * Cy ------------ right ---> X

-SZ * Cy + cz * SX * Sy CZ * CX Sy * SZ + SX * Cy * CZ -------------- up -------> Y

CX * sy-sx cx * Cy --------------------------- forward-> Z

The configuration corresponding to the torch light is:

Right. X right. y right. Z

Up. x up. y up. Z

Forward. x forward. y forward. Z

Their default values are:

1 0 0

0 1 0

0 0 1

We already know right. x/y/z up. x/y/z forward. x/y/z, which is the three vectors corresponding to the torch light editor. The above matrix can be obtained:

X =-sin (forward. Y)

Y = atan2 (forward. X, forward. Z)

Z = atan2 (right. Y, up. Y)

In this way, we can get the transform. Rotation required by unity based on the torch light configuration ). If no axis is configured in the configuration, the default value is used.

3. Left-hand or right-hand coordinates.

The torch light is in the right-hand coordinate system. By default, the x-axis is oriented outward. Unity is the left-hand coordinate system. By default, the orientation of the Z axis is in the forward direction. Now it involves the conversion from a right-hand coordinate system to a left-hand coordinate system. Here, the translation matrix and the rotation matrix are converted. The translation matrix is easy to use. You can reverse the zcoordinate directly. After searching for the rotating matrix for half a day, there is no clear answer. Here I will take forward. Z as the inverse, and then calculate a new Z in the formula above. It seems that the result is OK.

Combining 2 and 3 is the specific code implementation in the second largest item above.

 

V. troubleshooting of subsequent problems

1. lighting. Loading models is only the most basic step. If you want to achieve the effect of torch, you still need to adjust a lot of details. For example, the shader should be rewritten based on the situation, rather than using the default diffuse. Lighting is also an important part. The overall effect of TORCH 2 and Diablo 3 is achieved by lighting, the effects mentioned here are not advanced rendering technologies such as real-time shadows and ray tracing, but the most basic settings of light brightness, tones, and ranges. If these settings are complete, you can enjoy a very comfortable experience. Lightingmap is mainly used on the mobile phone to bake the scenario, which can achieve the desired effect and efficiency.

2. Particle effect. The light effects of a game are the main cause. Here we will not discuss the masterpiece of the next era, but in the case of limited equipment, limited funds, or limited personnel capabilities, what is the most eye catching thing. After the light effects are done, a simple action can be used to design very cool skills. A simple weapon model with a light-emitting particle light effects can become an excellent inheritance equipment, even if the characters do a little less, with a surround lightning light effect can also pretend to be Raytheon. The main application scenarios of particle effects include skill, weapon luminous effect, flame in the scene, and other special performances, such as bloody corpse explosion. Torch light has achieved a great blow to the extreme of the two points. One is the combination of the light effects, screen vibrations, and sound effects of the attacks, and the other is the explosive growth and split of monsters after their death.

But with so much said, the particle effect cannot be reused, and it is a tragedy. If the technology is strong enough, consider porting the particle system as a whole. Similar work has been done by xffector. However, considering the technical difficulty and workload, this is only theoretically feasible.

3. Dynamic generation scenarios. Originally, I thought that the dynamic generation of torch light scene was a very advanced technology. However, after studying it, it only achieved the purpose of dynamic scene generation by using simple settings. First, each [piece] can contain multiple models. These models are randomly selected when generated, so that the details in the scenario are different each time. Then, many different scenarios are designed for the same level area, and the style of the scenario can be ever-changing, you only need to meet the most basic task settings, scenario link settings, and exit entry settings with certain rules. During the generation of the entire level, the appropriate regional block will be randomly selected based on the layout chunk rules (that is, a layout implemented above) to form a big scenario.

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.