ComfyUI Node

RS Character Position

What the X/Y actually controls (it isn't where the body goes)

By raspie10032·Created 3 days ago·Updated 2 days ago· 1
RS Character Position
  • building_pipe
  • building_pipe
◄character_count2►
◄character1_geometrypoint►
◄character1_x0.50►
◄character1_y0.50►
◄character1_width0.40►
◄character1_height0.80►
◄character2_geometrypoint►
◄character2_x0.50►
◄character2_y0.50►
◄character2_width0.40►
◄character2_height0.80►
◄character3_geometrypoint►
◄character3_x0.50►
◄character3_y0.50►
◄character3_width0.40►
◄character3_height0.80►
◄character4_geometrypoint►
◄character4_x0.50►
◄character4_y0.50►
◄character4_width0.40►
◄character4_height0.80►
◄character5_geometrypoint►
◄character5_x0.50►
◄character5_y0.50►
◄character5_width0.40►
◄character5_height0.80►
◄character6_geometrypoint►
◄character6_x0.50►
◄character6_y0.50►
◄character6_width0.40►
◄character6_height0.80►
◄character7_geometrypoint►
◄character7_x0.50►
◄character7_y0.50►
◄character7_width0.40►
◄character7_height0.80►
◄character8_geometrypoint►
◄character8_x0.50►
◄character8_y0.50►
◄character8_width0.40►
◄character8_height0.80►
◄character9_geometrypoint►
◄character9_x0.50►
◄character9_y0.50►
◄character9_width0.40►
◄character9_height0.80►
◄character10_geometrypoint►
◄character10_x0.50►
◄character10_y0.50►
◄character10_width0.40►
◄character10_height0.80►

The most expensive misunderstanding in regional prompting: you move a character's centre, run it, and the person doesn't budge. You conclude the node is broken. It isn't. Coordinates here pick which prompt owns which patch of canvas - they're an attention partition, not a placement control. Get that straight and the rest of this node becomes obvious.

The mechanism, in one paragraph

Each character gets a normalised centre, and the sampler builds a nearest-centre partition of the whole image: every token belongs to exactly one character. Positive cross-attention then lets a token read the common scene prompt plus its own character's text, and nothing from the others. Boxes work the same way but claim a rectangle instead of a slice. So X/Y decides which words apply to which pixels - and because it's the model that decides what a person's body does inside that region, small coordinate nudges change surprisingly little on a single-character image, where one character owns the entire canvas anyway.

Doing it with the box or without

RS Character Position is the position role in the modular pipe: rows 1–10, each with geometry (point or box), x, y, width, height, all 0–1. character_count controls how many rows show, and the tooltip is precise about what it means - the prompt node's count determines the active regions, this node's count determines which slots get positions. Unlisted rows default to centre.

Points are quick and they behave well for the classic case: two people, one at 0.3 and one at 0.7, both at y 0.5, wide canvas, done. Coincident points spread left to right in slot order, and the sampler records original and effective coordinates separately, so two characters both sitting at 0.5 still come out side by side rather than stacked on each other.

Boxes are width and height around the centre, and they buy you two things. Overlap control - boxes take priority over point regions in mixed layouts, and overlapping boxes share their captions. And text regions, which can only exist in a box, since you can't write into a point.

The shipped counter-example is worth copying: two people plus the word HELLO is character_count = 3, slot 3 set to kind = text, geometry box, with the word in its string and a box placed where you want the lettering. Width 0.25 and height 0.15 are a sane starting rectangle for a word.

The layout guide

The node draws a guide of the current layout into its UI, and Finalize shows the complete line so you can see the whole arrangement in one place before sampling. Use it as a sanity check, not a preview. The author's own wording is that layout is "a guide, not a composition guarantee", and the validation notes back that up: requesting four people in a 2×2 grid produced twelve in one run and ten in another. Horizontal arrangements are the strongest tested case for a reason - a wide canvas with two characters maps cleanly onto two prompt regions, whereas rows and grids invite duplication.

Wiring

Output is building_pipe, same as the other role nodes. Connect Position, Prompt and LoRA in any order, finish with RS Finalize Character Pipe, then feed the sampler.

cd ComfyUI/custom_nodes
git clone https://github.com/raspie10032/ComfyUI_RS_MultiCharacter_Sampler.git
# restart ComfyUI

That's the whole install - the core pack has no root requirements file and leans on ComfyUI's own torch/NumPy/Pillow. Or install RS MultiCharacter Sampler from ComfyUI Manager; just don't do both, since a Manager copy alongside a Git checkout is the usual cause of a duplicated or half-loaded node list.

Failure modes I'd actually expect

Box geometry that runs off the canvas gets an explicit error with the fix in the message: move the centre inward or shrink the box. Handle it by keeping x ± width/2 and y ± height/2 inside 0–1.

Text rows without box geometry fail at Finalize. So do text rows carrying a LoRA - spelling has no character design attached.

And the classic: two characters with the same centre and the same prompt-ish text will blend into one extremely well-dressed person. Push the centres apart before you start fiddling with weights.

Finally, when one character occupies 80% of the frame and the other is squeezed into a corner, the composition is telling you the region sizes are the problem. Widen the canvas to 1536×768 rather than fighting the partition - that's the shape this pack was validated on.

CategoryRS MultiCharacter/Characters

Inputs (52)

NameTypeDefaultDescription
character_countINT21–10Show all slots 1–N together. Prompt count determines the active regions; LoRA/Position counts determine which settings they supply. / 1~N번 설정을 함께 표시합니다. 최종 인원수는 프롬프트 노드 기준입니다.
character1_geometryCOMBOpoint2 options: point, box
character1_xFLOAT0.500–1—
character1_yFLOAT0.500–1—
character1_widthFLOAT0.400.01–1—
character1_heightFLOAT0.800.01–1—
character2_geometryCOMBOpoint2 options: point, box
character2_xFLOAT0.500–1—
character2_yFLOAT0.500–1—
character2_widthFLOAT0.400.01–1—
character2_heightFLOAT0.800.01–1—
character3_geometryCOMBOpoint2 options: point, box
character3_xFLOAT0.500–1—
character3_yFLOAT0.500–1—
character3_widthFLOAT0.400.01–1—
character3_heightFLOAT0.800.01–1—
character4_geometryCOMBOpoint2 options: point, box
character4_xFLOAT0.500–1—
character4_yFLOAT0.500–1—
character4_widthFLOAT0.400.01–1—
character4_heightFLOAT0.800.01–1—
character5_geometryCOMBOpoint2 options: point, box
character5_xFLOAT0.500–1—
character5_yFLOAT0.500–1—
character5_widthFLOAT0.400.01–1—
character5_heightFLOAT0.800.01–1—
character6_geometryCOMBOpoint2 options: point, box
character6_xFLOAT0.500–1—
character6_yFLOAT0.500–1—
character6_widthFLOAT0.400.01–1—
character6_heightFLOAT0.800.01–1—
character7_geometryCOMBOpoint2 options: point, box
character7_xFLOAT0.500–1—
character7_yFLOAT0.500–1—
character7_widthFLOAT0.400.01–1—
character7_heightFLOAT0.800.01–1—
character8_geometryCOMBOpoint2 options: point, box
character8_xFLOAT0.500–1—
character8_yFLOAT0.500–1—
character8_widthFLOAT0.400.01–1—
character8_heightFLOAT0.800.01–1—
character9_geometryCOMBOpoint2 options: point, box
character9_xFLOAT0.500–1—
character9_yFLOAT0.500–1—
character9_widthFLOAT0.400.01–1—
character9_heightFLOAT0.800.01–1—
character10_geometryCOMBOpoint2 options: point, box
character10_xFLOAT0.500–1—
character10_yFLOAT0.500–1—
character10_widthFLOAT0.400.01–1—
character10_heightFLOAT0.800.01–1—
building_pipeoptRS_MC_BUILD_PIPE—

Outputs (1)

NameTypeDescription
building_pipeRS_MC_BUILD_PIPE—