LinearAnimation stores its keyed objects in ups
diff --git a/include/rive/animation/linear_animation.hpp b/include/rive/animation/linear_animation.hpp
index 1d91d3e..8f60da5 100644
--- a/include/rive/animation/linear_animation.hpp
+++ b/include/rive/animation/linear_animation.hpp
@@ -9,15 +9,16 @@
 
     class LinearAnimation : public LinearAnimationBase {
     private:
-        std::vector<KeyedObject*> m_KeyedObjects;
+        std::vector< std::unique_ptr<KeyedObject> > m_KeyedObjects;
 
         friend class Artboard;
 
     public:
-        ~LinearAnimation();
+        LinearAnimation();
+        ~LinearAnimation() override;
         StatusCode onAddedDirty(CoreContext* context) override;
         StatusCode onAddedClean(CoreContext* context) override;
-        void addKeyedObject(KeyedObject* object);
+        void addKeyedObject(std::unique_ptr<KeyedObject>);
         void apply(Artboard* artboard, float time, float mix = 1.0f) const;
 
         Loop loop() const { return (Loop)loopValue(); }
diff --git a/include/rive/importers/linear_animation_importer.hpp b/include/rive/importers/linear_animation_importer.hpp
index 3f3466d..80cb13f 100644
--- a/include/rive/importers/linear_animation_importer.hpp
+++ b/include/rive/importers/linear_animation_importer.hpp
@@ -14,7 +14,7 @@
     public:
         LinearAnimation* animation() const { return m_Animation; };
         LinearAnimationImporter(LinearAnimation* animation);
-        void addKeyedObject(KeyedObject* object);
+        void addKeyedObject(std::unique_ptr<KeyedObject>);
     };
 } // namespace rive
 #endif
diff --git a/src/animation/keyed_object.cpp b/src/animation/keyed_object.cpp
index 3b48962..7f04749 100644
--- a/src/animation/keyed_object.cpp
+++ b/src/animation/keyed_object.cpp
@@ -50,6 +50,7 @@
     if (importer == nullptr) {
         return StatusCode::MissingObject;
     }
-    importer->addKeyedObject(this);
+    // we transfer ownership of ourself to the importer!
+    importer->addKeyedObject(std::unique_ptr<KeyedObject>(this));
     return Super::import(importStack);
 }
\ No newline at end of file
diff --git a/src/animation/linear_animation.cpp b/src/animation/linear_animation.cpp
index 91e3d4c..f9b3672 100644
--- a/src/animation/linear_animation.cpp
+++ b/src/animation/linear_animation.cpp
@@ -10,18 +10,17 @@
 int LinearAnimation::deleteCount = 0;
 #endif
 
+LinearAnimation::LinearAnimation() {}
+
 LinearAnimation::~LinearAnimation() {
 #ifdef TESTING
     deleteCount++;
 #endif
-    for (auto object : m_KeyedObjects) {
-        delete object;
-    }
 }
 
 StatusCode LinearAnimation::onAddedDirty(CoreContext* context) {
     StatusCode code;
-    for (auto object : m_KeyedObjects) {
+    for (const auto& object : m_KeyedObjects) {
         if ((code = object->onAddedDirty(context)) != StatusCode::Ok) {
             return code;
         }
@@ -31,7 +30,7 @@
 
 StatusCode LinearAnimation::onAddedClean(CoreContext* context) {
     StatusCode code;
-    for (auto object : m_KeyedObjects) {
+    for (const auto& object : m_KeyedObjects) {
         if ((code = object->onAddedClean(context)) != StatusCode::Ok) {
             return code;
         }
@@ -39,10 +38,12 @@
     return StatusCode::Ok;
 }
 
-void LinearAnimation::addKeyedObject(KeyedObject* object) { m_KeyedObjects.push_back(object); }
+void LinearAnimation::addKeyedObject(std::unique_ptr<KeyedObject> object) {
+    m_KeyedObjects.push_back(std::move(object));
+}
 
 void LinearAnimation::apply(Artboard* artboard, float time, float mix) const {
-    for (auto object : m_KeyedObjects) {
+    for (const auto& object : m_KeyedObjects) {
         object->apply(artboard, time, mix);
     }
 }
diff --git a/src/artboard.cpp b/src/artboard.cpp
index b11e996..6758548 100644
--- a/src/artboard.cpp
+++ b/src/artboard.cpp
@@ -437,7 +437,7 @@
 bool Artboard::isTranslucent(const LinearAnimation* anim) const {
     // For now we're conservative/lazy -- if we see that any of our paints are
     // animated we assume that might make it non-opaque, so we early out
-    for (const auto obj : anim->m_KeyedObjects) {
+    for (const auto& obj : anim->m_KeyedObjects) {
         const auto ptr = this->resolve(obj->objectId());
         for (const auto sp : m_ShapePaints) {
             if (ptr == sp) {
diff --git a/src/importers/linear_animation_importer.cpp b/src/importers/linear_animation_importer.cpp
index c038eeb..43a9274 100644
--- a/src/importers/linear_animation_importer.cpp
+++ b/src/importers/linear_animation_importer.cpp
@@ -8,6 +8,6 @@
 LinearAnimationImporter::LinearAnimationImporter(LinearAnimation* animation) :
     m_Animation(animation) {}
 
-void LinearAnimationImporter::addKeyedObject(KeyedObject* object) {
-    m_Animation->addKeyedObject(object);
+void LinearAnimationImporter::addKeyedObject(std::unique_ptr<KeyedObject> object) {
+    m_Animation->addKeyedObject(std::move(object));
 }
\ No newline at end of file