Beginning Your Game Part 3   31 comments

IMPORTANT

This tutorial was created with the March build of UDK, as opposed to the February build.

This is a big -MY BAD- on my part.

The rest of the tutorials flow nicely after this. I promise.

Here is what you do:

You download the March build.

You install it.

You set up the config files just like you have been doing in Part 1 and Part 2.

YOU THEN DOWNLOAD THIS .ZIP which has the code finished from Part 3. Don’t worry about what you are missing out, if you read through the tutorial you’ll get the important stuff.

Open UTGameConfigDefaultGame.ini

Replace the Engine.GameInfo block with the following:

[Engine.GameInfo]
DefaultGame=UDKGame.UDKGame
DefaultServerGame=UDKGame.UDKGame
PlayerControllerClassName=UDKGame.HTPlayerController
GameDifficulty=+1.0
MaxPlayers=32
DefaultMapPrefixes=(Prefix="HT",GameType="UDKGame.TheHuntGame")

What we did there was move the DefaultMapPrefixes from DefaultProperties to this .ini file, as thats where the March build put it. You will learn how to do stuff like this later on as well.

When you compile, you will get a warning about HTInventoryManager. This will fix itself when you complete step 4.

Then continue to Step 4.

Also, skip Migrating From Feb. To March. since you are now using the March build. <_<

Sorry. These were my first tutorials I’ve made and I was bound to mess up somewhere. All the future tutorials after this will go smoothly. I will try to redo these first three later when I have some spare time.

Video Version

Subject: Beginning Your Game Part 3
Skill Level: Beginner
Run-Time: 16 Minutes
Author: Michael Allar
Notes: The project I’m working on as I’m creating this documentation requires the classes we’ve made to be based off higher level classes. These were the changes made.

Streaming:     720×480 1920×1080

Download:     Low-Res (32MB) Hi-Res (72MB)

Written Version

Subject: Beginning Your Game Part 3
Skill Level: Beginner
Author: Michael Allar
Notes: The project I’m working on as I’m creating this documentation requires the classes we’ve made to be based off higher level classes. These were the changes made.

In order to make these changes, you must be using the February build or later of UDK.

Why Is There A Part 3?

I am the Lead Programmer for a student ran project at The Art Institute of Orange County called The Hunt. It is a standalone game using Unreal Engine 3 being developed with the Unreal Development Kit. I am creating these tutorials as I progress in development of The Hunt and we’ve recently had a need to base our code off of higher level classes within the engine. Our goal is to stay away from as much UT code as possible without rewriting too much of everything. Instead of extending UTGame, UTPlayerController, and UTPawn, we will be extending GameInfo, UDKPlayerController, and UDKPawn.

UDKGame now extends GameInfo

/*******************************************************************************
	UDKGame

	Creation date: 14/01/2010 13:55
	Copyright (c) 2010, Michael Allar, Epic

*******************************************************************************/

class UDKGame extends GameInfo
	config(UDKGame);

struct GameTypePrefix
{
	var string Prefix;
	var string GameType;
};

var array<GameTypePrefix> DefaultMapPrefixes;

static event class<GameInfo> SetGameType(string MapName, string Options, string Portal)
{
	local string ThisMapPrefix;
	local int i,pos;
	local class<GameInfo> NewGameType;

	if (Left(MapName, 10) ~= "HTFrontEnd")
	{
		return class'UDKGame';
	}

	// strip the UEDPIE_ from the filename, if it exists (meaning this is a Play in Editor game)
	if (Left(MapName, 6) ~= "UEDPIE")
	{
		MapName = Right(MapName, Len(MapName) - 6);
	}
	else if ( Left(MapName, 5) ~= "UEDPC" )
	{
		MapName = Right(MapName, Len(MapName) - 5);
	}
	else if (Left(MapName, 6) ~= "UEDPS3")
	{
		MapName = Right(MapName, Len(MapName) - 6);
	}
	else if (Left(MapName, 6) ~= "UED360")
	{
		MapName = Right(MapName, Len(MapName) - 6);
	}

	// replace self with appropriate gametype if no game specified
	pos = InStr(MapName,"-");
	ThisMapPrefix = left(MapName,pos);

	// change game type
	for ( i=0; i<Default.DefaultMapPrefixes.Length; i++ )
	{
		if ( Default.DefaultMapPrefixes[i].Prefix ~= ThisMapPrefix )
		{
			NewGameType = class<GameInfo>(DynamicLoadObject(Default.DefaultMapPrefixes[i].GameType,class'Class'));
			if ( NewGameType != None )
			{
				return NewGameType;
			}
		}
	}

	return class'UDKGame';
}

defaultproperties
{
	DefaultPawnClass=class'UDKGame.HTPawn'
	PlayerControllerClass=class'UDKGame.HTPlayerController'
	DefaultMapPrefixes(0)=(Prefix="HT",GameType="UDKGame.TheHuntGame")
}
You will see that the main change here is the struct GameTypePrefix, var array<GameTypePrefix> DefaultMapPrefixes;, and the event  SetGameType. Because we are now basing UDKGame of of GameInfo instead of UTGame, we have to restore the map prefix functionality that is present in UTGame but is missing in GameInfo.
struct GameTypePrefix
{
     var string Prefix;
     var string GameType;
};
This declares a struct for a class that holds two strings, Prefix and GameType. A struct is essentially a set of variables in a variable or “structure”. Every instance of GameTypePrefix has a Prefix of GameType, which allows us to make an organized array of this data. This may make more sense when we see how it is used.
var array<GameTypePrefix> DefaultMapPrefixes;
This declares an array of our struct called DefaultMapPrefixes. An array can be thought of as a collection of objects that you can add, remove, or edit the objects within. DefaultMapPrefixes will hold all of our default map prefixes for our different map names and game types. We will assign these in the default properties block at the end of the class.
static event class<GameInfo> SetGameType(string MapName, string Options, string Portal)
{
	local string ThisMapPrefix;
	local int i,pos;
	local class<GameInfo> NewGameType;

	if (Left(MapName, 10) ~= "HTFrontEnd")
	{
		return class'UDKGame';
	}
This is an event. Events are usually called automatically from other code when an event triggers. In this case, when the engine loads the UDKGame class it calls this event to see if we should set the game type to a different GameInfo class. It is given three strings, MapName, Options, and Portal. The only one we will use in our logic is MapName. We then have three lines of code declaring local variables. local variables are the same as variables we have been using before (var) except they only exist in the function they are declared in (also known as scope). The string ThisMapPrefix will be used to store the map prefix of the currently loaded map or MapName. “i” is used as an iterator for a for loop we will be running later, while pos is an integer that stores the location of a “-” in the map name if one exists (which we will calculate later). NewGameType is a variable of class GameInfo that we will be using to return the new GameInfo class we will switch to.
Our first if statement is checking to see if the first 10 characters from the left of MapName are a case-insensitive match (~=) to “HTFrontEnd”, and if so, it will return the class ‘UDKGame’ causing the GameInfo class we are loading into to be UDKGame. Because we are already in UDKGame, no game type will be switched.
	// strip the UEDPIE_ from the filename, if it exists (meaning this is a Play in Editor game)
	if (Left(MapName, 6) ~= "UEDPIE")
	{
		MapName = Right(MapName, Len(MapName) - 6);
	}
	else if ( Left(MapName, 5) ~= "UEDPC" )
	{
		MapName = Right(MapName, Len(MapName) - 5);
	}
	else if (Left(MapName, 6) ~= "UEDPS3")
	{
		MapName = Right(MapName, Len(MapName) - 6);
	}
	else if (Left(MapName, 6) ~= "UED360")
	{
		MapName = Right(MapName, Len(MapName) - 6);
	}
Just as Epic’s comment states, these if statements check to see if our MapName contains a prefix that is added on automatically by the UDK Editor when we use the “Play in Editor” feature. If an editor prefix exists, we reassign MapName to be the the right most characters of the original mapname, ignoring the left-hand editor prefix.
	// replace self with appropriate gametype if no game specified
	pos = InStr(MapName,"-");
	ThisMapPrefix = left(MapName,pos);
This code searches our MapName for a “-” and stores the position of the first “-” character it finds into our variable “pos”. We then assign ThisMapPrefix to the left side of our MapName ending at the “-” character, causing the prefix of our map to only be stored. Example: If the MapName is HT-Hole1, it will first find the “-” character and then store 2 in pos as the “-” is character 2. (The first character of a string is always character zero). We then grab the left of the MapName from the beginning of the string up to the 2nd character (being the “-”), causing ThisMapPrefix to have “HT” assigned to it.
	// change game type
	for ( i=0; i<Default.DefaultMapPrefixes.Length; i++ )
	{
		if ( Default.DefaultMapPrefixes[i].Prefix ~= ThisMapPrefix )
		{
			NewGameType = class<GameInfo>(DynamicLoadObject(Default.DefaultMapPrefixes[i].GameType,class'Class'));
			if ( NewGameType != None )
			{
				return NewGameType;
			}
		}
	}
This is a for loop. A for loop essentially loops a code block while changing a variable every loop until a condition is no longer true. This is where our i variable comes into play (i being short for iterator). We start the loop by making i = 0, and we give the loop a condition of  i<Default.DefaultMapPrefixes.Length. Default.DefaultMapPrefixes refers to our default value of DefaultMapPrefixes which we assign to in the DefaultProperties code block later on in this class. It contains all the map prefixes for our game. Default.DefaultMapPrefixes.Length is the length of the array, or how many prefixes are in DefaultMapPrefixes. Every time this for loop loops, it will continue to loop as long as our iterator is less than the number of prefixes in our array. The “i++” in our for loop tells the loop to increment i by 1 every time it loops.
Our if statement is checking to see if the “ith” object of DefaultMapPrefixes is a case-insensitive (~=) match to our map prefix of our map. Arrays are kind of like strings in that the first object in an array has an ‘index’ of 0, just like the first character of a string is character 0. To access an object in an array, you suffix the array with square brackets [ ] with the index of the object inside the brackets. In this case it is i, our loop iterator. Every time we loop this code block, i is increased by one, thus moving to the next object in the array. If our array has 1 object in it, that first object has an index of 0, so our loop will loop once. After it loops once, i will be 1 which is not less than the number of objects in our array, which is 1; thus the loop will stop. If we had two objects in our array, the loop will run the code block twice with i being 0 and 1, stopping at 2; which works because the second object of an array has an index of 1 because our first object has an index of 0.
If it is a match, the next line of code is a bit tricky. What we are doing here is loading an object by its asset name which is stored as a string “GameType”. Our DefaultMapPrefixes is an array of the GameTypePrefix struct, so every object in the array has two strings, Prefix and GameType. We can access that string by referencing DefaultMapPrefixes[i].GameType where i is the index of the object we are comparing to in our loop. This string is the fully qualified name of a GameInfo class, such as UDKGame.UDKGame or later UDKGame.TheHuntGame. UTGame.UTDeathmatch would also work here. We load it in as a “class” instead of an instance because we are looking for the actual class of the GameInfo we want to switch to, not an instance of it. Because DynamicLoadObject returns a generic Object, we have to do whats called type-casting in order to turn it into a GameInfo class. Type-casting allows us to store an object in a variable thats designed to hold another object if the two objects are compatible. We can store a UDKGame.UDKGame in a GameInfo class because UDKGame derives from GameInfo. We can not however type-cast an Actor into GameInfo because Actor is not a sub-class of GameInfo, but instead is a parent of it. Finally, this newly loaded and type-casted object is stored in NewGameType. Even though if we load a UDKGame.UDKGame class and type cast it as a GameInfo class, it will still remain a UDKGame class with all its unique properties, but it will just be stored as a GameInfo class.
The second if statement checks to see if NewGameType does not equal None, which means that we successfully converted our newly loaded object into a GameInfo class. If for some reason we could not load the object or type-casting failed, NewGameType would not be assigned to anything (None) and therefore would not be a valid thing to return, as we can’t change the game mode to “None”. If NewGameType was assigned a value, we then return it, which causes the engine to set our new game type to whatever game type matched our prefix that we assigned in DefaultMapPrefixes.
	return class'UDKGame';
}
This last bit of code will return “UDKGame” if our loop fails to return a new game type, causing us not to switch game modes because we are already in UDKGame. The last bracket closes the SetGameType event.
defaultproperties
{
	DefaultPawnClass=class'UDKGame.HTPawn'
	PlayerControllerClass=class'UDKGame.HTPlayerController'
	DefaultMapPrefixes(0)=(Prefix="HT",GameType="UDKGame.TheHuntGame")
}
This is our defaultproperties box, which is pretty much the same as before. We assign our HT prefix with the GameType UDKGame.TheHuntGame to the first object of DefaultMapPrefixes, so that if our map has a prefix of HT it will load UDKGame.TheHuntGame instead.

{var string Prefix;var string GameType;};

HTPawn now extends UDKPawn

HTPawn now has a defaultproperties block identical to UTPawn, with the UTPawn specific properties removed. It is really long so here is a link to the script instead.

HTPlayerController now extends UDKPlayerController

/*******************************************************************************
HTPlayerController
Creation date: 14/01/2010 14:31
Copyright (c) 2010, Michael Allar
*******************************************************************************/
class HTPlayerController extends UDKPlayerController
     config(UDKGame);
No added functionality here, just inherits from UDKPlayerController instead.

TheHuntGame is a second GameInfo class that extends UDKGame

So that we can use UDKGame as a generic GameInfo class for things like front-ends while having the majority of our game code in a subclass of it.

/*******************************************************************************
	TheHuntGame

	Creation date: 19/01/2010 22:24
	Copyright (c) 2010, Michael Allar

*******************************************************************************/

class TheHuntGame extends UDKGame;

var array< class<Inventory> > DefaultInventory;

event PlayerController Login(string Portal, string Options, const UniqueNetID UniqueID, out string ErrorMessage)
{
	local PlayerController PC;
	PC = super.Login(Portal, Options, UniqueID, ErrorMessage);
	ChangeName(PC, "New Player", true);
    return PC;
}

function AddDefaultInventory( pawn PlayerPawn )
{
	local int i;

	for (i=0; i<DefaultInventory.Length; i++)
	{
		// Ensure we don't give duplicate items
		if (PlayerPawn.FindInventoryType( DefaultInventory[i] ) == None)
		{
			// Only activate the first weapon
			PlayerPawn.CreateInventory(DefaultInventory[i], (i > 0));
		}
	}

	PlayerPawn.AddDefaultInventory();
}

defaultproperties
{
	DefaultPawnClass=class'UDKGame.HTPawn'
	PlayerControllerClass=class'UDKGame.HTPlayerController'

	ConsolePlayerControllerClass=class'UTGame.UTConsolePlayerController'

	PlayerReplicationInfoClass=class'UTGame.UTPlayerReplicationInfo'
	GameReplicationInfoClass=class'UTGame.UTGameReplicationInfo'

	//DefaultInventory(0)=class'UDKGame.HTWP_LittleBang'

	bRestartLevel=False
	bDelayedStart=False
	bUseSeamlessTravel=true

}

Thats all the changes made.

Now you are ready to continue to set up your game!

Posted March 8, 2010 by Allar in Unreal

Tagged with , , , , , , , ,

31 responses to Beginning Your Game Part 3

Subscribe to comments with RSS.

  1. I so wish you had not done that, I was understanding what was going on up to the start of this one.

    • I plan on re-doing this tutorial, many have given me similar input. However if you blindly accept the code the rest of the tutorials go way indepth and make the changes here easier to understand. I might do that tonight.

  2. Without comments in UDKGame.uc

    Line 5: Warning, 'GameTypePrefix' obscures 'GameTypePrefix' defined in base class 'GameInfo'.

    Line 10: Warning, Variable declaration: 'DefaultMapPrefixes' conflicts with previously defined field in 'GameInfo'

    Line 50: Error, Unknown member 'GameTypes' in struct 'GameTypePrefix'

    I'm still looking for typos, but can someone look for possible mistakes in our developers code ;) ?

    Btw. I'm using the March build as well

    • @Line 50: GameTypes possible typo to GameType

    • The .zip file instructed to download to fix the issues in this part of the tutorial (at the top labeled IMPORTANT) rip all the lines above because this code was then moved up to the base GameInfo class in the March build, and this tutorial was made with the Feb. build in mind.

      Been too busy to recreate these beginning few tutorials, but if you can get past em, the rest of these tutorials are pretty solid.

      • Oh, I'm very sorry. I though it was the same as the tutorials offers.

        Dudes, if you read that you know what to do ;)

  3. Let me make sure I got this;
    You created a higher class for the game,
    moved the relevant code into the new class,
    removed original code from the UT class,
    And in doing this- we transfer control to the new high level class, and don't have to worry about modifying the UT classes.
    Does that pretty much cover the change?

  4. thnks for the tutorials so far (the first 2 where realy good). But after this one if i jump into the game it doesnt work properly is this normal?

  5. As others said, it is a little hard to follow trhought this tutorial. I hope you to rewrite it ^_^
    So , my doubt, am i the only getting this error Error, Unknown Property 'DefaultMapPrefixes' in 'Function UDKGame.UDKGame:SetGameType'

    when using the zipped scripts?
    Can't figure out what happens :?

  6. Oh thanks i thought it would work with april's also.

  7. I'm using the April build, all scripts compile fine and when I load the map with given prefix I can walk around like a regular pawn. Thing is in the defaultproperties block we set the crouch. double jump and pickup inventory to true, yet I can't crouch, can't perform the double jump nor pick up the rocket launcher. Is this a normal behaviour?

    • Indeed it is normal, the base Pawn class isn't set up to crouch or use UT inventory items. To add crouching, check out PlayerController and UTPlayerController's CheckJumpAndDuck() functions along with UTPlayerInput to implement your own ducking.

      • Ok so I added this change to my APlayerController:

        function CheckJumpOrDuck()
        {
        Super.CheckJumpOrDuck();

        if(Pawn != None && (Pawn.Physics != PHYS_Falling && Pawn.bCanCrouch))
        {
        Pawn.ShouldCrouch(bDuck != 0);
        }
        }

        defaultproperties
        {
        InputClass=class'Arilienta.APlayerInput'
        }

        And made a class APlayerInput:

        class APlayerInput extends UDKPlayerInput within APlayerController;

        var float LastDuckTime;
        var bool bHoldDuck;

        simulated exec function Duck()
        {
        if(APawn(Pawn) != None)
        {
        if(bHoldDuck)
        {
        bHoldDuck = false;
        bDuck = 0;
        return;
        }

        bDuck = 1;

        if(WorldInfo.TimeSeconds – LastDuckTime < DoubleClickTime)
        {
        bHoldDuck = true;
        }

        LastDuckTime = WorldInfo.TimeSeconds;
        }
        }

        simulated exec function UnDuck()
        {
        if(!bHoldDuck)
        {
        bDuck = 0;
        }
        }

        So crouching works fine, but instead of interpolating the camera height it just "pops out". I looked through UTPawn, UTPlayerController and UTPlayerInput but i didn't found anything related to this. Do you have any idea how to make the interpolation just like the UTPawn has?

        • Hmmm, this is something I have not looked into. You might have to do this with some custom logic in your Pawn's CalcCamera function.

  8. I am also using the April build, but I get the colliding noclip/spectator pawn on both HTGame and TheHuntGame (Files from ZIP).

    I have re-named the files, classes and all references of HT to the names I use, but I still spectate, unless I make HTGame extend from UTGame, but that makes this pointless

    • Update:

      Fixed the above problem. Simply had to add:

      +DefaultMapPrefixes=(Prefix="HT",bUsesCommonPackage=FALSE,GameType="UDKGame.TheHuntGame")

      to DefaultGame.ini and comment out the corresponding line in the code you gave us in the UDKGame class. UDK from April doesn't seem to like defining default game types in hard code :/

      Also, I had to copy a test map and stick a HT- infront of it, but that was just me.

  9. A small note:

    For those of you who are getting incorrectly lit weapon models (ie, They are completely black no-matter how well lit the world is), simply replace:

    Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment
    bSynthesizeSHLight=TRUE

    End Object

    in HTPawn with:

    Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment
    bSynthesizeSHLight=TRUE
    bIsCharacterLightEnvironment=TRUE
    End Object
    Components.Add(MyLightEnvironment)
    LightEnvironment=MyLightEnvironment

    Done! :D

  10. This Section total confused me so i skipped it :)

  11. I'm working with the october version and I now get an empty scene with no gravity, weapons, menu or anything, only collision works in the empty cube-map. Is that right so far?

    But primary I wanted to ask an other question:
    When map-prefixes in the newer versions of UDK are initiated in the DefaultGame.ini file and not in the defaultproperties, can we still access them via "default.*" like you do in your UDKGame-class?

    ([...]Default.DefaultMapPrefixes[i].Prefix[...] etc)

  12. Im using the newest UDK… November's…:)… Now… im getting a few warnigs…. This ones…

    [code]
    C:UDKUDK-2010-11DevelopmentSrcUnrealRacingClassesURGameInfo.uc(39) : Warning, Unknown property in defaults: ConsolePlayerControllerClass=class'UTGame.UTConsolePlayerController' (looked in URGameInfo)
    C:UDKUDK-2010-11DevelopmentSrcUnrealRacingClassesURPawn.uc(48) : Warning, ObjectProperty Engine.SkeletalMeshComponent:SkeletalMesh: unresolved reference to 'SkeletalMesh'HTLash.Mesh.SK_CH_Lash''
    C:UDKUDK-2010-11DevelopmentSrcUnrealRacingClassesURPawn.uc(48) : Warning, Invalid property value in defaults: SkeletalMesh=SkeletalMesh'HTLash.Mesh.SK_CH_Lash'
    C:UDKUDK-2010-11DevelopmentSrcUnrealRacingClassesURPawn.uc(49) : Warning, ObjectProperty Engine.SkeletalMeshComponent:AnimTreeTemplate: unresolved reference to 'AnimTree'HTLash.Anims.AT_Lash''
    C:UDKUDK-2010-11DevelopmentSrcUnrealRacingClassesURPawn.uc(49) : Warning, Invalid property value in defaults: AnimTreeTemplate=AnimTree'HTLash.Anims.AT_Lash'
    C:UDKUDK-2010-11DevelopmentSrcUnrealRacingClassesURPawn.uc(160) : Warning, ClassProperty Engine.Pawn:InventoryManagerClass: unresolved reference to 'class'HTInventoryManager''
    C:UDKUDK-2010-11DevelopmentSrcUnrealRacingClassesURPawn.uc(160) : Warning, Invalid property value in defaults: InventoryManagerClass=class'HTInventoryManager'
    [/code]

    im guessing its the version but i was wondering… and also… i agree with some post i saw up… (or down)… i was getting it all fine with the first 2 tutorials… now i didnt really understood what happened…. Anyways… Thanks for the tutorials… they have been more helpfulkl than any other…

  13. the first two tutorials are useless, too many things are different

  14. Hi there,
    Thanks for the tutorials, this is exactly what im after as well with my project (staying away from the UT code as much as possible).
    That being said, the only issue im having at the moment is the fact that my pawn just wont render…
    He is there in the world, i can walk around and such, but he is invisible. I noticed you used your own skeletal meshes, so i changed it back to the original:

    SkeletalMesh=SkeletalMesh'CH_IronGuard_Male.Mesh.SK_CH_IronGuard_MaleA'
    AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'

    But it is still invisible. Any tips? Thanks

    • SkeletalMesh=SkeletalMesh'CH_IronGuard_Male.Mesh.SK_CH_IronGuard_MaleA'
      AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.Anims.AT_CH_Human' – You forgot about 'anims'.

  15. Hello!
    It's hard to understand part 3 of beginning your game tutorial, but. You changed UT to UDKk classes in our scripts, yes? The old UT script extended is replaced for UDK?

  16. Hm, i only have 3 uc files by following the parts before this one, but the zip file comes with 4…

  17. Greetings and Salutations!
    First of all, thank you for the tutorials;)
    Now, to the point:
    I'm using the july version 2011. I placed my pawn and the animset in the content folder of UDK. I made the 1,2 and 3 part of Beginning your game and replaced your pawn and animset with mine in the Pawn script, but when I compile the scripts, the following warnings appeared:

    C:Program FilesUDKUDK-07-2011DevelopmentSrcMyGameClassesGGPawn.uc(48) : Warning, ObjectProperty Engine.SkeletalMeshComponent:AnimTreeTemplate: unresolved reference to 'AnimTree'CH_MyCharacter.Mesh.AnimSet_01''

    C:Program FilesUDKUDK-07-2011DevelopmentSrcMyGameClassesGGPawn.uc(48) : Warning, Invalid property value in defaults: AnimTreeTemplate=AnimTree'CH_MyCharacter.Mesh.AnimSet_01'

    And I can not see my character in the editor. Can u help me?

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>