How Client Entities Work
When the server or local world spawns an entity defined in a Behavior Pack (BP), the game client only receives its type identifier, position, and synchronised data. The client has no idea what the entity looks like until it checks the active Resource Packs (RP) for a matching client entity definition inside the RP/entity/ folder.
The client entity JSON does not contain raw 3D vertex coordinates or animation keyframes itself. Instead, it assigns short, convenient alias names (such as "default" or "walk") to the actual asset identifiers or file paths found elsewhere in your resource pack. Render controllers and animation controllers then reference those short aliases rather than the full identifiers.
Minimal Client Entity Structure
A client entity file lives inside the RP/entity/ directory (commonly named <name>.entity.json to distinguish it from the behavior file, though any .json extension works). At a minimum, a visible entity needs an identifier matching the behavior pack, a material, a texture, a geometry reference, and at least one render controller to draw them together.
Below is a complete, working client entity definition for a basic custom golem. It defines one model, one texture, a standard opaque entity material, a walking animation, and a spawn egg.
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "wiki:copper_golem",
"materials": {
"default": "entity"
},
"textures": {
"default": "textures/entity/copper_golem"
},
"geometry": {
"default": "geometry.copper_golem"
},
"animations": {
"walk": "animation.copper_golem.walk"
},
"scripts": {
"animate": [
{
"walk": "query.modified_move_speed"
}
]
},
"render_controllers": [
"controller.render.default"
],
"spawn_egg": {
"base_color": "#B86B43",
"overlay_color": "#4A856E"
}
}
}
}Description Properties Reference
Everything inside a client entity file happens inside the description object of minecraft:client_entity. Most fields are key-value dictionaries where the key is a short name you invent for this specific entity, and the value points to the global resource.
Here are the standard properties you will use when setting up a custom entity in the resource pack:
| Field | What it does | Notes |
|---|---|---|
| identifier | Links this visual definition to the Behavior Pack entity. | Must match the BP identifier string character-for-character. |
| materials | Maps short names to material definitions. | Common vanilla values: "entity", "entity_alphatest", "entity_emissive_alpha", "entity_alphablend". |
| textures | Maps short names to texture paths from the RP root. | Omit the .png file extension (for example, "textures/entity/my_mob"). |
| geometry | Maps short names to geometry identifiers defined in RP/models/entity/. | Always starts with "geometry." matching the identifier inside the model file. |
| animations | Maps short names to animation and animation controller identifiers. | Since format_version 1.10.0, both raw animations and animation controllers are listed here. |
| scripts | Runs Molang expressions to initialize variables, scale the model, or trigger animations. | Supports "initialize", "pre_animation", "animate", and "scale". |
| render_controllers | Lists the render controllers that assemble the geometry, material, and texture. | "controller.render.default" works for single-texture, single-model entities. |
| spawn_egg | Configures the appearance of the auto-generated spawn egg item. | Uses either "base_color" and "overlay_color" hex strings, or "texture" and "texture_index". |
How Render Controllers Connect Your Assets
Listing a model, texture, and material in the description is not enough to make an entity appear in the world. Minecraft requires a render controller to know which geometry gets paired with which material and texture on any given frame.
For simple entities that only have one look, you do not need to write a custom render controller file. You can reference the built-in "controller.render.default" inside the render_controllers array. However, there is a strict catch: "controller.render.default" is hardcoded to look for the short alias name "default" under geometry, materials, and textures. If you name your texture alias "main_skin" instead of "default", the built-in render controller will fail to find it.
When your entity has multiple skins, armor layers, or toggleable model parts, you write a custom render controller in RP/render_controllers/ and reference your custom short names there using arrays or Molang queries.
Running Animations with Scripts
In format_version 1.10.0, you declare all animations and animation controllers in the animations block, and then tell the game when to play them inside the scripts.animate array. Each entry in scripts.animate can either be a plain string (the short alias of an animation that should run constantly) or a single-key object where the key is the short alias and the value is a Molang condition or blend weight.
You can also use scripts.pre_animation to calculate Molang variables once per frame before any animations or render controllers evaluate. This keeps complex math out of your animation files and improves readability.
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "wiki:copper_golem",
"materials": {
"default": "entity_alphatest"
},
"textures": {
"default": "textures/entity/copper_golem"
},
"geometry": {
"default": "geometry.copper_golem"
},
"animations": {
"look_at_target": "animation.common.look_at_target",
"idle": "animation.copper_golem.idle",
"walk": "animation.copper_golem.walk",
"move_ctrl": "controller.animation.copper_golem.move"
},
"scripts": {
"pre_animation": [
"variable.is_moving = query.ground_speed > 0.05;"
],
"animate": [
"look_at_target",
"move_ctrl",
{
"walk": "query.modified_move_speed"
}
]
},
"render_controllers": [
"controller.render.default"
]
}
}
}Spawn Egg and Localization
If your Behavior Pack entity has "is_spawnable": true in its description, the client entity's spawn_egg block determines how that egg looks in the Creative inventory. Using base_color and overlay_color tints the standard two-layer vanilla egg template using hexadecimal color codes. If you prefer a completely custom item icon, you can define a short name in RP/textures/item_texture.json and reference it in the spawn_egg block using the "texture" property.
Finally, to give your entity and its spawn egg a proper display name instead of raw identifiers, add two lines to your language file (such as RP/texts/en_US.lang):
entity.wiki:copper_golem.name=Copper Golem
item.spawn_egg.entity.wiki:copper_golem.name=Spawn Copper GolemWhich versions this applies to
Client entity format_version 1.10.0 is stable and supported across all modern Bedrock versions (1.10.0 through 1.21+). An older format_version (1.8.0) still loads for legacy packs and some vanilla overrides, but 1.10.0 is standard because it allows scripts and direct animation blending. No experimental toggles are required for custom resource pack entities.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| The entity spawns in the world (it has a shadow, makes sounds, or has a hitbox), but it is completely invisible. | Either the identifier in RP/entity/ does not match the BP/entities/ identifier, the render_controllers array is missing, or you used "controller.render.default" without naming your geometry, material, and texture keys "default". | Check the Content Log for errors like [RenderController] Could not find geometry 'default'. Ensure your short keys in materials, textures, and geometry are all named "default" when using the default render controller. |
| The entity renders with a pink-and-black checkerboard texture. | The file path in the textures dictionary does not match the actual location of the .png file in your Resource Pack, or you accidentally included the ".png" extension in the JSON path. | Verify the file is located at RP/textures/entity/<name>.png and that the JSON string reads "textures/entity/<name>" with forward slashes and no file extension. |
| Transparent parts of the texture appear solid black or white on the model. | The material is set to "entity", which is opaque and ignores alpha channels for performance reasons. | Change the material value from "entity" to "entity_alphatest" (for sharp cutout transparency) or "entity_alphablend" (for translucent stained-glass style pixels). |
| Animations defined in the file never play, even though there are no JSON syntax errors. | The animations were registered in the "animations" block, but never actually called inside "scripts": { "animate": [ ... ] }, or the file is set to format_version 1.8.0 while using 1.10.0 script syntax. | Ensure "format_version" at the top of the client entity JSON is "1.10.0", and add the short name of each animation or controller to the "scripts.animate" array. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
