From 3D Asset to Working Worktable: Difference between revisions
| [unchecked revision] | [unchecked revision] |
Done. This guide is long and probably too repetitive, but it will produce results! |
|||
| Line 655: | Line 655: | ||
=== Checkpoint === | === Checkpoint === | ||
[[File:WikiDemo - Medieval Stall - Checkpoint -3.png|thumb|The Medieval Stall modded into Eco.]] | [[File:WikiDemo - Medieval Stall - Checkpoint -3.png|thumb|The Medieval Stall modded into Eco.]] | ||
Revision as of 02:29, 29 April 2026
Introduction
Below is a guide on how to take an 3D asset from the Unity Store and make a working workbench in Eco. This includes:
- Creating a recipe to craft the modded table
- Creating recipes so the player can use the modded table to craft something
- Using Blender to generate a modded icon (seen when holding it in inventory)
- Using Blender to adjust the origin point of the model
- How to setup all this in a Unity scene and package for Eco
Setup
- Already have setup ModKit + Unity
- Have a 3D model
- Just following along? Find the one used here at
https://assetstore.unity.com/packages/3d/props/low-poly-medieval-market-stalls-314286
- Just following along? Find the one used here at
- A C# IDE (notepad++, Visual Studio, etc.)
- Highly encouraged to have an Intellisense setup and linked to the Reference Assemblies. Optional, but its really worth the time to figure out because it will help quickly correct small typos and trivial mistakes.
- See: Getting Started with Eco Modding in Visual Studio 2022 (generally the same steps apply if using a new version of Visual Studio)
- Blender installed
- Homepage:
https://www.blender.org/
- Homepage:
Importing the Assets
- Open the Unity editor to the project.
- From the top toolbar open the Window drop down.
- Hover Package Management to open sub-menu.
- Select Package Manager.
- The Package Manager window will pop-up.
- Install the package containing the assets you want to use...
- If not using Unity Registry...
- Find the +▾ button in the top left and open the drop down.
- Install the package from one of those options.
- If using Unity Registry...
- Visit
https://assetstore.unity.comand sign in. - Search for the asset desired.
- Go to it's page (e.g.
https://assetstore.unity.com/packages/3d/props/low-poly-medieval-market-stalls-314286) and click the big blue button, Add to My Assets. - Now, in the Unity editor and back at the Package Manager window.
- Find My Assets on the left menu and navigate to it.
- Click the ⟳ button in the lower-right.
- The asset should be in the list now. Use the search to filter if needed.
- Click on the asset in the list. For those following along, Low Poly Medieval Market Stalls.
- In the right panel, find the Download ⤓ button. Click it.
- Once downloaded, a new button should show up, it'll say something like ⊕ Import 1.0 to project . Click it.
- The Import Unity Package window will pop-up.
- Select Import on it.
- Visit
- If not using Unity Registry...
- Verify you can find your assets from the explorer. If following along, the assets are at
Assets/PolyRonin/Medieval Market Stalls. - Load in a demo scene, if provided, and make sure everything looks okay.
- For those following along, double click on the Demo scene at
Assets/PolyRonin/Medieval Market Stalls/Demo.unity.
- For those following along, double click on the Demo scene at

If something seems off, check the different draw modes and see if changing those allow the scene to render as expected (see picture).
Creating The Worktable
This guide will create the worktable in this order:
- Create the item that represents the worktable
- Make a recipe to craft the worktable item
- Make the worktable item something that places a world object
- Give the worktable functionality by adding recipes to it
Creating the Item
Item Icon

- Open Blender.
- Delete everything in the Scene Collection. Find this section in the top-right of the application.
- From the top toolbar, open the File drop down.
- Hover Import to open the sub-menu.
- Select the type of 3D asset. For those using medieval assets, select FBX (.fbx).
- Find the asset on the computer...
Tip: Use Unity to find the.fbxasset.- For the medieval assets, that's in
Assets/PolyRonin/Medieval Market Stalls/Meshes/medieval-market-stalls-1.fbx. - Right click on it and select Show in explorer.
- Now copy the address of that folder from Explorer. It might look like
C:\Users\Wug\EcoMod--WikiDemo\WikiDemo\Assets\PolyRonin\Medieval Market Stalls\Meshes. - Paste that in the address bar of the Blender import pop-up.
- For the medieval assets, that's in
- Select the blue Import FBX button.
- Be in the Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- Change the Viewport Shading to Material Preview or Rendered. This is on the second toolbar down, far right of center, but before Scene Collection section.
- If you see purple models, Blender will need help finding textures for these meshes...
- From the top toolbar, open the File drop down.
- Hover External Data to open the sub-menu.
- Select Find Missing Files...
- Point this to the whole directory that the 3D assets came in. For the medieval pack,
C:\Users\Wug\EcoMod--WikiDemo\WikiDemo\Assets\PolyRonin. - The proper textures/materials should have now loaded in. If it hasn't, consult Google because without the textures the following steps won't produce a usable icon.
- Add a source of light...
- Still be in the Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- From the toolbar just under that one, find and open the Add drop down.
- Hover Light to open that sub-menu.
- Click Sun.
- Still be in the Layout workspace (top toolbar) and in the Object Mode...
- Add a camera...
- In the Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- From the second toolbar down, find and open the Add drop down.
- Select Camera.
- In the Layout workspace (top toolbar) and in the Object Mode...
- Setup the scene with the object placement and lighting direction desired.
Tip: To reset the editor to something selected press the period key on the numpad. Without a numpad, use View (second toolbar from the top) and select Frame Selected from it. Alternatively, just set the zoom to zoom to the mouse position: Edit (top toolbar), Preferences (from drop down), Navigation (on left menu), Zoom to Mouse Position (In the zoom section). This makes moving around a lot more natural feeling. - Setup the rendering camera...
- Go to Rendering tab on the top toolbar
- On the right there will be a side-panel open, it should be the Render tab. Confirm that.
- Change Render Engine to Cycles.
- Look down below in the same tab for the Film section.
- Expand it and find the Transparent checkbox and section. Click it so that it has a check mark. This will make the icon's background transparent.
- Now, go to the Output tab on the side panel. The tab is just below the current one.
- In the Format section set Resolution X to 64. And Y to 64 as well. This will make the icon generated a 64 by 64 pixel image.
- Go back to the Layout tab from the top toolbar.
- Center your view on the object (numpad period or View > Frame Selected). Adjust it so that the object is how it should be for the icon.
- Align the camera to the view...
- Make sure the editor is in Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- Find View from the second from the top toolbar and open the drop down.
- Hover Align View to open the sub-menu.
- Select Align Active Camera To View.
- If the view is slightly off, there is a lock icon on the right side of this panel. Use it to "lock" controls to the camera and tweak it's view.
- Make sure the editor is in Layout workspace (top toolbar) and in the Object Mode...
- Now return to the Rendering tab from the top toolbar.
- Press the F12 key to start the render. This should complete quickly since 64x64 pixels is a very small render.
- A window should popup, Blender Render. This is the icon!
- From the top tool bar of this Blender Render window, open the Image drop down.
- Select Save As... to save somewhere on the computer.
- Return to step 13 and repeat to do larger images if desired. Create a 128 by 128 pixel image too. It will make things smoother later.
- Save the Blender scene. Not only will it be used later, this will make making a new icon with a small tweak that much easier.
- File drop down from top toolbar.
- Save As... to save the Blender scene to the computer.
- Save it to
Assets/WikiDemo/MedievalStall - Icon Scene.blend.
Adding to Unity Scene
The developers explain how to create an item in one of ModKit's read me files (See: Assets/EcoModKit/Docs/README.md), but this guide will explain it below.
Additionally, TheKye on YouTube covers this in their Creating Your First Item and Creating Your First Item Pt 2 videos.
Use those additional resource to help troubleshoot issues with item's icons.
- Open Unity.
- In the left panel, the Hierarchy tab should be selected.
- Select the top-most object there. It should be a scene. If the editor last loaded the Demo scene from the medieval assets, it'll be named Demo.
- Right click on this scene and select Add New Scene from the menu.
- Right click again on the old scene (Demo) and select Remove Scene.
- Let it save if the changes to the old scene are important. Discard if it was open just for exploration's sake.
- Right click the new, Untitled scene. Click Save Scene As...
- Save it to
Assets/WikiDemo.unity. - Delete anything in the scene.
- Right click the scene, hover GameObject, and select Create Empty from the sub-menu.
- Name this new object Objects.
- Select the newly created Objects object from the Hierarchy menu.
- On the far right side of the screen, in the Inspector menu, click the Add Component button.
- Type in ModkitPrefabContainer. Click on the component from the search to add it. The component now should be listed in the Inspector.
- In the Hierarchy panel right click the scene, hover GameObject, and select Create Empty.
- Name this new object Items.
- Right click the scene, hover GameObject, and select Create Empty.
- Name this new object Emoji.
- Select the newly created Emoji object, find the Inspector menu (far-right), and click the Add Component button.
- Type in ChatEmoteSetOld. Click on the component from the search to add it. That component should now be listed in the Inspector.
- Right click the scene, hover GameObject, and select Create Empty.
- Name this new object BlockSets.
- Select the newly created BlockSets object, find the Inspector menu (far-right), and click Add Component.
- Search for BlockSetContainer. Click on the component from the search to add it. The Inspector should now show that component as added.
- Go to
Assets/EcoModKit/Prefabsin the Unity project window. - Find the prefab ItemTemplate.
- Drag it onto the Items object in the Hierarchy panel. It should add it as a child of the Items object.
- Right click on the new ItemTemplate object, hover Prefab, and select Unpack Completely.
- Right click on the ItemTemplate object and select Rename. Name this what you want the item to be called. Example: MedievalStallItem.
- Set this item's background...
- Here's the default backgrounds (blue = item, brown = block, green = food):

- Download or prepare the background and add it to the
Assetsfolder in Unity.- To follow along lockstep, put the background in a new
Assets/WikiDemofolder. - Right click on
Assetsfolder, hover Create, select Folder. - Name the folder WikiDemo.
- To follow along lockstep, put the background in a new
- Configure Unity to use these as sprites...
- Select the background(s) added (Ctrl+Click each one).
- In the Inspector, find TextureType and change that to Sprite (2D and UI).
- Again in the Inspector, find SpriteMode and change that to Single.
- Then scroll and go to the bottom of the Inspector and find the Apply button.
- This will apply those changes to that file and all other ones highlighted.
- Select the item being created (MedievalStallItem).
- In the Inspector panel (far-right), scroll and find the Item Template (Script) section.
- In here find the Background input. It'll say Background (Image) in it. If clicked that text to reveal and highlight the related object in the Hierarchy panel.
- Select the revealed, and highlighted object Background.
- In the Inspector panel, scroll and find the Image component section.
- Inside that component's section, find Source Image. It'll say Missing (Sprite). Click the ⦿ button to the right.
- The Select Sprite popup will show. Make sure the Assets tab is selected, and find the backgrounds desired.
- Here's the default backgrounds (blue = item, brown = block, green = food):
- Create the foreground image...
- This is easily accomplished in MS Paint.
- Get to the background image file in a file explorer.
- Right click on it, hover Open with..., and select Paint.
- The solid background should be displayed.
- Open the File menu from the top toolbar.
- Hover Import to Canvas and select From a File.
- Find the icon in the file browser and import it. Match the size of the background image to have it nicely center itself.
- Now File from the top toolbar.
- Hover Save As... and select PNG.
- Save this to the
Assets/WikiDemofolder in Unity. - Configure Unity to use these as sprites...
- Select the foreground image.
- In the Inspector, find TextureType and change that to Sprite (2D and UI).
- Again in the Inspector, find SpriteMode and change that to Single.
- Then scroll and go to the bottom of the Inspector and find the Apply button.
- This will apply those changes to that file and all other ones highlighted.
- Set this item's foreground...
- Copy the item's icon into the
Assetsfolder. - Configure Unity to use it as a sprite (see the previous step's Set this item's background... instructions)
- Select the item being created (MedievalStallItem).
- In the Inspector panel (far-right), scroll and find the Item Template (Script) section.
- In here find the Foreground input. It'll say Foreground (Image) in it. If clicked that text to reveal and highlight the related object in the Hierarchy panel.
- Select the revealed, and highlighted object Foreground.
- Use the Inspector, find the Image component, within that component find the Source Image input. It will say Missing (Sprite).
- Click the ⦿ button to the right of that input.
- From the Select Sprite popup, ensure the Assets tab is being searched, and find the icon just created.
- Copy the item's icon into the
Export From Unity
- Open the File menu from the top toolbar.
- Select Save. Save it to the
Assets/WikiDemofolder.
Note: Do not skip. The scene must be saved for the ModKit build to work properly. - Open the Eco Tools menu from the top toolbar.
- Hover Mod Kit to open the sub-menu.
- Select Build Current Bundle.
- Have it output the bundle to
/Eco Server/Mods/UserCode/WikiDemo.unity3d - Wait for this to build. This may take a few minutes.
Coding the Item
For this guide, all code will be placed in a single .cs file and will not be compiled into a .dll.
- Create a
.csfile:/Eco Server/Mods/UserCode/WikiDemo.cs - Put the following into the newly created file:
using Eco.Core.Items;
using Eco.Gameplay.Items;
using Eco.Shared.Localization;
using Eco.Shared.Serialization;
namespace WikiDemo
{
#region Item
[Serialized] // Tells the save/load system this object needs to be serialized.
[LocDisplayName("Market Stall")] // Defines the localized name of the item.
[Weight(100)] // Defines how heavy this is.
[Ecopedia("Work Stations", "Craft Tables", createAsSubPage: true)]
[LocDescription("A medieval market stall.")] //The tooltip description for the item.
public partial class MedievalStallItem: Item { }
#endregion
}
Line 8: A region tag. Lets the editor know it can collapse all of that code as a section. The following examples in this guide will just show #region Item in their code examples.
Line 13: The implementation of Item means that Eco will find this and look for Unity assets that matching this class' name, MedivalStallItem. While this doesn't do anything fancy, it completes the first step towards a new workbench.
Checkpoint #1

Make sure everything is running smoothly by doing the following:
- Double-check that the
WikiDemo.unity3dand theWikiDemo.csfiles are in/Eco Server/Mods/UserCodefolder. - Start the server and connect to it.
- Test it out by typing
/give MedievalStallin chat.- It's also possible to do
/give Market Stallto get the item. How? Line 10: of the the above code declares that name as this item's "common name". Neat.
- It's also possible to do
- The item should appear in the players inventory with a working icon.
Code the Item's Recipe
The following goes over how to add a new class and implement the RecipeFamily interface.
using Eco.Core.Items;
using Eco.Gameplay.Components;
using Eco.Gameplay.Items;
using Eco.Gameplay.Items.Recipes;
using Eco.Gameplay.Skills;
using Eco.Mods.TechTree;
using Eco.Shared.Localization;
using Eco.Shared.Serialization;
using System.Runtime.Versioning;
using System.Collections.Generic;
namespace WikiDemo
{
#region Item
#region Recipe
[RequiresSkill(typeof(CarpentrySkill), 3)]
[Ecopedia("Work Stations", "Craft Tables", subPageName: "Market Stall")]
public partial class MedievalStallRecipe : RecipeFamily
{
[SupportedOSPlatform("windows7.0")]
public MedievalStallRecipe()
{
var recipe = new Recipe();
recipe.Init(
name: "MedievalStallItem",
displayName: Localizer.DoStr("Market Stall"),
ingredients: new List<IngredientElement>
{
new IngredientElement("Wood", 40, typeof(Skill)),
new IngredientElement(typeof(CottonFabricItem), 30, typeof(Skill)),
new IngredientElement(typeof(HempMooringRopeItem), 5, true)
},
items: new List<CraftingElement>
{
new CraftingElement<MedievalStallItem>(1)
}
);
this.Recipes = new List<Recipe> { recipe };
this.LaborInCalories = CreateLaborInCaloriesValue(800, typeof(Skill));
this.CraftMinutes = CreateCraftTimeValue(typeof(MedievalStallRecipe), 10f, typeof(Skill));
// Perform pre/post initialization for user mods and initialize our recipe instance with the display name "Market Stall"
this.ModsPreInitialize();
this.Initialize(displayText: Localizer.DoStr("Market Stall"), recipeType: typeof(MedievalStallRecipe));
this.ModsPostInitialize();
// Register our RecipeFamily instance to a work table (in this case the Carpentry Table) so it can be crafted.
CraftingComponent.AddRecipe(tableType: typeof(CarpentryTableObject), recipeFamily: this); // NOTE: The table must be the object instance!
}
/// <summary>Hook for other mods to customize RecipeFamily before initialization.</summary>
partial void ModsPreInitialize();
/// <summary>Hook for other mods to customize RecipeFamily after initialization, but before registration. You can change skill requirements here.</summary>
partial void ModsPostInitialize();
}
#endregion
}
Line 10: Eco will need this explicitly added to the file. Visual Studio will not add this line automatically. It's used for the List<T> objects found in this code.
Line 14: "Collapsed" Item section. See the earlier sections in this guide for the code that belongs there.
Line 17: Sets the required skill and skill level to craft this recipe.
Line 21: [SupportedOSPlatform("windows7.0")] is here to silence some annoying warnings in Visual Studio. It's optional.
Line 30-32: Declares the input ingredients used for crafting. typeof(Skill) gets mapped to the CarpentrySkill as defined by line 31. In this example the HempMooringRope is a static input. A static input will not be modified by skills, upgrade modules, or game settings.
Note: It seems that at the time of writing (4/21/2026, Eco v13.0.2) the only way to get an ingredient to be a dynamic value that is reduced by the table's upgrade is to pass typeof(Skill) to it; Passing either true or false makes the this input static.
Line 34: The items list declares what items are output by this recipe.
Line 36: This line declares that one medieval stall is output from this recipe. Functionally this links this recipe to the MedievalStallItem (aka "Market Stall") item created in the last step.
Line 40: Amount of calories needed to craft this item. For a static value (not modified by upgrades or skill levels) change this line to: this.LaborInCalories = CreateLaborInCaloriesValue(800);. As it's written in the example, this item's calorie cost will be dynamic (modified by upgrades and skill levels). The skill level that will modify it is declared on line 16.
Line 41: Minutes needed to craft. Both static and dynamic values for crafting time can be modified by the world difficulty settings. For a static value change this line to: this.CraftMinutes = CreateCraftTimeValue(10f);. As it's written in the example, this item's craft time will be dynamic.
Line 49: This line assigns the recipe to a workbench. Do not assign to itself because then the first table could never be made. It's recommend to use a preexisting vanilla table.
Checkpoint #2
Check the functionality at this point -- it should be possible to see the recipe in the crafting table.
- Have the
.unity3dand the.csfile in the/Eco Server/Mods/UserCodefolder. - Start the server and log in.
- Type
/give Carpentry Table. - Place the Carpentry Table down and interact to see the what can be crafted.
- Find the newly added recipe under the name Market Stall.
- Type
/give Basic Upgrade 4. - Put the basic upgrade into the table.
- Go back to the recipe for the Market Stall and make sure the Wood and the Cotton fabric inputs now require less, but the Hemp Mooring Rope still is the same.
Note: In case the recipe hasn't changed close that table's window and interact with it again. It should for the recipes to refresh now that the upgrade is in it.
Create the World Object
Preparing the 3D Asset
- Open Blender.
- Load the 3D object created earlier for icon rendering --
Assets/WikiDemo/MedievalStall - Icon Scene.blend. - Cleanup the scene...
- Delete any light source. Use the Scene Collection panel on the top-right side of the screen. These will have a 💡 icon and by default are named something like "sun", "point", "spot" or "area".
Note: If your model is a light source or has one in it, you can leave that light source. The point here is to remove the ambient lights used for icon rendering. - Delete any camera(s). Again, use the Scene Collection panel. These have a 🎥 icon and by default are named something like "camera".
- Delete any light source. Use the Scene Collection panel on the top-right side of the screen. These will have a 💡 icon and by default are named something like "sun", "point", "spot" or "area".
- If there are multiple different 3D assets in the scene (like bags, crates, jars, ect.), join them all together...
- Select all of the meshes by holding Shift and clicking on each one in the Scene Collection panel (right side of window).
Tip: Quickly select a group of them by selecting one near the top. Then hold Shift, Ctrl, and click on one near the bottom. This will both the one at the top and the one at the bottom, but also every item in between. Neat! - Be in Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- Find and open the Object menu (second toolbar down from the top).
- Select Join.
- In the Scene Collection panel, double click on the name of the newly joined mesh.
- Select all of the meshes by holding Shift and clicking on each one in the Scene Collection panel (right side of window).
- Rename the joined mesh to
MedievalStallMesh. - Add and position a reference cube...
- Make sure the editor is in Layout view (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- Then, add a reference cube. Open the Add menu (second top toolbar down).
- Hover Mesh.
- Select Cube.
- Open the View menu (second toolbar down).
- Select Sidebar.
- A new panel will have expanded.
- Along the right side of that panel there's buttons (Item, Tool, View, Animation). Find and click the Item button.
- Find and expand the Transform section
- Set the Location...
- X to 1.
- Y to 1.
- Z to 1.
- The bottom corner of the cube should be touching the where green and red axis lines meet.
- Make sure the editor is in Layout view (top toolbar) and in the Object Mode...
- Move the reference cube's origin to
(0, 0, 0)...- Be in Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- Open the View menu (second toolbar down).
- Select Sidebar.
- A new panel will have expanded.
- Along the right side of that panel there's buttons (Item, Tool, View, Animation). Find and click the View button.
- Find and expand the 3D Cursor section.
- Set the 3D cursor's Location...
- X to 0.
- Y to 0.
- Z to 0.
- Now in the Scene Collection panel, click on the Cube mesh to highlight and select it.
- Open the Object menu from the second toolbar down from the top.
- Hover Set Origin.
- Select Origin to 3D Cursor.
- Be in Layout workspace (top toolbar) and in the Object Mode...
- Set the reference cube's dimensions...
- Be in Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- Open the View menu (second toolbar down).
- Select and check the Sidebar option.
- The Sidebar menu just expanded over on the right side of the screen.
- To the right of the Sidebar, find and click the Item button.
- Expand the Transform section.
- Set the Dimensions...
Note: These dimensions only make sense for the asset being used for this guide. If using a different one, set the dimensions to the size of the box that model should fit in.- X to 4.
- Y to 3.
- Z to 3.
- Be in Layout workspace (top toolbar) and in the Object Mode...
- Adjust the position and scale of the MedievalStallMesh to fit inside a box.
- Be in Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- On the left side of the screen there's a column of icons. Hover over them to see their names.
- Select the Move tool.
- Click on the Medieval Stall to select it. Zoom out and reposition the camera so that the blue, green, and red arrows are visible.
Tip: By holding the middle-mouse button and dragging the scene will rotate. By holding the middle-mouse button and the Shift key, the scene will pan.
Tip: If panning or rotating the scene becomes slow or frustrating (especially after zooming), try selecting 3D asset from the Scene Collection panel, opening the View menu (second toolbar from top), and selecting Frame Selected. This will reset the view onto that object and controls should feel normal again. - Click and hold one of the arrows. Move the mouse to drag the 3D asset towards the box.
- Move the 3D asset around till it's completely inside the box. If it cannot fit and is too big, continue to the next step.
Tip: To select the 3D asset once it disappears, use the Scene Collection panel. Click on it there and the blue, green, and red arrows will show up again for it.
Tip: There are preset views. To use them go to the View menu (second toolbar from top), hover Viewpoint, and select the view that would be most helpful. - Find the Scale tool from the left side of the screen.
- Now the blue, green, and red "arrows" don't really look like arrows anymore. They are lines with boxes at the end.
- Click and hold on those lines to adjust the scale of the 3D asset to make it fit inside the box.
Tip: There are little colored boxes in between the lines that can be dragged to scale the 3D asset more proportionally. - Continue using the Move and Scale tools till the model fits. This will take patience and time.
Tip: Hide the reference cube to see what is happening with the 3D asset. Go to the Scene Collections panel and click the 👁 button to hide it. Click that button again to show it.
- Be in Layout workspace (top toolbar) and in the Object Mode...
- Move the reference cube's origin to
(0.5, 0.5, 0.5)...- Be in Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- Open the View menu (second toolbar down).
- Select Sidebar.
- A new panel will have expanded.
- Along the right side of that panel there's buttons (Item, Tool, View, Animation). Find and click the View button.
- Find and expand the 3D Cursor section.
- Set the 3D cursor's Location...
- X to 0.5.
- Y to 0.5.
- Z to 0.5.
- Select the MedievalStallMesh using the Scene Collection panel.
- Open the Object menu (second toolbar down).
- Hover Set Origin.
- Select Origin to 3D Cursor.
- Be in Layout workspace (top toolbar) and in the Object Mode...
- Select the reference cube named Cube from the Scene Collections panel.
- Open Object menu (second toolbar down).
- Select Delete.
- Move the MedievalStallMesh to
(0, 0, 0)...- Be in Layout workspace (top toolbar) and in the Object Mode...
- Find the drop down in the second toolbar from the top that has options like Object Mode, Edit Mode, Sculpt Mode, etc.
- Select Object Mode from that drop down.
- Open the View menu (second toolbar down).
- Select Sidebar.
- A new panel will have expanded.
- Along the right side of that panel there's buttons (Item, Tool, View, Animation). Find and click the Item button.
- Make sure the MedievalStallMesh is selected. Use the Scene Collection panel if needed.
- Find and expand the Transform section
- Set the Location...
- X to 0.
- Y to 0.
- Z to 0.
- Be in Layout workspace (top toolbar) and in the Object Mode...
- Make sure the MedievalStallMesh is selected. Use the Scene Collection panel if needed.
- Open the Object menu.
- Hover Apply.
- Select All Transformations.
Note: This step bakes all of the changes into the mesh. It's very important. - Open the File menu from the top toolbar.
- Hover Export to open the sub-menu.
- Select FBX (.fbx)
- A Blender File View window will pop-up.
- On the right side of this window there's a ⚙️ icon. Click it to expand the settings region.
- In the expanded region find the Include section and expand it. Change the following:
- Find Object Types and only select Mesh. No other option should be highlighted for this setting.
- In the settings region scroll and find the Transform section and expand it. Change the following:
- Find Apply Scalings and set it to FBX All.
- Just below that find Forward and set it to Z Forward.
- Ensure that the next setting down, Up, changed to Y Up.
- Find Apply Unit and make sure it's checked.
- Next, find Use Space Transform check it.
- Lastly, find Apply Transform and check it too.
- Save it to
Assets/WikiDemo/MedievalStall.fbx. - Save the Blender scene...
- File drop down from top toolbar.
- Save As... to save the Blender scene to the computer.
- Save it to
Assets/WikiDemo/MedievalStall - Eco Ready Scene.blend.
Add to Unity Scene
- Open Unity.
- Select the
.fbxfile in the project window. - Open the Eco Tools menu from the top toolbar.
- Hover Mod Kit.
- Select World Object Setup.
- A World Object Setup window will pop-up.
- Make sure that Selected Objects reads MedievalStall.
- Also make sure that World Object Type is set to World Object.
- Press the Setup World Objects button.
- Notice in the project window that a new
.prefabfile was created --MedievalStallObject.prefab - Select the
.prefab. - In the Inspector panel find the Transform component.
- Change this component's Rotation...
- X to 0.
- Y to 0.
- Z to 0.
- In the Inspector panel find the Box Collider component.
- Find the ⋮ icon (all the way to the right of the words Box Collider) and click on it.
- Select Reset from the menu. This will regenerate the box collider now that the rotation has changed.
- Look in the Inspector panel and find the World Object (Script) component.
- That component has a checkbox Override Occupancy. Check it.
- A new field should've expanded below it called Size.
- Set the Size...
Note: This size similar to the size of the reference cube from earlier, but the Y and Z coordinates get flipped! So if in Blender it was(1, 2, 3)then in Unity its(1, 3, 2).- X to 4.
- Y to 3.
- Z to 3.
- Select Objects from Hierarchy panel (left-side of the window).
- Find the Modkit Prefab Container (Script) component. This component was added earlier, if it's not there add it now.
- Expand the Prefabs section in that component.
- Click the + button to add an item to the list.
- Either...
- Click the ⦿ button, switch to the Assets tab, find or search for MedievalStallObject, and double click on it. Make sure it's the medieval stall object with the
.prefabending. - Drag the
.prefabfile onto the ⦿ button
- Click the ⦿ button, switch to the Assets tab, find or search for MedievalStallObject, and double click on it. Make sure it's the medieval stall object with the
- Open the File menu from top toolbar and select Save.
Note: Do not skip. The scene must be saved for the ModKit build to work properly. - Open the Eco Tools menu from the top toolbar.
- Hover Mod Kit.
- Select Build Current Bundle.
- Save the bundle to
/Eco Server/Mods/UserCode/WikiDemo.unity3d
Coding the World Object
The following collapses the #region Recipe. Please see the earlier section Code the Item's Recipe to get the code that belongs there.
Add the new using lines, replace the #region Item section, and replace the #region Object sections using the following:
using Eco.Core.Items;
using Eco.Gameplay.Components;
using Eco.Gameplay.Items;
using Eco.Gameplay.Items.Recipes;
using Eco.Gameplay.Objects;
using Eco.Gameplay.Skills;
using Eco.Mods.TechTree;
using Eco.Shared.Localization;
using Eco.Shared.Serialization;
using System.Collections.Generic;
using System.Runtime.Versioning;
using System;
using Eco.Core.Controller;
using Eco.Gameplay.Systems.NewTooltip;
using Eco.Shared.Items;
using Eco.Gameplay.Occupancy;
using Eco.Shared.Math;
using Eco.Gameplay.Components.Auth;
namespace WikiDemo
{
#region Item
[Serialized] // Tells the save/load system this object needs to be serialized.
[SupportedOSPlatform("windows7.0")]
[LocDisplayName("Market Stall")] // Defines the localized name of the item.
[Weight(3000)] // Defines how heavy this is.
[Ecopedia("Work Stations", "Craft Tables", createAsSubPage: true)]
[LocDescription("A medieval market stall.")] //The tooltip description for the item.
public partial class MedievalStallItem : WorldObjectItem<MedievalStallObject>, IPersistentData
{
[Serialized, SyncToView, NewTooltipChildren(CacheAs.Instance, flags: TTFlags.AllowNonControllerTypeForChildren)] public object? PersistentData { get; set; }
protected override OccupancyContext GetOccupancyContext => new SideAttachedContext(
DirectionAxisFlags.Down, // Read: every occupied block on the bottom must be supported
WorldObject.GetOccupancyInfo(this.WorldObjectType)
);
}
#endregion
#region Recipe
#region Object
[Serialized]
[SupportedOSPlatform("windows7.0")]
[RequireComponent(typeof(CraftingComponent))]
[RequireComponent(typeof(MinimapComponent))]
[RequireComponent(typeof(LinkComponent))]
[RequireComponent(typeof(OccupancyRequirementComponent))]
[Tag("Usable")]
[Ecopedia("Work Stations", "Craft Tables", subPageName: "Market Stall")]
public partial class MedievalStallObject : WorldObject, IRepresentsItem
{
public Type RepresentedItemType => typeof(MedievalStallItem);
static MedievalStallObject()
{
WorldObject.AddOccupancy<MedievalStallObject>(CalculateBoxOccupancy(4, 3, 3));
}
protected override void Initialize()
{
this.ModsPreInitialize();
this.GetComponent<LinkComponent>().Initialize(15);
this.GetComponent<MinimapComponent>().SetCategory(Localizer.DoStr("Crafting"));
this.ModsPostInitialize();
}
/// <summary>Hook for mods to customize WorldObject before initialization. You can change housing values here.</summary>
partial void ModsPreInitialize();
/// <summary>Hook for mods to customize WorldObject after initialization.</summary>
partial void ModsPostInitialize();
/// <summary>
/// Calculates the blocks that this item will occupy when placed. All coordinates are offsets relative to this 3D model's origin
/// point. This function can only be used to calculate a box shape; there can be no gaps. All blocks will be of the
/// BlockOccupancyType.None type.
/// </summary>
///
/// Examples:
/// * Imagine a 1x1x1 cube. The origin point of the 3D model is the middle of the bottom-left cube. The only block the
/// cube would occupy would be the same one the origin point is in. In offset coordinates, the only block the cube occupies
/// is (0,0,0) from the origin point.
/// * Image a 1x5x1 flag pole. Again the origin point of the 3D model is in the middle of the bottom most cube. The only
/// blocks the flage pole occupies is the one the origin point is in and the 4 above that one. In offset coordinates, that
/// would be (0,0,0) + (0,1,0) + (0,2,0) + (0,3,0) + (0,4,0).
/// <returns></returns>
private static List<BlockOccupancy> CalculateBoxOccupancy(int sizeX, int sizeY, int sizeZ)
{
var cells = new List<BlockOccupancy>(sizeX * sizeY * sizeZ);
for (int x = 0; x < sizeX; x++)
for (int y = 0; y < sizeY; y++)
for (int z = 0; z < sizeZ; z++)
cells.Add(new BlockOccupancy(new Vector3i(x, y, z)));
return cells;
}
}
#endregion
}
Line 30: This changes from implementing Item to WorldObjectItem<MedievalStallObject>. This is what tell Eco that this item has the ability to place a world object into the world.
Line 32: This defines the object where PersistentData is stored. Other components like a PartsComponet would store the information of the table parts' durability in here. in this example, this line is illustrative and doesn't have any components using it.
Line 34: Sets the type of occupancy context this world object has. Occupancy is the system used to determine what space blocks and object are in. The SideAttachContext means that this object must have a certain side supported for it to be attached to the world and valid to be placed.
Line 35: Defines the bottom side as the side this object uses to attach.
Line 36: This line is getting the list of blocks occupied from a static lookup in WorldObject for the MedievalStallObject. See line 60 to see this value set.
Line 41: The "collapsed" Recipe section. See earlier sections in this guide to see what code belongs here.
Line 46: Adds a CraftComponent to the table. This component lets players use this table to craft something on.
Line 47: MinimapComponent this registers the object with the minimap. This makes it so when a player places a medieval stall, the minimap shows it. Related: line 67.
Line 48: LinkComponent allows storage linking. Related: line 66.
Line 49: OccupancyRequirementComponent defines this object as having and occupying physical space. Related: line 60.
Line 50: Assigns a tag to this object. Like how the tag Wood in Eco refers to all the different types of logs. In this case, the MedievalStallObject is being added to the Usable tag.
Line 52: Declares the MedievalStallObject. It's important that this class name is matches exactly the .prefab file name because the name is what links them.
Line 54: Declares the item that is given when this world object is picked up.
Line 58: This sets the occupancy for the world object in the simulation. This must also be set for the object in addition to the Override Occupancy and Size setting previously set on the Unity .prefab. That's because the settings in Unity are used client side. This sets the occupancy on the server side. They both need to be set and be matching for things to work right.
Line 64: Initializes the LinkComponent with a base 15 block radius. Know that this value is just the base value and that server settings will determine the actual game play radius.
Line 65: Initializes the MinimapComponent and add this object to the Crafting category.
Checkpoint

Warning: In Eco v13.0.2, free-placed objects may display misaligned ghost cubes, even when configured correctly in your mod. This is a visual-only base-game bug — placement still works as expected, even if the object appears red near edges.
- Have the
.unity3dand the.csfile in the/Eco Server/Mods/UserCodefolder. - Start the server and log in.
- Type
/give MedievalStall. - Place the stall down. Pro-tip: Put down a floor of flat roof tiles made of Reinforced Concrete. This will show you where the occupancy of your object is when you place it because the roof tiles will change shape under the object. Neat!
- It should look and function like a normal workbench.
The WikiDemo.unity3d and the WikiDemo.cs files are all that is needed to share this mod now.
Adding a Recipe to Craft
To add a recipe to the medieval stall add this to the WikiDemo.cs file:
using Eco.Core.Items;
using Eco.Gameplay.Components;
using Eco.Gameplay.Items;
using Eco.Gameplay.Items.Recipes;
using Eco.Gameplay.Objects;
using Eco.Gameplay.Skills;
using Eco.Mods.TechTree;
using Eco.Shared.Localization;
using Eco.Shared.Serialization;
using System.Collections.Generic;
using System.Runtime.Versioning;
using System;
using Eco.Core.Controller;
using Eco.Gameplay.Systems.NewTooltip;
using Eco.Shared.Items;
using Eco.Gameplay.Occupancy;
using Eco.Shared.Math;
using Eco.Gameplay.Components.Auth;
namespace WikiDemo
{
#region Item
#region Recipe
#region Object
#region CraftingRecipes
public partial class MyArrowRecipe : RecipeFamily
{
[SupportedOSPlatform("windows7.0")]
public MyArrowRecipe()
{
var recipe = new Recipe();
recipe.Init(
name: "Alternate Arrow",
displayName: Localizer.DoStr("Alternate Arrow"),
ingredients: new List<IngredientElement>
{
new IngredientElement("Wood", 1, typeof(Skill)),
new IngredientElement("Rock", 1)
},
items: new List<CraftingElement>
{
new CraftingElement<ArrowItem>(1)
}
);
this.Recipes = new List<Recipe> { recipe };
this.LaborInCalories = CreateLaborInCaloriesValue(10);
this.CraftMinutes = CreateCraftTimeValue(0.1f);
// Perform pre/post initialization for user mods and initialize our recipe instance with the display name "Market Stall"
this.ModsPreInitialize();
this.Initialize(displayText: Localizer.DoStr("Alternate Arrow Recipe"), recipeType: typeof(MyArrowRecipe));
this.ModsPostInitialize();
// Register our RecipeFamily instance to a work table (in this case the Carpentry Table) so it can be crafted.
CraftingComponent.AddRecipe(tableType: typeof(MedievalStallObject), recipeFamily: this); // NOTE: The table must be the object instance!
}
/// <summary>Hook for other mods to customize RecipeFamily before initialization.</summary>
partial void ModsPreInitialize();
/// <summary>Hook for other mods to customize RecipeFamily after initialization, but before registration. You can change skill requirements here.</summary>
partial void ModsPostInitialize();
}
#endregion
}

Line 58: This line here adds this recipe to the MedievalStallObject just created.