1import{_ as t,c as n,a as s,g as e,i as l,h,o as p}from"./app-DqiSUqwL.js";const k={};function r(o,i){const a=h("video-embed");return p(),n("div",null,[i[0]||(i[0]=s("h1",{id:"duplicate-objects-by-dragging",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#duplicate-objects-by-dragging"},[s("span",null,"Duplicate Objects by Dragging")])],-1)),i[1]||(i[1]=s("p",null,"Create interactive experiences where users can spawn copies of objects by clicking and dragging.",-1)),e(a,{src:"/docs/videos/duplicatable.mp4",autoplay:"",muted:""}),i[2]||(i[2]=l(`<div class="hint-container tip"><p class="hint-container-title">Works with Unity and Blender</p><p>The Duplicatable component is available for both Unity and Blender integrations.</p></div><h2 id="what-you-can-do" tabindex="-1"><a class="header-anchor" href="#what-you-can-do"><span>What You Can Do</span></a></h2><ul><li><strong>Drag to Duplicate</strong> - Users click and drag to create a copy that follows their cursor</li><li><strong>Automatic Networking</strong> - Duplicated objects sync across all connected users</li><li><strong>Rate Limiting</strong> - Prevent spam by limiting how many objects can be created</li><li><strong>Custom Templates</strong> - Define what object gets duplicated</li><li><strong>Works with DragControls</strong> - Automatically integrates with object dragging</li></ul><p>Perfect for:</p><ul><li>Object placement tools</li><li>Building and construction games</li><li>Collaborative design spaces</li><li>Inventory systems where items spawn</li><li>Furniture configurators</li></ul><h2 id="quick-start" tabindex="-1"><a class="header-anchor" href="#quick-start"><span>Quick Start</span></a></h2><h3 id="basic-setup" tabindex="-1"><a class="header-anchor" href="#basic-setup"><span>Basic Setup</span></a></h3><p><strong>In Unity or Blender:</strong></p><ol><li>Create an object you want to duplicate (e.g., a cube)</li><li>Add a <code>Duplicatable</code> component to it</li><li>The component automatically sets up the object as a template</li><li>Export and open in browser</li><li>Click and drag the object - a copy spawns and follows your cursor!</li></ol><h3 id="with-multiplayer" tabindex="-1"><a class="header-anchor" href="#with-multiplayer"><span>With Multiplayer</span></a></h3><p>Share duplicated objects with other users:</p><ol><li>Add <code>SyncedRoom</code> component to your scene</li><li>The Duplicatable component automatically adds networking</li><li>When users click and create objects, everyone sees them</li></ol><h2 id="settings" tabindex="-1"><a class="header-anchor" href="#settings"><span>Settings</span></a></h2><table><thead><tr><th>Setting</th><th>What it does</th></tr></thead><tbody><tr><td><strong>Object</strong></td><td>The object to duplicate (leave empty to duplicate this object)</td></tr><tr><td><strong>Parent</strong></td><td>Where duplicates are parented (leave empty to use this object's parent)</td></tr><tr><td><strong>Limit Count</strong></td><td>Max objects that can be created per 60 seconds (prevents spam)</td></tr></tbody></table><h2 id="how-it-works" tabindex="-1"><a class="header-anchor" href="#how-it-works"><span>How It Works</span></a></h2><p>When you add Duplicatable to an object:</p><ol><li>The component creates a hidden template copy</li><li>When you click and drag, a new instance spawns from the template</li><li>The new object follows your cursor as you drag</li><li>If networking is enabled, the object syncs to other users</li><li>The template stays hidden and ready for the next duplication</li></ol><h2 id="examples" tabindex="-1"><a class="header-anchor" href="#examples"><span>Examples</span></a></h2><h3 id="furniture-spawner" tabindex="-1"><a class="header-anchor" href="#furniture-spawner"><span>Furniture Spawner</span></a></h3><p>Create a palette of furniture users can place:</p><ol><li>Create furniture objects (chair, table, lamp)</li><li>Add <code>Duplicatable</code> to each one</li><li>Arrange them in a palette/toolbar area</li><li>Set <strong>Limit Count</strong> to <code>10</code> to prevent spam</li><li>Users click and drag to create and place furniture</li></ol><h3 id="building-blocks" tabindex="-1"><a class="header-anchor" href="#building-blocks"><span>Building Blocks</span></a></h3><p>Let users build with blocks:</p><ol><li>Create a block object</li><li>Add <code>Duplicatable</code> component</li><li>Add <code>DragControls</code> (automatically configured)</li><li>Set drag mode to snap to grid</li><li>Users click and drag to create blocks and build structures</li></ol><h3 id="inventory-system" tabindex="-1"><a class="header-anchor" href="#inventory-system"><span>Inventory System</span></a></h3><p>Spawn items from an inventory:</p><ol><li>Create item templates (tools, equipment, etc.)</li><li>Add <code>Duplicatable</code> to each</li><li>Set <strong>Parent</strong> to a "world items" container</li><li>Display items in UI or palette</li><li>Click items to spawn them into the scene</li></ol><h3 id="collaborative-object-spawning" tabindex="-1"><a class="header-anchor" href="#collaborative-object-spawning"><span>Collaborative Object Spawning</span></a></h3><p>Multiple users adding objects together:</p><ol><li>Add <code>SyncedRoom</code> component</li><li>Create object templates with <code>Duplicatable</code></li><li>Each template automatically gets <code>SyncedTransform</code></li><li>Users spawn and place objects collaboratively</li><li>Everyone sees the same scene in real-time</li></ol><h2 id="scripting" tabindex="-1"><a class="header-anchor" href="#scripting"><span>Scripting</span></a></h2><h3 id="duplicate-programmatically" tabindex="-1"><a class="header-anchor" href="#duplicate-programmatically"><span>Duplicate Programmatically</span></a></h3><p>Trigger duplication from code without user click:</p><div class="language-ts" data-highlighter="shiki" data-ext="ts" style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#263238;"><pre class="shiki shiki-themes one-light material-theme vp-code"><code class="language-ts"><span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">
1import</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> Behaviour</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> Duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> GameObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> from</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;"> "</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">@needle-tools/engine</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 2<span class="line"></span> 3<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">export</span><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> ObjectSpawner</span><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> extends</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> Behaviour</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 4<span class="line"></span> 5<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#F07178;"> start</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">()</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 6<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> const</span><span style="--shiki-light:#986801;--shiki-dark:#EEFFFF;"> duplicatable</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#89DDFF;"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">gameObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">getComponent</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">(</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">Duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">)</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 7<span class="line"></span> 8<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">duplicatable</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;"> &&</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">[</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">handleDuplication</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">]) </span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">{</span></span> 9<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#546E7A;--shiki-dark-font-style:italic;"> // Spawn a copy</span></span> 10<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> const</span><span style="--shiki-light:#986801;--shiki-dark:#EEFFFF;"> newObject</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">[</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">handleDuplication</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">]()</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 11<span class="line"></span> 12<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">newObject</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">) </span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">
12{</span></span> 13<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> console</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">log</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">Spawned:</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> newObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">name</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">)</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 14<span class="line"></span> 15<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#546E7A;--shiki-dark-font-style:italic;"> // Customize the spawned object</span></span> 16<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> newObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">position</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">set</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">(</span><span style="--shiki-light:#986801;--shiki-dark:#F78C6C;">0</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#986801;--shiki-dark:#F78C6C;"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#986801;--shiki-dark:#F78C6C;"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">)</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 17<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 18<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 19<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 20<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">}</span></span></code></pre></div><div class="hint-container warning"><p class="hint-container-title">Private Method</p><p>The <code>handleDuplication</code> method is private. The recommended way is to let users click the object naturally. Use this approach only for advanced cases.</p></div><h3 id="custom-duplication-logic" tabindex="-1"><a class="header-anchor" href="#custom-duplication-logic"><span>Custom Duplication Logic</span></a></h3><p>Create your own duplication system:</p><div class="language-ts" data-highlighter="shiki" data-ext="ts" style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#263238;"><pre class="shiki shiki-themes one-light material-theme vp-code"><code class="language-ts"><span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">import</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> Behaviour</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> GameObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> serializable</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> from</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;"> "</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">@needle-tools/engine</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 21<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">
21import</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> Object3D</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> from</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;"> "</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">three</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 22<span class="line"></span> 23<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">export</span><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> CustomDuplicator</span><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> extends</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> Behaviour</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 24<span class="line"></span> 25<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> @</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">serializable</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">(Object3D)</span></span> 26<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#F07178;"> template</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;">?:</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> Object3D</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 27<span class="line"></span> 28<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#F07178;"> onPointerClick</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">()</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 29<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;"> (</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;">!</span><span style="--shiki-light:#E45649;--shiki-dark:#89DDFF;">this</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">template</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">) </span><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">return</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 30<span class="line"></span> 31<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#546E7A;--shiki-dark-font-style:italic;"> // Clone the template</span></span> 32<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> const</span><span style="--shiki-light:#986801;--shiki-dark:#EEFFFF;"> clone</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> GameObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">instantiateSynced</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">(</span><span style="--shiki-light:#E45649;--shiki-dark:#89DDFF;">this</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">template</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 33<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#F07178;"> parent</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;">:</span><span style="--shiki-light:#E45649;--shiki-dark:#89DDFF;"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">gameObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span></span> 34<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#F07178;"> position</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;">:</span><span style="--shiki-light:#E45649;--shiki-dark:#89DDFF;"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">worldPosition</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span></span> 35<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">)</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 36<span class="line"></span> 37<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">clone</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">) </span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">
37{</span></span> 38<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> console</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">log</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">Created custom duplicate:</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> clone</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">name</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">)</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 39<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 40<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 41<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">}</span></span></code></pre></div><h3 id="check-duplicate-count" tabindex="-1"><a class="header-anchor" href="#check-duplicate-count"><span>Check Duplicate Count</span></a></h3><p>Monitor how many objects have been created:</p><div class="language-ts" data-highlighter="shiki" data-ext="ts" style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#263238;"><pre class="shiki shiki-themes one-light material-theme vp-code"><code class="language-ts"><span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">import</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> Behaviour</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> Duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> from</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;"> "</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">@needle-tools/engine</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 42<span class="line"></span> 43<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">export</span><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> DuplicateMonitor</span><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> extends</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> Behaviour</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 44<span class="line"></span> 45<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#F07178;"> update</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">()</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 46<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> const</span><span style="--shiki-light:#986801;--shiki-dark:#EEFFFF;"> duplicatable</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#89DDFF;"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">gameObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">getComponent</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">(</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">
46Duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">)</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 47<span class="line"></span> 48<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">) </span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">{</span></span> 49<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#546E7A;--shiki-dark-font-style:italic;"> // Access internal counter (private, for debugging)</span></span> 50<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> const</span><span style="--shiki-light:#986801;--shiki-dark:#EEFFFF;"> count</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">[</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">_currentCount</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">]</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 51<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> const</span><span style="--shiki-light:#986801;--shiki-dark:#EEFFFF;"> limit</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">limitCount</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 52<span class="line"></span> 53<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;"> console</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">log</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">\`</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">Created: </span><span style="--shiki-light:#CA1243;--shiki-dark:#89DDFF;">\${</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">count</span><span style="--shiki-light:#CA1243;--shiki-dark:#89DDFF;">}</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">/</span><span style="--shiki-light:#CA1243;--shiki-dark:#89DDFF;">\${</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">limit</span><span style="--shiki-light:#CA1243;--shiki-dark:#89DDFF;">}</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">\`</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">)</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 54<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 55<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 56<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">}</span></span></code></pre></div><h3 id="customize-spawned-objects" tabindex="-1"><a class="header-anchor" href="#customize-spawned-objects"><span>Customize Spawned Objects</span></a></h3><p>Modify objects right after they're created:</p><div class="language-ts" data-highlighter="shiki" data-ext="ts" style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#263238;"><pre class="shiki shiki-themes one-light material-theme vp-code"><code class="language-ts"><span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">
56import</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> Behaviour</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">,</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;"> Duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;"> from</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;"> "</span><span style="--shiki-light:#50A14F;--shiki-dark:#C3E88D;">@needle-tools/engine</span><span style="--shiki-light:#50A14F;--shiki-dark:#89DDFF;">"</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 57<span class="line"></span> 58<span class="line"><span style="--shiki-light:#A626A4;--shiki-light-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic;">export</span><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> class</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> CustomizeSpawned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> extends</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> Behaviour</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 59<span class="line"></span> 60<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C792EA;"> private</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;"> duplicatable</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;">?:</span><span style="--shiki-light:#C18401;--shiki-dark:#FFCB6B;"> Duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 61<span class="line"></span> 62<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#F07178;"> awake</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">()</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 63<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#89DDFF;"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">duplicatable</span><span style="--shiki-light:#0184BC;--shiki-dark:#89DDFF;"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#89DDFF;"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#E45649;--shiki-dark:#EEFFFF;">gameObject</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#82AAFF;">getComponent</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">(</span><span style="--shiki-light:#383A42;--shiki-dark:#EEFFFF;">Duplicatable</span><span style="--shiki-light:#383A42;--shiki-dark:#F07178;">)</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">;</span></span> 64<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 65<span class="line"></span> 66<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#F07178;"> update</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">()</span><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> {</span></span> 67<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#546E7A;--shiki-dark-font-style:italic;"> // Watch for DragControls being created on new objects</span></span> 68<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#546E7A;--shiki-dark-font-style:italic;"> // This happens right after duplication</span></span> 69<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#546E7A;--shiki-dark-font-style:italic;"> // You can then customize the newly spawned object</span></span> 70<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;"> }</span></span> 71<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#89DDFF;">}</span></span></code></pre></div><h2 id="advanced-features" tabindex="-1"><a class="header-anchor" href="#advanced-features"><span>Advanced Features</span></a></h2><h3 id="automatic-dragcontrols" tabindex="-1"><a class="header-anchor" href="#automatic-dragcontrols"><span>Automatic DragControls</span></a></h3><p>When Duplicatable creates an object:</p><ul><li>Automatically adds <code>DragControls</code> if not present</li><li>Sets drag mode to <code>SnapToSurfaces</code> by default</li><li>User can immediately drag the new object</li><li>No additional setup needed</li></ul><h3 id="automatic-networking" tabindex="-1"><a class="header-anchor" href="#automatic-networking"><span>Automatic Networking</span></a></h3><p>When <code>SyncedRoom</code> is present:</p><ul><li>Uses <code>GameObject.instantiateSynced()</code> automatically</li><li>Adds <code>SyncedTransform</code> to spawned objects</li><li>All users see duplicated objects</li><li>Position and rotation sync in real-time</li></ul><h3 id="rate-limiting" tabindex="-1"><a class="header-anchor" href="#rate-limiting"><span>Rate Limiting</span></a></h3><p>Prevents users from creating too many objects:</p><ul><li><strong>
71Limit Count</strong> controls max objects per minute</li><li>Counter decrements by 1 every second</li><li>When limit is reached, clicks are ignored</li><li>Warning logged to console</li><li>Automatically resets over time</li></ul><h3 id="template-system" tabindex="-1"><a class="header-anchor" href="#template-system"><span>Template System</span></a></h3><p>The object to duplicate becomes a hidden template:</p><ul><li>Original object is hidden (<code>visible = false</code>)</li><li>Template preserves initial position and rotation</li><li>Each click spawns from the template</li><li>Template never appears in the scene</li></ul><h2 id="common-questions" tabindex="-1"><a class="header-anchor" href="#common-questions"><span>Common Questions</span></a></h2><p><strong>What happens to the original object?</strong> The original becomes a hidden template. The first duplicate you see is actually a copy, not the original.</p><p><strong>Can I duplicate objects without DragControls?</strong> The component expects DragControls and adds it automatically. If you don't want dragging, disable DragControls on the spawned object via script.</p><p><strong>How do I change what object gets duplicated?</strong> Set the <strong>Object</strong> field to a different object. If left empty, the object with the Duplicatable component is used.</p><p><strong>Can I duplicate objects with animations or scripts?</strong> Yes! The entire hierarchy and all components are copied. Scripts, animations, materials - everything is duplicated.</p><p><strong>What's the difference between Duplicatable and instantiate?</strong> Duplicatable is for user interaction (clicking to spawn). <code>GameObject.instantiate()</code> is for programmatic spawning in code.</p><p><strong>How do I increase the spawn limit?</strong> Change <strong>Limit Count</strong> to a higher number. Default is 60 objects per minute. Set to 0 for unlimited (not recommended).</p><p><strong>Does it work with physics?</strong> Yes! Duplicated objects keep their Rigidbody components and physics properties.</p><h2 id="common-issues" tabindex="-1"><a class="header-anchor" href="#common-issues"><span>Common Issues</span></a></h2><p><strong>Objects spawn at wrong position:</strong> Make sure the template object starts at the correct position. The Duplicatable stores the initial position when the scene loads.</p><p><strong>Can't create any objects:</strong> Check if you've hit the <strong>Limit Count</strong>. Wait a few seconds and try again, or increase the limit.</p><p><strong>Objects don't appear for other users:</strong> Ensure you have <code>SyncedRoom</code> in your scene for networking to work.</p><p><strong>Duplicated object is missing components:</strong> Check if components are being destroyed in <code>start()</code> or <code>awake()</code>. Some components remove themselves on instantiation.</p><h2 id="more-information" tabindex="-1"><a class="header-anchor" href="#more-information"><span>More Information</span></a></h2><p><strong>Live Example:</strong></p><ul><li><a href="https://engine.needle.tools/samples/collaborative-sandbox/" target="_blank" rel="noopener noreferrer">Collaborative Sandbox</a> - Multi-user building with duplication and dragging</li></ul><p><strong>API Documentation:</strong></p><ul><li><a href="https://engine.needle.tools/docs/api/Duplicatable" target="_blank" rel="noopener noreferrer">Duplicatable API</a> - Complete technical reference</li></ul><p><strong>Related Components:</strong></p><ul><li><a href="/docs/how-to-guides/components/drag-controls">DragControls</a> - Drag and move objects</li><li><a href="/docs/reference/components#deletable">Deletable</a> - Delete spawned objects</li><li><a href="/docs/reference/components#syncedtransform">SyncedTransform</a> - Network synchronization</li></ul>`,77))])}const c=t(k,[["render",r]]),F=JSON.parse('{"path":"/how-to-guides/components/duplicatable.html","title":"Duplicate Objects by Dragging (Duplicatable)","lang":"en-US","frontmatter":{"title":"Duplicate Objects by Dragging (Duplicatable)","description":"Let users create copies of objects by dragging them with the Duplicatable component. Works in Unity and Blender with multiplayer support.","head":[["link",{"rel":"canonical","href":"https://engine.needle.tools/docs/how-to-guides/components/duplicatable.html"}],["meta",{"name":"og:image","content":"https://engine.needle.tools/docs/imgs/default-unfurl-image-2.webp"}],["meta",{"name":"og:description","content":"Let users create copies of objects by dragging them with the Duplicatable component. Works in Unity and Blender with multiplayer support."}],["meta",{"property":"og:title","content":"Duplicate Objects by Dragging (Duplicatable) â Needle Engine"}]]}
71,"git":{"updatedTime":1769604971000,"contributors":[{"name":"Marcel Wiessler","username":"","email":"[email protected]","commits":1}],"changelog":[{"hash":"fc2e9a85ae5b565ab70d20b53454d6e7f5d166c3","time":1769604971000,"email":"[email protected]","author":"Marcel Wiessler","message":"add some component guides"}]},"filePathRelative":"how-to-guides/components/duplicatable.md"}');export{c as comp,F as data};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.