Skeletal Mesh Importing via UnrealScript
This page displays a list of the import commands for skeletal meshes in UT2004. Most obsolete parameters have been left out. Sometimes you may want to package your .psk and .psa files into a .u file. Here I will show you how to do that and also some other import commands for skeletal meshes that you might find useful. The order in which these commands are given is important but straightforward (for example, in order to reference or digest an animation set, it first must be imported).I have presented them here in a correct order. It’s important to remember that almost any errors made in the import code will be silently ignored by the compiler and the package will usually always compile. The compiler should log a warning if any none optional parameters are missing, although it usually wont tell you what is missing. But it will still compile. The warnings may look like this.
ExecWarning: C:\UT2004\MyPackage\Classes\MyModel.uc(3) : ExecWarning, Bad MODEL IMPORT ExecWarning: C:\UT2004\MyPackage\Classes\MyModel.uc(4) : ExecWarning, Bad MESH LODPARAMS ExecWarning: C:\UT2004\MyPackage\Classes\MyModel.uc(5) : ExecWarning, Bad MESH ORIGIN ExecWarning: C:\UT2004\MyPackage\Classes\MyModel.uc(6) : ExecWarning, Missing Mesh ExecWarning: C:\UT2004\MyPackage\Classes\MyModel.uc(7) : ExecWarning, Bad MESH ATTACHNAME parameters.
To import the psk and psa files they must be placed in a folder located inside your new package folder. This folder can be named anything, the most common name is “Models” in order to keep the file structure neat and consistant. You will need a .uc file contained within the “Classes” folder to contain the import code. You can extend any actor or object of your choice, and the name is not important either. This file is basically just a placeholder for the import code. Remember that in order to view the model in the animation browser you might need to first load your package in the actor browser.
Example C:\UT2004\MyPackage\Models
class MyModelImport extends Actor; //code goes here
You can download a .uc file I made that contains examples of all of the code featured on this page here Skeletal Import Code. Although almost all the parameters are optional, I have put “No” if leaving the parameter out would create a broken or worthless command. The first step is to import the model and set some parameters that go with it.
#Exec MESH MODELIMPORT Parameters:
MESH | This specifies the name of the mesh. | Optional: No |
MODELFILE | This specifies the path to the psk file for import. | Optional: No |
GROUP | If you want you can assign the mesh to a group. | Optional: Yes |
MLOD | A boolean value (0 or 1). It controls whether or not to use LOD (level of detail) on this mesh. Use 0 if you want to disable any detail loss. | Optional: Yes |
LODSTYLE | A bit field with switches that changes the style of building for the level of detail collapse sequences.1: Value curvature over length. 2: Protect the edges of doublesided polygons – like the CTF flags. 4: Try to respect texture seams more. Use this if there is too much ‘stretching’ going on. 8: Value length over curvature. Needed for unwelded, multi-element, or otherwise ‘open’ meshes like the new superhealth. 16: Translucent polygons will be collapsed less early in the LOD sequence. (Broken in the 224 code base.) |
Optional: Yes |
LODFRAME | With this you can pick a frame, other than the default 0th frame to be sampled for generating the collapse sequence. | Optional: Yes |
LODNOTEX | A boolean value. If set, causes texture coordinates to be ignored when importing. This improves performace. It’s good for models that will only ever have 1 flat texture (constant colour such as red or blue). It’s also good for those models that might only ever be seen in the far distance behind clouds or fog. | Optional: Yes |
LODOLD | A boolean value. Maintain the original order of animation vertices as they are imported. If active, this means some internal reorganization will be done at load time, instead of compile time. Included to make differential patching of older content feasible. | Optional: Yes |
LODSPECIFY | A boolean value. 0 means it will automatically create the LOD levels for you. 1 assumes you wish to create them yourself using the LODMODEL command. | Optional: Yes |
DOSMOOTH | A boolean value. If 1 then the LOD level changes appear smoother. 0 results in more visible popping but increase in performance. | Optional: Yes |
//Examples of minimum requirements and including optional settings #Exec MESH MODELIMPORT MESH=MyMesh MODELFILE=Models\MyMesh.PSK #Exec MESH MODELIMPORT MESH=MyMesh MODELFILE=Models\MyMesh.PSK GROUP=MyMeshGroup MLOD=1 LODstyle=8 LODFRAME=0 LODNOTEX=0 LODOLD=0 LODSPECIFY=0 DOSMOOTH=1
The next step is to set any additional LOD settings that may be desired (optional).
#Exec MESH LODPARAMS parameters:
MESH | This specifies the name of the mesh that we are setting LOD parameters for. | Optional: No |
STRENGTH | LOD scaler. The default is 1.0. Tweak this setting higher for more aggressive LOD-culling, lower it if you see the mesh distort too early. | Optional: Yes |
MINVERTS | The minimum number of vertices you want your mesh to always retain at the farthest distances. Maximum appears to be 887. | Optional: Yes |
MORPH | Set it to 0.0 for no morphing, any other value up to 1.0 indicates the proportion of vertices that are allowed to contribute to the smooth morphing. More means less popping, but at the cost of more CPU time. Useful values are 0.25 – 0.4, the default is currently 0.3. | Optional: Yes |
ZDISP | This specifies (in Unreal units) the distance at which the LOD culling kicks in. | Optional: Yes |
//Example including optional settings #Exec MESH LODPARAMS MESH=MyMesh STRENGTH=1 MINVERTS=10 MORPH=0.4 ZDISP=500
If you set LODSPECIFY=1 when importing the model, you can now specify your own LOD levels.
#Exec MESH LODMODEL parameters:
MESH | The name of the mesh we are creating LOD levels for. | Optional: No |
LEVEL | The LOD level we are creating. | Optional: No |
HYSTERESIS | This value gives a range (around the DistanceFactor) within which the level of detail will be ‘sticky’ and not change. Any reasonably small value ( like 0.01 ) will help eliminate potential flicker that would otherwise occur when a mesh happens to sit at the exact boundary of two LODs, distance-wise. This value may be obsolete as it always appear to revert to 0.02 on import. | Optional: Yes |
DISTANCEFACTOR | This number tells the engine when to start using the next detail level. Lower numbers indicate that the model must be farther away before the next LOD level will activate. | Optional: Yes |
REDUCTION | An approximate value between 0 and 1, indicating how many vertices to collapse. 1 forces full detail, so the smaller the number the fewer the vertices that will be preserved. Defaults to 1. | Optional: Yes |
MAXINFLUENCES | An int value with a maximum setting of 7. You should try not to use more than 3 as it will impact performace. A limit to the maximum number of bones influencing (deforming) each vertex during animation. | Optional: Yes |
COHERENCE | A boolean value, whether or not to reorder the skeletal mesh triangles (on import) for optimal coherence. Defaults to 0. | Optional: Yes |
FROMMESH | The name of the mesh you wish to import (a .psk file that must be imported before this command) to use at this level of detail, instead of using the generated levels. | Optional: Yes |
//Examples of FROMMESH and manual LOD levels including optional settings #Exec MESH MODELIMPORT MESH=MyLOD0Mesh MODELFILE=Models\MyLOD0Mesh.PSK #Exec MESH LODMODEL MESH=MyMesh LEVEL=0 FROMMESH=MyLOD0Mesh #Exec MESH LODMODEL MESH=MyMesh LEVEL=1 HYSTERESIS=0.02 DISTANCEFACTOR=1 REDUCTION=1 MAXINFLUENCES=3 COHERENCE=1
Now it’s time to set the origin and rotation of the mesh (optional). These are useful if errors were made in the 3d package that was used to create the model.
#Exec MESH ORIGIN parameters:
MESH | This specifies the name of the mesh that we are setting the parameters for. | Optional: No |
X, Y, Z | Here you can set the origin of the mesh. | Optional: Yes |
YAW,PITCH, ROLL | Here you can set the rotation of the mesh. The rotation unit is a byte.255 = 360 degrees (65536) 192 = 270 degrees (49152) 128 = 180 degrees (32768) 64 = 90 degrees (16384) |
Optional: Yes |
//Example including optional settings #Exec MESH ORIGIN MESH=MyMesh X=10 Y=0 Z=50 YAW=0 PITCH=64 ROLL=192
The next step is to set the scale of the mesh otherwise it will default to 0 (optional). Even though this step is optional, not doing it would result in an invisible mesh as the drawscale would be 0. So this step is highly recommended!
#Exec MESH SCALE parameters:
MESH | This specifies the name of the mesh that we are setting the parameters for. | Optional: No |
X, Y, Z | Here you can set the scale of the mesh. | Optional: Yes |
//Example including optional settings #exec MESH SCALE MESH=MyMesh X=1 Y=1 Z=1
The next step is to create any desired attachments also known as sockets (optional). Don’t forget if you are creating a new character then you might need to create a weapon bone socket called “righthand” and a “FlagHand” bone for game types such as Capture the Flag and Bombing Run.
#Exec MESH ATTACHNAME parameters:
MESH | This specifies the name of the mesh that we are setting the parameters for. | Optional: No |
BONE | Put here the name of the bone on the model that you wish to create an attachment for. This is a string variable and needs to be enclosed in quotation marks. | Optional: No |
TAG | This is the attach alias (name) that you wish this socket to be known as. This is a string variable and needs to be enclosed in quotation marks. | Optional: No |
YAW, PITCH, ROLL | You can tweak the rotation of the attachment here. The rotation unit is a byte just like with the MESH ORIGIN parameters. | Optional: Yes |
X, Y, Z | Here you can set the relative location of the attachment. | Optional: Yes |
//Example including optional settings #exec MESH ATTACHNAME MESH=MyMesh BONE="L_Hand" TAG="WeaponBone" YAW=-64.0 PITCH=00.0 ROLL=128.0 X=0 Y=0 Z=0
If yu wish, you can change the bounding box which is created automatically for you to one that better fits the model (optional).
#Exec MESH BOUNDINGBOX parameters:
MESH | The name of the mesh that has the bounding box we wish to change. | Optional: No |
XMIN, YMIN, ZMIN | Change the lower limits of the box here. | Optional: Yes |
XMAX, YMAX, ZMAX | Change the upper limits of the box here. | Optional: Yes |
//Example including optional settings #Exec MESH BOUNDINGBOX MESH=MyMesh XMIN=-50.0 YMIN=-50.0 ZMIN=-50.0 XMAX=50.0 YMAX=50.0 ZMAX=50.0
Next it is time to import the animation file that goes with the model, if it has one (optional).
#Exec ANIM IMPORT parameters:
ANIM | This specifies the name of the animation set. | Optional: No |
ANIMFILE | This specifies the path to the psa file for import. | Optional: No |
MAXKEYS | This seems like it is supposed to control the number of keys in the animation set as a whole, but it appears to have no effecet. May be obsolete. | Optional: Yes |
IMPORTSEQS | Appears to be a boolean value. But setting it to either 0 or 1 appears to have the same effect. May be obsolete. | Optional: Yes |
COMPRESS | This compresses the sequences (removes keys). The value ranges from 0 to 1. Defaults to 1. | Optional: Yes |
//Example including optional/obsolete settings #Exec ANIM IMPORT ANIM=MyAnims ANIMFILE=Models\MyAnims.PSA MAXKEYS=999999 IMPORTSEQS=1 COMPRESS=0.8
Now it’s possible to change specific animation sequence information such as the group or rate. This must go before the #Exec ANIM DIGEST command.
#Exec ANIM SEQUENCE parameters:
ANIM | The name of the animation set the sequence resides in, which we wish to change. | Optional: No |
SEQ | The name of the sequence you wish to change. | Optional: No |
GROUP | Here you can assign the animation sequence to a group. | Optional: Yes |
RATE | You can change the rate of the animation sequence here. | Optional: Yes |
//Example including optional settings. #Exec ANIM SEQUENCE ANIM=MyAnims SEQ=Walk GROUP=Movement RATE=20.000000
The animations now need to be “digested” before they will do anything.
#Exec ANIM DIGEST parameters:
ANIM | This specifies the name of the animation set we want to digest. | Optional: No |
VERBOSE USERAWINFO | Include this phrase to make the compiler log information about the digest process. | Optional: Yes |
//Example including optional settings #Exec ANIM DIGEST ANIM=MyAnims VERBOSE USERAWINFO
The next step is to link the animation set to the desired mesh (this sets the default animation set of the mesh).
#Exec MESH DEFAULTANIM parameters:
MESH | This specifies the name of the mesh we wish to link the animation to. | Optional: No |
ANIM | This specifies the name of the animation set we are linking to the mesh. | Optional: No |
//Example #Exec MESH DEFAULTANIM MESH=MyMesh ANIM=MyAnims
Now that the animation information “exists” you can create animation notifies. This must be placed after the #Exec ANIM DIGEST command. To set an ANIM NOTIFY you have the option of using TIME or FRAME. Only one or the other can be used. If you try to use both it will accept the first one and ignore the second.
#Exec ANIM NOTIFY parameters:
ANIM | The name of the animation set the sequence resides in, which we wish to add a notify for. | Optional: No |
SEQ | The name of the sequence we want to create a notify for. | Optional: No |
TIME | This is where to place the notify. TIME appears to be more accurate than FRAME. The range is 0 to 1. To find the correct value the math is:Frame / TotalFrames
So if you wanted to place a notify on frame 1.58 (of a 26 frame total animation) you would put 0.06. |
Optional: Yes |
FRAME | You can choose a specific frame to apply the notification to instead of using TIME. This can be off by anywhere up to 0.5 of a frame probably due to compression. | Optional: Yes |
FUNCTION | The name of the function that will be called for this notify. This function should exist within the actor that has this mesh when its drawtype is DT_Mesh. | Optional: No |
//Examples of FRAME and TIME #Exec ANIM NOTIFY ANIM=MyAnims SEQ=Punch TIME=0.4 FUNCTION=MeleeAttack #Exec ANIM NOTIFY ANIM=MyAnims SEQ=Punch FRAME=10 FUNCTION=MeleeAttack //In this example the FRAME parameter will be ignored #Exec ANIM NOTIFY ANIM=MyAnims SEQ=Punch TIME=0.4 FRAME=10 FUNCTION=MeleeAttack
Finally, you can apply textures (or materials) to the mesh. But in order to do that something called a “meshmap” must be created. The meshmap can also be used to resize the mesh.
#Exec MESHMAP NEW parameters:
MESHMAP | The name of the meshmap we are creating, this must be the same as the mesh we are creating it for. | Optional: No |
MESH | The name of the mesh we are creating the meshmap for. | Optional: No |
//Example #Exec MESHMAP NEW MESHMAP=MyMesh MESH=MyMesh
You can use the meshmap to change the scale of the mesh (optional).
#Exec MESHMAP SCALE parameters:
MESHMAP | The name of the meshmap we are creating, this must be the same as the mesh we are creating it for. | Optional: No |
X, Y, Z | Changes the scale of the mesh (does the same as the MESH SCALE command). | Optional: No |
//Example #Exec MESHMAP SCALE MESHMAP=MyMesh X=0.5 Y=0.1 Z=1
To set the textures use the SETTEXTURE command. The textures should exist at compile time. If your model has more than one material applied it will need to be prepared correctly.You can read here how to do that in 3ds Max.
#Exec MESHMAP SETTEXTURE parameters:
MESHMAP | The name of the meshmap that was created for this model. | Optional: No |
NUM | The position in the skin array where this texture should go. For example NUM=0 corresponds to Skins[0]. | Optional: No |
TEXTURE | The name of the texture (or material) to apply to this skin slot. The texture should be referenced first, either by importing the texture into the package or by loading the package it resides in.IMPORT TEXTURE (via UnrealScript) LOADING TEXTURE (via UnrealScript) |
Optional: No |
//Example including texture import #Exec TEXTURE IMPORT NAME=HeadTexture FILE=Images\MyHeadTexture.DDS GROUP=MyMeshTextures #Exec TEXTURE IMPORT NAME=BodyTexture FILE=Images\MyBodyTexture.DDS GROUP=MyMeshTextures #Exec TEXTURE IMPORT NAME=WeaponTexture FILE=Images\MyWeaponTexture.DDS GROUP=MyMeshTextures #Exec MESHMAP SETTEXTURE MESHMAP=MyMesh NUM=0 TEXTURE=HeadTexture #Exec MESHMAP SETTEXTURE MESHMAP=MyMesh NUM=1 TEXTURE=BodyTexture #Exec MESHMAP SETTEXTURE MESHMAP=MyMesh NUM=2 TEXTURE=WeaponTexture
TIP – Create a “resource” .uc file that holds all of the import information, this will save time and keep things neat.
IMPORTSEQS parameter in #Exec ANIM IMPORT directive was used in 1st generation of Unreal Engine.
When set to false (0) animation sequence list would be re-created on import by using #Exec ANIM SEQUENCE directive. Example line should look like this:
#Exec ANIM SEQUENCE ANIM=MyAnims SEQ=Walk GROUP=Movement STARTFRAME=0 NUMFRAMES=20 RATE=20.000000
Format used here is somehow bridging unreal vertex animation formats _d.3d/_a.3d with skeletal animation formats .psk/.psa. Former is not capable to include animation sequence data; later is capable. However presence of anim sequence list depends on capabilities of exporter/modeling (animating) SW used.
So this feature will come extremely handy when dealing with exporters incapable to export PSA including animation sequences (e.g. MilkShape3D that just produces one anim loop per whole anim timeline).