Automating the Import Process In UE4 with Blueprint Editor Scripts

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so here i'm going to show you how to make a script where say that you have an object and some modeling program and it has some materials on it what happens if in unreal we were to just import that object into a folder where its textures live and it automatically created and attached to the materials for you perfect it's all done here through this editor script a small menu and here's how you make it inside we're going to be using a check box to determine that we want to actually make it just in case you don't want to we're going to go over a details view panel where you can put in the varying kinds of materials that you want to attach and i'll show you how to do each step of it right over here we're going to first get the import subsystem and that's where we're going to grab our objects from we're going to store those that way then we can reference them and then we're going to do a check just to make sure that we even want to automatically create the materials for each mesh that comes in we're going to store the materials then for each material we're going to determine a new name based on our naming convention create a replacement material instance for that material then we're going to find the textures that need to go onto that instance make sure they have the correct settings and then attach them finally we'll attach the material instance to the static mesh and then lastly we'll clean up the directory afterwards all right so the first thing you need to do is make sure that you have the editor scripting utilities plugin enabled okay and the other disclaimer is that in maya well whatever modeling program you're using you're at least obeying some kind of naming convention so here i have just a cube with two materials on it and i have one of them called m underscore matt underscore zero one and the other one is just matt underscore zero two so either of these for me work because i do a check for both but make sure that you have some kind of consistency that you can extrapolate from all right so the first thing you're going to do is go to editor utilities and create an editor utility widget now open that up i'm gonna add a vertical box real quick and we're just gonna add a couple of things a horizontal box inside this we're gonna add a check box and some text cool and on the text we'll just put auto material then we're going to add a details view and this is where all of our inputs will go the kinds of materials that we want to have on it i'm also going to change it from fill screen to custom and we'll make it oh so big okay uh so the details view is gonna sit blank for a little while and we'll come back to that in the graph here i need to do a couple of things i'm going to get rid of these guys we are going to drag our details view in here off of that say set object and tie that to the event pre-construct and then get a reference to self and plug that in here for new object all right so this will initiate the details view when it's set up but we're not going to add variables to it or inputs for a little while so the first thing that we need to do going back to that graph um or that comment we need to get the import subsystem cool so this guy will fire uh grabbing an object each time an uh object comes into the engine so we're gonna bind this to event construct and unbind it from event destruct so whenever our window is open it will pick up the assets that come in i'm going to create a custom event call it on asset post import bp event zero that was it from here so we went to bind event to on asset post import and we're going to put our custom event there and then off of the import subsystem onbind event from on asset import on asset post import oops sometimes this happens and i just have to drag off of the bind oh that's because i'm using the wrong one nope it's the right one what am i saying all right so here we've gotten the import subsystem and anytime that this guy fires it will get whatever the imported object is we're going to promote that to a variable and label it as imported object great and then another thing that we're going to do is grab our check box and unchecked gonna promote the is checked to a pool saying auto material and this basically says whenever this will set it up here with a branch that whenever this guy is true we know that this is the function that we want to perform all right so first i'm going to set it all up for a static mesh and afterwards i'll show you when we're completely done the differences that you have to do for a skeletal mesh i am going to put all of this in a function just to make it convenient so i will call this sm create and attach material and afterwards to we'll talk about some design decisions that you can use to tailor it to your specific needs all right so we'll get imported object and i'm going to make some local variables here um automat asset will be one and that's just the object that we have inside of this function cool and we will set that to the imported object we're also going to make an array here called materials for auto mat asset these will be the ones that it imported with and this is a material interface and we're going to make it an array so we're going to drag that in and because this is the start every time that we perform this we actually want to clear the arrays so that way then we don't save the values from the previous object that came in now under this guy i'm going to cast to static mesh and then here we're going to do a sequence and our first bit here is basically done we've gotten we've just set up some values casted to the static mesh so now we can talk to the actor that got imported and we've set up the import system in the parent graph here cool alright so the first thing that we're going to do is actually grab all of the materials that came in with it we're going to do a for loop with break and then off of our static mesh we're going to get number materials fun fact the tool tip for this is wrong all right so then we're gonna for loop with break through the first index being zero and the last index being the number of materials that we have on the static mesh this is technically one more than we need but we're gonna do a check to make sure that we don't go over any ways all right so then we're going to get material also off of our static mesh cast and we're going to plug the index of our for loop with break into that and we're also going to perform an is valid check and off of the loop body we're going to do a branch and then here the array that we made can i get that and add to it off of the true from our branch and we're going to use the material that we got off of the static mesh and then if it's false oops not return and plug that into the break all right so what we're doing here is we've kept cast to the static mesh we're looping through each of the materials so this will return say if we have two materials zero one two well it'll return two as a number and then we're gonna loop through the indexes starting at zero will go to zero then one then two uh the material index number starts at zero so if we have two materials we'll have index zero and index 1 once this hits 2 we're going to do a valid check that'll return invalid because we're past the number of materials that we have so false will come through and we'll break and come out otherwise we will store it here into this array and now we have an array of all the materials that are on the static mesh to start working with so i'm going to comment this store the materials that imported cool all right so then the next thing that we're going to do is say for each loop so we can duplicate this guy over and for each of the materials we have a few options that we want to do first we're going to promote the index to a variable just so we can reference it later you technically don't have to do that but it adds to graph readability and i wanted to do that as a local variable all right then we're going to do a sequence off of this too for each material we have a number of things that we want to do and before i continue i'm just going to bring up a little document that talks about varying directory types there's a difference between display name path name package path and package name uh display name will just be the asset name uh path name will be like slash game slash directory subdirectory subdirectory finish with asset name dot asset name and that's important because if we want to rename the materials we kind of have to do stuff this way and then the only one that's relevant past that is package name which is the same as path name except that it's just the display name at the end okay so off of the material or the array element from the for each loop with our stored materials we're going to get display name and then we're going to do a couple things here we're going to split so this next section we're going to extrapolate the name from the material that it imported with and then we're also going to do a start with all right so if you remember here in maya my materials are m underscore the material name and then just the material name so matador 1 and matador 2 are the materials this one had a prefix to it this is mainly so that way then other people that are working in the project i'll tell them as long as you can obey one of these two if you don't remember the prefix that's fine just make sure that you have the material named at the material that it's going to be in unreal all right so off of the first part of our sequence we're going to do a branch and then in our starts with we're going to put m underscore so if it starts with the prefix that we know that we're supposed to have then we're going to chop it off we want to take the display name well we'll make another local variable call this print material name make it a string and make it not an array and then i will set it here and we're going to do two of these okay so if it begins with m underscore i want to remove everything from the start so here see i want to use right it returns everything to the right of the in string so the n string is the underscore so we're going to start from the beginning we'll see m we'll see underscore and then we know that the m and the underscore need to come off so we'll set that otherwise we'll just get the display name and we'll plug that in great okay so we're gonna comment this section get to the material name okay so next we're gonna do get asset tools um this returns some editor handling that works for the assets in the content browser and next we're going to set up creating the replacement material so off of that you can do create asset interface call and then we have our current material name i'm going to append to it now that we have the core name of the material i can now put m under m i underscore because i want material instances of my master material to come to be attached to the object you can skip this if you want or set m underscore or whatever kind of prefix you want for your materials that you're generating whatever fits your naming convention if you want the underscore inst at the end you can do that too but that'll go into asset name so now we have package path which as i brought up earlier oh i lied this is the one that mattered so it's slash game slash whatever the directory is for the directory that you want to put it in uh so there's a really easy way that we can get this uh we're gonna create a macro real quick and i'll call it get directory and then for one of the the only input we need is an object all right and then here we will get path name and get display name now if i come back to this the display name for an asset would be the asset name while the path name will be the directory plus asset name dot asset name at the end so if we take the display name we get the length of it we multiply that by two so you get the asset name twice and add one to account for the dot and off of the path name and do left chop and this might seem a little counter-intuitive because i think that they're named backwards but it returns the leftmost characters of the string chopping off the given character from the end so here we have the length of what the asset name dot asset name would be and if we plug that in that will get us just the directory pile and save come back we will do get directory and we will plug in the auto material asset that we made earlier okay then for asset class you would choose whatever your material or material instance is i'm going to do a material instance and the subsequent nodes will specifically reference a value that you need to work with material instances in the editor i have that made here so i've selected it and then i can hit none oh asset class is material instance constant do not confuse this with material instant material instant does not work you need material instant consonant all right promote this to not promote to cast to material instance constant and i forgot to hook that up there make sure that this is all good promote to variable oops and again i want to promote it to a local variable call it current replacement map now here we will probably have to drag off the blue pen set material instance parent all right so then i also need in full variables not a local in the global variables for this blueprint i need the material that i want to be using static mesh material will be the new variable name and this will be also a material instance constant plug that into the new parent and then for its value you just choose whatever you have in your editor that you want to use so now if i plug this in oh whoops wrong this guy i made it wrong that's why i didn't need to do that material instance constant object reference now if i do it there we go now it'll show up there all right so this section here is done just to recap get asset tools create asset we're going to get the current material name that we had before put our naming convention in there this should be due to the previous section just the material name and then we're going to take our asset get the path name and the display name and from the path name we will left chop a number of characters that is equal to 2 the display names length times two plus one the type for this is material instance constant we'll cast to it store that and then set the parent as this value which we've predetermined as the material that we want to put in now let's say i'll comment this real quick all right cool well let's say that you want the user to be able to choose what kind of material that they want to put on so here in our details view now that we have anything to put into it uh i'm gonna come back to the graph actually and just copy this guy's name in a details view it'll look like what you would normally have in the details panel for unreal you have to add a property though so here is one property i'm gonna paste that value and compile and i think i'm gonna oh is it not ah there we go i need the vertical box to be the size of the whole thing all right so there now it'll have the input just like an unreal i'm also just going to bring my canvas out a bit and the vertical box make it a bit bigger all right so at this point if we hit run on our widget it at least looks like something that we would have in unreal and a checkbox here that sets that bool to correct or not okay so real quick i'm going to try this just as is so here i have some textures the base name is matte01 so i have t underscore as the prefix for the texture asset type and then the type of texture would be underscore base color or bc normal or n and we're gonna chop those off but or rather we're gonna pick those up in a minute uh right now if i bring this in i want to set this true first and then import the sky we at least make the material so the material construction up to this point is working we're just not plugging in textures or assigning them to the material or the static mesh so that's the next step [Music] all right so next on our sequence we're going to get asset registry uh this gets a list of all the assets that you have in your content browser it loads the list into memory and then you can access the metadata or attributes of objects off of that um this guy will also update dynamically if something changes not that particularly matters but off of him you can get a lot of extra nodes like get asset by object path here we can use this to get the textures so i have in my material that i want to hook up i can get to it this way i have three textures base color normal and our channel packed map and i'll leave this guy up because we'll reference well i'll open them later but we'll reference these names in a moment so first we want to get the textures that are associated with it and as i said my naming convention is t underscore the texture name which will correspond with the material name and then underscore the texture type so since we know that we have the base material name assuming that your naming convention has your texture follow your material name that they match we can get our current material name and then we can append and we'll put it in the center with an input on either side t underscore and underscore bc for our base color and then do another one for normal and i'm using orm for my channel packed map great now in get asset by object path it takes an object path and an object path is basically the same as a path name so what we can do to get that off of these guys so we know the names of the textures that we want so now we just have to figure out where they are if i take get directory our auto material asset plug that in there this should return just the directory we're importing to and assuming that we are importing to the directory where the textures live we can append add a couple of inputs here remember it is the directory slash asset name dot asset name i'll do that for each of these great and then for this first one plug that in there and drag all of this down a little bit to format a little better and then we're going to copy this guy twice because we have three textures and i'll plug this into each of these and we'll plug these in oops all right so now we have the return value for each of these and this should return the asset data for those textures so off of one of these we're going to type get asset and that'll get the actual texture that's there and we're going to do this a couple times cool then we're going to cast to texture because we need to access that it is a texture and again do that for each of them alright so now we have access to the textures going to comment this section as get textures the order i did these in i put my channel packed map last off of this guy we also want to get whether or not is set to srgb off of this same texture if it is set to srgb we're going to turn it off if it isn't and we don't really care whoops i want to reroute all right then we're going to get the current replacement material stored that out earlier i'm going to set material instance texture parameter value both of these will plug in and we're going to grab each of our textures that we casted to so first this should be the base color so oops i close that on here we just need to know this is base color map that's what i put it to so whatever you choose for this texture parameter name i need to go in here and i will do this two more times and be sure to plug in the current instance material variable to each of them and each of our oops textures that we casted to will then go into the value cool so i'm going to grab all these and slide them over and this we're going to comment as set textures to current replacement material instance all right and then finally on the rm texture or the channel pack texture which is last um we just went to save loaded asset we changed a value on it so we're just going to save it all right over here i forgot to change this to normal map make sure that these are typed correctly i'm just double checking my names normal map or a map this turned on and import cool okay so now we have our materials generated and they have the correct textures plugged into them now we just have to attach them to the mesh and get rid of the old ones so again i'm going to delete these i'm going to close that come back to our editor script next off of here we need one more in our sequence for each material i should comment this for each material so then down here and a cast to static mesh we're gonna get our auto material asset off of the as static mesh output we're going to set we're material get our current replacement material and here's where the array index that we stored out earlier should come in these should line up for the first index which is zero that should correspond to the index that is zero on the material index and do all of this and so on all the way up until we're done then off of our current replacement material we're going to save loaded asset we've created a material we should be saving it and finally the same for our static mesh all right so just to recap we got the materials and then for each material we've extracted the name created a material to replace it based on the name we went and found the textures and casted to them made sure the channel packed map had its correct settings we've put the textures into the corresponding texture parameters of our material and then we've saved any the texture our channel pack map if we did change it the only if dirty if you end up changing it it'll save you can untick this and it'll always save it so this last bit here i'm just going to comment replace material on mesh and save cool so compile and save i'm going to run this again bring it in import all right now our cube has the materials on it the only last thing to do here is to get rid of these two old materials and that's super easy on this sequence earlier just comment this store mesh for rhythm for each mesh on the last output of this sequence we can come down put a reroute node here and luckily we still have that array from earlier the materials for auto material asset which is the materials that imported if we get that we can just delete loaded assets and we're done perfect so now again if i run this make sure that is checked grab my asset and bring it in there we go again just to prove it's got the two materials on it all right so there we go we now have a material that we can choose from and you can choose other materials and put in here the only thing to remember is that the texture parameter values have to be the same name so the only difference is i'm going to show you this version that i've had that i was tinkering with if you you can do the same thing for a skeletal mesh there's just a couple of differences you need to create a skeletal material array you're going to clear it at the start so that way then the next skeletal mesh that comes in you're not using the previous skeletal meshes materials you're going to cast a skeletal mesh and then the store materials you have a for each loop and for each you uh you want to off the cast to skeletal mash you want to get its skeletal materials and for each material in the skeletal material array you're going to add those to your material for auto matte asset these come out with kind of a different object they don't come out like with the object reference itself they come out with a struct which is going to be the material and then the material slot name so i've also created an array and we just add to that and since you're doing these in the same iteration of the for loop they should line up with indexes the only other big thing is here i'll come back to this in just a second i don't set the parent here after creating the material i actually have a function so you can choose what kind of material it is um but again i'll come back to that in just a second so after we set the we get grab the textures plug them into the texture parameters that they go on the material instance um in order to get the materials onto the object you have to that you have to grab that skeletal material array that we cleared at the very beginning here we're going to add to it we're going to get the current material that we make and we're also going to take the array index to get the slot name and then this guy here should start populating for each material and then afterwards we'll take that array cast to the skeletal mesh and set its skeletal material array to this new one that we built and all of your material should attach okay so then here as i said that i'd bring this up later the create by keyword function um it's actually down here but normally so previously in the static mesh one you would have the set material instance parent uh characters tend to be a bit more complex they'll have a clothing material a skin material a hair material an eye material right so instead we just create a custom event that we call here and then on that we pick up keywords in the material name you don't actually have to do any of this this is pretty workflow based for or personal to your workflow i'm using keywords in the material like if it contains hair so m underscore character underscore hair if it contains hair then the replacement will be a hair material if it contains i the replacement will be or the parent will be an eye material and so on you can skip the branch at the end here if you wanted to make sure that no matter what they got onto a material or you could do all branches and then end with a print that to let you or your artist know hey it didn't have a keyword you should republish the asset anyways that does it i hope you guys find this helpful
Info
Channel: Zeatch
Views: 548
Rating: 5 out of 5
Keywords: unreal 4, impor, material, automate, automation, automated
Id: 7hTTqsAlutg
Channel Id: undefined
Length: 40min 33sec (2433 seconds)
Published: Tue Feb 23 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.