Sometimes it's useful to make copies of objects at play time. A NodeEmitter essentially does this, for instance. In cases where a NodeEmitter isn't ideal, we can make copies directly from script. One useful case is when we work with shared copies and want to dynamically change a single copy at play time without affecting the other shared copies.
Here's a Trigger that can take in a SphereEntity that is shared with others (where all shared copies share the same shape). It makes a non-shared copy of the SphereEntity, then alters its radius.
function Trigger:onEnter(obj) -- Filter for non-sphere shapes if (not obj:getMeshModel():getShape():isTypeOf("SphereShape")) then return end -- Copy as non-shared so we can alter the radius without affecting other -- shared copies copy = obj:cloneAsCopy() -- Remove the original shared copy obj:orphan() -- Alter the copy's shape copy:getMeshModel():getShape().radius = 0.5 end
Managing complexity is an important part of working with copies. If we make too many copies of something, the system may get bogged down. The NodeEmitter, for instance, automatically manages a pre-determined object count and destroys the oldest emitted objects if the total number of emitted objects goes past a user defined threshold.
But what if we are copying objects manually? How do we remove objects from the space? In the following example, a Trigger will make a 10 shared copies of the object that passes through it. To manage complexity, it will define these copies to be temporary and fade them out after 5 seconds. It also handles not allowing the copies themselves to be copyable by the Trigger.
function Trigger:onEnter(obj) -- Filter out copied objects (so they don't recopy themselves) if (obj.noCopy) then return end -- Make 10 copies for i=1,10 do copy = obj:cloneAsSharedCopy() -- Set a variable inside the copy so we won't recopy -- it copy.noCopy = true -- Remove the copy after 5 seconds copy:fadeOutAndOrphan(seconds(5)) end end