diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj
index f7d520dd..11cb1697 100644
--- a/projects/kiwano/kiwano.vcxproj
+++ b/projects/kiwano/kiwano.vcxproj
@@ -4,7 +4,6 @@
     
     
     
-    
     
     
     
diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters
index 7e28e439..c0a05373 100644
--- a/projects/kiwano/kiwano.vcxproj.filters
+++ b/projects/kiwano/kiwano.vcxproj.filters
@@ -75,15 +75,9 @@
     
       2d
     
-    
-      2d\action
-    
     
       2d\action
     
-    
-      2d\action
-    
     
       2d\action
     
@@ -357,6 +351,9 @@
     
       core
     
+    
+      2d\action
+    
   
   
     
@@ -380,9 +377,6 @@
     
       2d
     
-    
-      2d\action
-    
     
       2d\action
     
@@ -584,6 +578,9 @@
     
       base
     
+    
+      2d\action
+    
   
   
     
diff --git a/src/kiwano/2d/action/Action.cpp b/src/kiwano/2d/action/Action.cpp
index 796fc25b..36654579 100644
--- a/src/kiwano/2d/action/Action.cpp
+++ b/src/kiwano/2d/action/Action.cpp
@@ -23,7 +23,7 @@
 
 namespace kiwano
 {
-Action::Action()
+ActionEntity::ActionEntity()
     : running_(true)
     , detach_target_(false)
     , loops_done_(0)
@@ -32,18 +32,18 @@ Action::Action()
 {
 }
 
-Action::~Action() {}
+ActionEntity::~ActionEntity() {}
 
-void Action::Init(Actor* target) {}
+void ActionEntity::Init(Actor* target) {}
 
-void Action::Update(Actor* target, Duration dt)
+void ActionEntity::Update(Actor* target, Duration dt)
 {
     Complete(target);
 }
 
-void Action::UpdateStep(Actor* target, Duration dt)
+void ActionEntity::UpdateStep(Actor* target, Duration dt)
 {
-    KGE_ASSERT(target != nullptr && "Action target should NOT be nullptr!");
+    KGE_ASSERT(target != nullptr && "ActionEntity target should NOT be nullptr!");
 
     elapsed_ += dt;
 
@@ -82,7 +82,7 @@ void Action::UpdateStep(Actor* target, Duration dt)
     }
 }
 
-void Action::Complete(Actor* target)
+void ActionEntity::Complete(Actor* target)
 {
     if (cb_loop_done_)
         cb_loop_done_(target);
@@ -99,16 +99,14 @@ void Action::Complete(Actor* target)
     ++loops_done_;
 }
 
-void Action::Restart(Actor* target)
+void ActionEntity::Reset()
 {
     status_     = Status::NotStarted;
     elapsed_    = 0;
     loops_done_ = 0;
-
-    Init(target);
 }
 
-ActionPtr Action::DoClone(ActionPtr to) const
+ActionEntityPtr ActionEntity::DoClone(ActionEntityPtr to) const
 {
     if (to)
     {
diff --git a/src/kiwano/2d/action/Action.h b/src/kiwano/2d/action/Action.h
index 0de9a0a4..109c37d6 100644
--- a/src/kiwano/2d/action/Action.h
+++ b/src/kiwano/2d/action/Action.h
@@ -32,7 +32,7 @@ namespace kiwano
 class Actor;
 class ActionScheduler;
 
-KGE_DECLARE_SMART_PTR(Action);
+KGE_DECLARE_SMART_PTR(ActionEntity);
 
 /**
  * \~chinese
@@ -45,24 +45,28 @@ KGE_DECLARE_SMART_PTR(Action);
  */
 
 /// \~chinese
-/// @brief 动画
-class KGE_API Action
+/// @brief 动画列表
+typedef IntrusiveList ActionList;
+
+/// \~chinese
+/// @brief 动画结束时的回调函数
+typedef Function ActionDoneCallback;
+
+/// \~chinese
+/// @brief 动画实体
+class KGE_API ActionEntity
     : public ObjectBase
-    , public Cloneable
-    , protected IntrusiveListValue
+    , public Cloneable
+    , protected IntrusiveListValue
 {
     friend class ActionScheduler;
-    friend class ActionGroup;
-    friend IntrusiveList;
+    friend class ActionGroupEntity;
+    friend IntrusiveList;
 
 public:
-    /// \~chinese
-    /// @brief 动画结束时的回调函数
-    using DoneCallback = Function;
+    ActionEntity();
 
-    Action();
-
-    virtual ~Action();
+    virtual ~ActionEntity();
 
     /// \~chinese
     /// @brief 继续动画
@@ -91,15 +95,15 @@ public:
 
     /// \~chinese
     /// @brief 设置动画结束时的回调函数
-    void SetDoneCallback(const DoneCallback& cb);
+    void SetDoneCallback(const ActionDoneCallback& cb);
 
     /// \~chinese
     /// @brief 设置动画循环结束时的回调函数
-    void SetLoopDoneCallback(const DoneCallback& cb);
+    void SetLoopDoneCallback(const ActionDoneCallback& cb);
 
     /// \~chinese
     /// @brief 获取动画的倒转
-    virtual ActionPtr Reverse() const = 0;
+    virtual ActionEntityPtr Reverse() const = 0;
 
     /// \~chinese
     /// @brief 获取动画的运行状态
@@ -115,11 +119,11 @@ public:
 
     /// \~chinese
     /// @brief 获取动画结束时的回调函数
-    DoneCallback GetDoneCallback() const;
+    ActionDoneCallback GetDoneCallback() const;
 
     /// \~chinese
     /// @brief 获取动画循环结束时的回调函数
-    DoneCallback GetLoopDoneCallback() const;
+    ActionDoneCallback GetLoopDoneCallback() const;
 
 protected:
     /// \~chinese
@@ -139,8 +143,8 @@ protected:
     void Complete(Actor* target);
 
     /// \~chinese
-    /// @brief 重新开始动画
-    void Restart(Actor* target);
+    /// @brief 重置动画
+    void Reset();
 
     /// \~chinese
     /// @brief 动画状态
@@ -178,113 +182,208 @@ protected:
     bool IsRemoveable() const;
 
 protected:
-    ActionPtr DoClone(ActionPtr to) const;
+    ActionEntityPtr DoClone(ActionEntityPtr to) const;
 
 private:
-    Status       status_;
-    bool         running_;
-    bool         detach_target_;
-    int          loops_;
-    int          loops_done_;
-    Duration     delay_;
-    Duration     elapsed_;
-    DoneCallback cb_done_;
-    DoneCallback cb_loop_done_;
+    Status             status_;
+    bool               running_;
+    bool               detach_target_;
+    int                loops_;
+    int                loops_done_;
+    Duration           delay_;
+    Duration           elapsed_;
+    ActionDoneCallback cb_done_;
+    ActionDoneCallback cb_loop_done_;
+};
+
+/// \~chinese
+/// @brief 动画
+class KGE_API Action
+{
+public:
+    /// \~chinese
+    /// @brief 设置循环次数
+    inline Action& Loops(int loops)
+    {
+        ptr->SetLoops(loops);
+        return (*this);
+    }
+
+    /// \~chinese
+    /// @brief 设置动画延迟
+    inline Action& Delay(Duration delay)
+    {
+        ptr->SetDelay(delay);
+        return (*this);
+    }
+
+    /// \~chinese
+    /// @brief 设置动画结束回调函数
+    inline Action& DoneCallback(const ActionDoneCallback& cb)
+    {
+        ptr->SetDoneCallback(cb);
+        return (*this);
+    }
+
+    /// \~chinese
+    /// @brief 设置动画循环结束时的回调函数
+    inline Action& LoopDoneCallback(const ActionDoneCallback& cb)
+    {
+        ptr->SetLoopDoneCallback(cb);
+        return (*this);
+    }
+
+    /// \~chinese
+    /// @brief 动画结束时移除目标角色
+    inline Action& RemoveTargetWhenDone()
+    {
+        ptr->RemoveTargetWhenDone();
+        return (*this);
+    }
+
+    /// \~chinese
+    /// @brief 设置名称
+    inline Action& Name(const String& name)
+    {
+        ptr->SetName(name);
+        return (*this);
+    }
+
+    /// \~chinese
+    /// @brief 克隆动画
+    inline Action Clone() const
+    {
+        return Action(ptr->Clone());
+    }
+
+    /// \~chinese
+    /// @brief 获取反向动画
+    inline Action Reverse() const
+    {
+        return Action(ptr->Reverse());
+    }
+
+    /// \~chinese
+    /// @brief 获取指针
+    inline ActionEntity* Get() const
+    {
+        return const_cast(ptr.Get());
+    }
+
+    inline operator ActionEntityPtr() const
+    {
+        return ptr;
+    }
+
+protected:
+    Action() = default;
+
+    inline Action(ActionEntityPtr ptr)
+        : ptr(ptr)
+    {
+    }
+
+    inline void SetEntity(ActionEntityPtr ptr)
+    {
+        this->ptr = ptr;
+    }
+
+    ActionEntityPtr ptr;
 };
 
 /** @} */
 
-inline void Action::Resume()
+inline void ActionEntity::Resume()
 {
     running_ = true;
 }
 
-inline void Action::Pause()
+inline void ActionEntity::Pause()
 {
     running_ = false;
 }
 
-inline void Action::Stop()
+inline void ActionEntity::Stop()
 {
     Done();
 }
 
-inline void Action::SetDelay(Duration delay)
+inline void ActionEntity::SetDelay(Duration delay)
 {
     delay_ = delay;
 }
 
-inline void Action::SetLoops(int loops)
+inline void ActionEntity::SetLoops(int loops)
 {
     loops_ = loops;
 }
 
-inline void Action::RemoveTargetWhenDone()
+inline void ActionEntity::RemoveTargetWhenDone()
 {
     detach_target_ = true;
 }
 
-inline void Action::SetDoneCallback(const DoneCallback& cb)
+inline void ActionEntity::SetDoneCallback(const ActionDoneCallback& cb)
 {
     cb_done_ = cb;
 }
 
-inline void Action::SetLoopDoneCallback(const DoneCallback& cb)
+inline void ActionEntity::SetLoopDoneCallback(const ActionDoneCallback& cb)
 {
     cb_loop_done_ = cb;
 }
 
-inline void Action::Done()
+inline void ActionEntity::Done()
 {
     status_ = Status::Done;
 }
 
-inline Action::Status Action::GetStatus() const
+inline ActionEntity::Status ActionEntity::GetStatus() const
 {
     return status_;
 }
 
-inline bool Action::IsRunning() const
+inline bool ActionEntity::IsRunning() const
 {
     return running_;
 }
 
-inline bool Action::IsDone() const
+inline bool ActionEntity::IsDone() const
 {
     return status_ == Status::Done || status_ == Status::Removeable;
 }
 
-inline bool Action::IsRemoveable() const
+inline bool ActionEntity::IsRemoveable() const
 {
     return status_ == Status::Removeable;
 }
 
-inline int Action::GetLoops() const
+inline int ActionEntity::GetLoops() const
 {
     return loops_;
 }
 
-inline Duration Action::GetDelay() const
+inline Duration ActionEntity::GetDelay() const
 {
     return delay_;
 }
 
-inline Duration Action::GetElapsed() const
+inline Duration ActionEntity::GetElapsed() const
 {
     return elapsed_;
 }
 
-inline int Action::GetLoopsDone() const
+inline int ActionEntity::GetLoopsDone() const
 {
     return loops_done_;
 }
 
-inline Action::DoneCallback Action::GetDoneCallback() const
+inline ActionDoneCallback ActionEntity::GetDoneCallback() const
 {
     return cb_done_;
 }
 
-inline Action::DoneCallback Action::GetLoopDoneCallback() const
+inline ActionDoneCallback ActionEntity::GetLoopDoneCallback() const
 {
     return cb_loop_done_;
 }
diff --git a/src/kiwano/2d/action/ActionDelay.cpp b/src/kiwano/2d/action/ActionDelay.cpp
index 3450ab6c..06f1023f 100644
--- a/src/kiwano/2d/action/ActionDelay.cpp
+++ b/src/kiwano/2d/action/ActionDelay.cpp
@@ -23,9 +23,14 @@
 namespace kiwano
 {
 
-ActionDelayPtr ActionDelay::Create(Duration delay)
+ActionDelay::ActionDelay(Duration delay)
 {
-    ActionDelayPtr ptr = memory::New();
+    SetEntity(ActionDelayEntity::Create(delay));
+}
+
+ActionDelayEntityPtr ActionDelayEntity::Create(Duration delay)
+{
+    ActionDelayEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDelay(delay);
@@ -33,14 +38,14 @@ ActionDelayPtr ActionDelay::Create(Duration delay)
     return ptr;
 }
 
-ActionPtr ActionDelay::Clone() const
+ActionEntityPtr ActionDelayEntity::Clone() const
 {
-    return DoClone(ActionDelay::Create(GetDelay()));
+    return DoClone(ActionDelayEntity::Create(GetDelay()));
 }
 
-ActionPtr ActionDelay::Reverse() const
+ActionEntityPtr ActionDelayEntity::Reverse() const
 {
-    return DoClone(ActionDelay::Create(GetDelay()));
+    return DoClone(ActionDelayEntity::Create(GetDelay()));
 }
 
 }  // namespace kiwano
diff --git a/src/kiwano/2d/action/ActionDelay.h b/src/kiwano/2d/action/ActionDelay.h
index 7cf11e1b..2a702f53 100644
--- a/src/kiwano/2d/action/ActionDelay.h
+++ b/src/kiwano/2d/action/ActionDelay.h
@@ -24,7 +24,7 @@
 namespace kiwano
 {
 
-KGE_DECLARE_SMART_PTR(ActionDelay);
+KGE_DECLARE_SMART_PTR(ActionDelayEntity);
 
 /**
  * \addtogroup Actions
@@ -39,15 +39,26 @@ public:
     /// \~chinese
     /// @brief 创建延时动画
     /// @param delay 延时时长
-    static ActionDelayPtr Create(Duration delay);
+    ActionDelay(Duration delay);
+};
+
+/// \~chinese
+/// @brief 延时动画实体
+class KGE_API ActionDelayEntity : public ActionEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建延时动画
+    /// @param delay 延时时长
+    static ActionDelayEntityPtr Create(Duration delay);
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override;
+    ActionEntityPtr Reverse() const override;
 };
 
 /** @} */
diff --git a/src/kiwano/2d/action/ActionGroup.cpp b/src/kiwano/2d/action/ActionGroup.cpp
index bff4986d..f11b7509 100644
--- a/src/kiwano/2d/action/ActionGroup.cpp
+++ b/src/kiwano/2d/action/ActionGroup.cpp
@@ -25,9 +25,14 @@
 namespace kiwano
 {
 
-ActionGroupPtr ActionGroup::Create(const Vector& actions, bool parallel)
+ActionGroup::ActionGroup(const Vector& actions, bool parallel)
 {
-    ActionGroupPtr ptr = memory::New();
+    SetEntity(ActionGroupEntity::Create(actions, parallel));
+}
+
+ActionGroupEntityPtr ActionGroupEntity::Create(const Vector& actions, bool parallel)
+{
+    ActionGroupEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->parallel_ = parallel;
@@ -36,19 +41,19 @@ ActionGroupPtr ActionGroup::Create(const Vector& actions, bool parall
     return ptr;
 }
 
-ActionGroup::ActionGroup()
+ActionGroupEntity::ActionGroupEntity()
     : parallel_(false)
 {
 }
 
-ActionGroup::ActionGroup(bool parallel)
+ActionGroupEntity::ActionGroupEntity(bool parallel)
     : parallel_(parallel)
 {
 }
 
-ActionGroup::~ActionGroup() {}
+ActionGroupEntity::~ActionGroupEntity() {}
 
-void ActionGroup::Init(Actor* target)
+void ActionGroupEntity::Init(Actor* target)
 {
     if (actions_.IsEmpty())
     {
@@ -56,22 +61,19 @@ void ActionGroup::Init(Actor* target)
         return;
     }
 
-    if (parallel_)
+    // reset all actions
+    for (current_ = actions_.GetFirst(); current_; current_ = current_->GetNext())
     {
-        // init all actions
-        for (current_ = actions_.GetFirst(); current_; current_ = current_->GetNext())
-        {
-            current_->Restart(target);
-        }
+        current_->Reset();
     }
-    else
+
+    if (!parallel_)
     {
         current_ = actions_.GetFirst();
-        current_->Restart(target);  // init first action
     }
 }
 
-void ActionGroup::Update(Actor* target, Duration dt)
+void ActionGroupEntity::Update(Actor* target, Duration dt)
 {
     if (!parallel_)
     {
@@ -83,9 +85,7 @@ void ActionGroup::Update(Actor* target, Duration dt)
             {
                 current_ = current_->GetNext();
 
-                if (current_)
-                    current_->Restart(target);  // init next action
-                else
+                if (!current_)
                     Complete(target);
             }
         }
@@ -109,7 +109,7 @@ void ActionGroup::Update(Actor* target, Duration dt)
     }
 }
 
-void ActionGroup::AddAction(ActionPtr action)
+void ActionGroupEntity::AddAction(ActionEntityPtr action)
 {
     if (action)
     {
@@ -117,28 +117,28 @@ void ActionGroup::AddAction(ActionPtr action)
     }
 }
 
-void ActionGroup::AddActions(const Vector& actions)
+void ActionGroupEntity::AddActions(const Vector& actions)
 {
     for (const auto& action : actions)
         AddAction(action);
 }
 
-ActionPtr ActionGroup::Clone() const
+ActionEntityPtr ActionGroupEntity::Clone() const
 {
-    Vector actions;
+    Vector actions;
     if (!actions_.IsEmpty())
     {
-        for (auto action = actions_.GetLast(); action; action = action->GetPrev())
+        for (auto action = actions_.GetFirst(); action; action = action->GetNext())
         {
             actions.push_back(action->Clone());
         }
     }
-    return DoClone(ActionGroup::Create(actions, parallel_));
+    return DoClone(ActionGroupEntity::Create(actions, parallel_));
 }
 
-ActionPtr ActionGroup::Reverse() const
+ActionEntityPtr ActionGroupEntity::Reverse() const
 {
-    Vector actions;
+    Vector actions;
     if (!actions_.IsEmpty())
     {
         for (auto action = actions_.GetLast(); action; action = action->GetPrev())
@@ -146,7 +146,7 @@ ActionPtr ActionGroup::Reverse() const
             actions.push_back(action->Reverse());
         }
     }
-    return DoClone(ActionGroup::Create(actions, parallel_));
+    return DoClone(ActionGroupEntity::Create(actions, parallel_));
 }
 
 }  // namespace kiwano
diff --git a/src/kiwano/2d/action/ActionGroup.h b/src/kiwano/2d/action/ActionGroup.h
index 95a7ff80..1afcb678 100644
--- a/src/kiwano/2d/action/ActionGroup.h
+++ b/src/kiwano/2d/action/ActionGroup.h
@@ -23,7 +23,7 @@
 
 namespace kiwano
 {
-KGE_DECLARE_SMART_PTR(ActionGroup);
+KGE_DECLARE_SMART_PTR(ActionGroupEntity);
 
 /**
  * \addtogroup Actions
@@ -35,29 +35,39 @@ KGE_DECLARE_SMART_PTR(ActionGroup);
 class KGE_API ActionGroup : public Action
 {
 public:
-    using ActionList = IntrusiveList;
-
     /// \~chinese
     /// @brief 创建动画组合
     /// @param actions 动画集合
     /// @param parallel 同步执行
-    static ActionGroupPtr Create(const Vector& actions, bool parallel = false);
+    ActionGroup(const Vector& actions, bool parallel = false);
+};
 
-    ActionGroup();
+/// \~chinese
+/// @brief 动画组合实体
+class KGE_API ActionGroupEntity : public ActionEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建动画组合
+    /// @param actions 动画集合
+    /// @param parallel 同步执行
+    static ActionGroupEntityPtr Create(const Vector& actions, bool parallel = false);
 
-    ActionGroup(bool parallel);
+    ActionGroupEntity();
 
-    virtual ~ActionGroup();
+    ActionGroupEntity(bool parallel);
+
+    virtual ~ActionGroupEntity();
 
     /// \~chinese
     /// @brief 添加动画
     /// @param action 动画
-    void AddAction(ActionPtr action);
+    void AddAction(ActionEntityPtr action);
 
     /// \~chinese
     /// @brief 添加多个动画
     /// @param actions 动画集合
-    void AddActions(const Vector& actions);
+    void AddActions(const Vector& actions);
 
     /// \~chinese
     /// @brief 获取所有动画
@@ -65,11 +75,11 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override;
+    ActionEntityPtr Reverse() const override;
 
 protected:
     void Init(Actor* target) override;
@@ -77,14 +87,14 @@ protected:
     void Update(Actor* target, Duration dt) override;
 
 private:
-    bool       parallel_;
-    ActionPtr  current_;
-    ActionList actions_;
+    bool            parallel_;
+    ActionEntityPtr current_;
+    ActionList      actions_;
 };
 
 /** @} */
 
-inline const ActionGroup::ActionList& ActionGroup::GetActions() const
+inline const ActionList& ActionGroupEntity::GetActions() const
 {
     return actions_;
 }
diff --git a/src/kiwano/2d/action/ActionHelper.h b/src/kiwano/2d/action/ActionHelper.h
deleted file mode 100644
index f0c727b0..00000000
--- a/src/kiwano/2d/action/ActionHelper.h
+++ /dev/null
@@ -1,370 +0,0 @@
-// Copyright (c) 2016-2018 Kiwano - Nomango
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#pragma once
-#include 
-#include 
-#include 
-#include 
-#include 
-
-namespace kiwano
-{
-/**
- * \addtogroup Actions
- * @{
- */
-
-/// \~chinese
-/// @brief 动画辅助类
-struct ActionHelper
-{
-    /// \~chinese
-    /// @brief 设置循环次数
-    inline ActionHelper& Loops(int loops)
-    {
-        ptr->SetLoops(loops);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置动画延迟
-    inline ActionHelper& Delay(Duration delay)
-    {
-        ptr->SetDelay(delay);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置动画结束回调函数
-    inline ActionHelper& DoneCallback(const Action::DoneCallback& cb)
-    {
-        ptr->SetDoneCallback(cb);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置动画循环结束时的回调函数
-    inline ActionHelper& LoopDoneCallback(const Action::DoneCallback& cb)
-    {
-        ptr->SetLoopDoneCallback(cb);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 动画结束时移除目标角色
-    inline ActionHelper& RemoveTargetWhenDone()
-    {
-        ptr->RemoveTargetWhenDone();
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置名称
-    inline ActionHelper& Name(const String& name)
-    {
-        ptr->SetName(name);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 获取指针
-    inline ActionPtr Get() const
-    {
-        return ptr;
-    }
-
-    inline ActionHelper(ActionPtr ptr)
-        : ptr(ptr)
-    {
-    }
-
-    inline operator ActionPtr() const
-    {
-        return ptr;
-    }
-
-    inline ActionPtr operator->() const
-    {
-        return ptr;
-    }
-
-private:
-    ActionPtr ptr;
-};
-
-/// \~chinese
-/// @brief 补间动画辅助类
-struct TweenHelper
-{
-    /// \~chinese
-    /// @brief 设置动画持续时长
-    inline TweenHelper& Dur(Duration dur)
-    {
-        ptr->SetDuration(dur);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置循环次数
-    inline TweenHelper& Loops(int loops)
-    {
-        ptr->SetLoops(loops);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置缓动函数
-    inline TweenHelper& EaseFunc(EaseFunc ease)
-    {
-        ptr->SetEaseFunc(ease);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置动画延迟
-    inline TweenHelper& Delay(Duration delay)
-    {
-        ptr->SetDelay(delay);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置动画结束回调函数
-    inline TweenHelper& DoneCallback(const Action::DoneCallback& cb)
-    {
-        ptr->SetDoneCallback(cb);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置动画循环结束时的回调函数
-    inline TweenHelper& LoopDoneCallback(const Action::DoneCallback& cb)
-    {
-        ptr->SetLoopDoneCallback(cb);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 动画结束时移除目标角色
-    inline TweenHelper& RemoveTargetWhenDone()
-    {
-        ptr->RemoveTargetWhenDone();
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 设置名称
-    inline TweenHelper& Name(const String& name)
-    {
-        ptr->SetName(name);
-        return (*this);
-    }
-
-    /// \~chinese
-    /// @brief 获取指针
-    inline ActionTweenPtr Get() const
-    {
-        return ptr;
-    }
-
-    inline TweenHelper(ActionTweenPtr ptr)
-        : ptr(ptr)
-    {
-    }
-
-    inline operator ActionPtr() const
-    {
-        return ptr;
-    }
-
-    inline operator ActionTweenPtr() const
-    {
-        return ptr;
-    }
-
-    inline ActionTweenPtr operator->() const
-    {
-        return ptr;
-    }
-
-private:
-    ActionTweenPtr ptr;
-};
-
-/// \~chinese
-/// @brief 动画构造器
-struct Tween
-{
-public:
-    /// \~chinese
-    /// @brief 构造相对位移动画
-    /// @param dur 动画时长
-    /// @param vector 移动向量
-    static inline TweenHelper MoveBy(Duration dur, const Point& vector)
-    {
-        return TweenHelper(ActionMoveBy::Create(dur, vector));
-    }
-
-    /// \~chinese
-    /// @brief 构造位移动画
-    /// @param dur 动画时长
-    /// @param pos 目的坐标
-    static inline TweenHelper MoveTo(Duration dur, const Point& pos)
-    {
-        return TweenHelper(ActionMoveTo::Create(dur, pos));
-    }
-
-    /// \~chinese
-    /// @brief 构造相对跳跃动画
-    /// @param dur 动画时长
-    /// @param vec 跳跃位移向量
-    /// @param height 跳跃高度
-    /// @param jumps 跳跃次数
-    static inline TweenHelper JumpBy(Duration dur, const Vec2& vec, float height, int jumps = 1)
-    {
-        return TweenHelper(ActionJumpBy::Create(dur, vec, height, jumps));
-    }
-
-    /// \~chinese
-    /// @brief 构造跳跃动画
-    /// @param dur 动画时长
-    /// @param pos 目的坐标
-    /// @param height 跳跃高度
-    /// @param jumps 跳跃次数
-    static inline TweenHelper JumpTo(Duration dur, const Point& pos, float height, int jumps = 1)
-    {
-        return TweenHelper(ActionJumpTo::Create(dur, pos, height, jumps));
-    }
-
-    /// \~chinese
-    /// @brief 构造相对缩放动画
-    /// @param dur 动画时长
-    /// @param scale_x 横向缩放相对变化值
-    /// @param scale_y 纵向缩放相对变化值
-    static inline TweenHelper ScaleBy(Duration dur, float scale_x, float scale_y)
-    {
-        return TweenHelper(ActionScaleBy::Create(dur, scale_x, scale_y));
-    }
-
-    /// \~chinese
-    /// @brief 构造缩放动画
-    /// @param dur 动画时长
-    /// @param scale_x 横向缩放目标值
-    /// @param scale_y 纵向缩放目标值
-    static inline TweenHelper ScaleTo(Duration dur, float scale_x, float scale_y)
-    {
-        return TweenHelper(ActionScaleTo::Create(dur, scale_x, scale_y));
-    }
-
-    /// \~chinese
-    /// @brief 构造透明度渐变动画
-    /// @param dur 动画时长
-    /// @param opacity 目标透明度
-    static inline TweenHelper FadeTo(Duration dur, float opacity)
-    {
-        return TweenHelper(ActionFadeTo::Create(dur, opacity));
-    }
-
-    /// \~chinese
-    /// @brief 构造淡入动画
-    /// @param dur 动画时长
-    static inline TweenHelper FadeIn(Duration dur)
-    {
-        return TweenHelper(ActionFadeIn::Create(dur));
-    }
-
-    /// \~chinese
-    /// @brief 构造淡出动画
-    /// @param dur 动画时长
-    static inline TweenHelper FadeOut(Duration dur)
-    {
-        return TweenHelper(ActionFadeOut::Create(dur));
-    }
-
-    /// \~chinese
-    /// @brief 构造相对旋转动画
-    /// @param dur 动画时长
-    /// @param rotation 角度相对变化值
-    static inline TweenHelper RotateBy(Duration dur, float rotation)
-    {
-        return TweenHelper(ActionRotateBy::Create(dur, rotation));
-    }
-
-    /// \~chinese
-    /// @brief 构造旋转动画
-    /// @param dur 动画时长
-    /// @param rotation 目标角度
-    static inline TweenHelper RotateTo(Duration dur, float rotation)
-    {
-        return TweenHelper(ActionRotateTo::Create(dur, rotation));
-    }
-
-    /// \~chinese
-    /// @brief 构造路径行走动画
-    /// @param dur 持续时长
-    /// @param path 路径形状
-    /// @param rotating 是否沿路径切线方向旋转
-    /// @param start 路径起点(百分比)
-    /// @param end 路径终点(百分比)
-    static inline TweenHelper Walk(Duration dur, ShapePtr path, bool rotating = false, float start = 0.f,
-                                   float end = 1.f)
-    {
-        return TweenHelper(ActionWalk::Create(dur, path, rotating, start, end));
-    }
-
-    /// \~chinese
-    /// @brief 构建帧动画
-    /// @param dur 动画时长
-    /// @param[in] frame_seq 序列帧
-    static inline TweenHelper Animation(Duration dur, FrameSequencePtr frames)
-    {
-        return TweenHelper(Animation::Create(dur, frames));
-    }
-
-    /// \~chinese
-    /// @brief 构造自定义动画
-    /// @param dur 动画时长
-    /// @param tween_func 动画回调函数
-    static inline TweenHelper Custom(Duration dur, ActionCustom::TweenFunc tween_func)
-    {
-        return TweenHelper(ActionCustom::Create(dur, tween_func));
-    }
-
-    /// \~chinese
-    /// @brief 构建延时动画
-    /// @param delay 延时时长
-    static inline ActionHelper Delay(Duration delay)
-    {
-        return ActionHelper(ActionDelay::Create(delay));
-    }
-
-    /// \~chinese
-    /// @brief 动画组合
-    /// @param actions 动画集合
-    /// @param parallel 同步执行
-    static inline ActionHelper Group(const Vector& actions, bool parallel = false)
-    {
-        return ActionHelper(ActionGroup::Create(actions, parallel));
-    }
-};
-
-/** @} */
-}  // namespace kiwano
diff --git a/src/kiwano/2d/action/ActionScheduler.cpp b/src/kiwano/2d/action/ActionScheduler.cpp
index 4e1fb3fb..c34a8480 100644
--- a/src/kiwano/2d/action/ActionScheduler.cpp
+++ b/src/kiwano/2d/action/ActionScheduler.cpp
@@ -30,7 +30,7 @@ void ActionScheduler::Update(Actor* target, Duration dt)
     if (actions_.IsEmpty() || !target)
         return;
 
-    ActionPtr next;
+    ActionEntityPtr next;
     for (auto action = actions_.GetFirst(); action; action = next)
     {
         next = action->GetNext();
@@ -43,7 +43,7 @@ void ActionScheduler::Update(Actor* target, Duration dt)
     }
 }
 
-Action* ActionScheduler::AddAction(ActionPtr action)
+ActionEntity* ActionScheduler::AddAction(ActionEntityPtr action)
 {
     KGE_ASSERT(action && "AddAction failed, NULL pointer exception");
 
@@ -87,7 +87,7 @@ void ActionScheduler::StopAllActions()
     }
 }
 
-ActionPtr ActionScheduler::GetAction(const String& name)
+ActionEntityPtr ActionScheduler::GetAction(const String& name)
 {
     if (actions_.IsEmpty())
         return nullptr;
diff --git a/src/kiwano/2d/action/ActionScheduler.h b/src/kiwano/2d/action/ActionScheduler.h
index 1cc4f26f..ddb9027c 100644
--- a/src/kiwano/2d/action/ActionScheduler.h
+++ b/src/kiwano/2d/action/ActionScheduler.h
@@ -29,10 +29,6 @@ namespace kiwano
  * @{
  */
 
-/// \~chinese
-/// @brief 动画列表
-typedef IntrusiveList ActionList;
-
 /**
  * \~chinese
  * @brief 动画调度器
@@ -42,7 +38,7 @@ class KGE_API ActionScheduler
 public:
     /// \~chinese
     /// @brief 添加动画
-    Action* AddAction(ActionPtr action);
+    ActionEntity* AddAction(ActionEntityPtr action);
 
     /// \~chinese
     /// @brief 继续所有暂停动画
@@ -59,7 +55,7 @@ public:
     /// \~chinese
     /// @brief 获取指定名称的动画
     /// @param name 动画名称
-    ActionPtr GetAction(const String& name);
+    ActionEntityPtr GetAction(const String& name);
 
     /// \~chinese
     /// @brief 获取所有动画
diff --git a/src/kiwano/2d/action/ActionTween.cpp b/src/kiwano/2d/action/ActionTween.cpp
index dc5849c2..c0c65865 100644
--- a/src/kiwano/2d/action/ActionTween.cpp
+++ b/src/kiwano/2d/action/ActionTween.cpp
@@ -86,22 +86,22 @@ KGE_API EaseFunc Ease::QuintOut     = math::EaseQuintOut;
 KGE_API EaseFunc Ease::QuintInOut   = math::EaseQuintInOut;
 
 //-------------------------------------------------------
-// ActionTween
+// ActionTweenEntity
 //-------------------------------------------------------
 
-ActionTween::ActionTween()
+ActionTweenEntity::ActionTweenEntity()
     : dur_()
     , ease_func_(nullptr)
 {
 }
 
-ActionTween::ActionTween(Duration duration, EaseFunc func)
+ActionTweenEntity::ActionTweenEntity(Duration duration, EaseFunc func)
     : dur_(duration)
     , ease_func_(func)
 {
 }
 
-void ActionTween::Update(Actor* target, Duration dt)
+void ActionTweenEntity::Update(Actor* target, Duration dt)
 {
     float percent;
 
@@ -129,23 +129,23 @@ void ActionTween::Update(Actor* target, Duration dt)
     UpdateTween(target, percent);
 }
 
-ActionPtr ActionTween::DoClone(ActionTweenPtr to) const
+ActionEntityPtr ActionTweenEntity::DoClone(ActionTweenEntityPtr to) const
 {
     if (to)
     {
         to->SetDuration(this->GetDuration());
         to->SetEaseFunc(this->GetEaseFunc());
     }
-    return Action::DoClone(to);
+    return ActionEntity::DoClone(to);
 }
 
 //-------------------------------------------------------
 // Move Action
 //-------------------------------------------------------
 
-ActionMoveByPtr ActionMoveBy::Create(Duration duration, const Vec2& displacement)
+ActionMoveByEntityPtr ActionMoveByEntity::Create(Duration duration, const Vec2& displacement)
 {
-    ActionMoveByPtr ptr = memory::New();
+    ActionMoveByEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -154,9 +154,9 @@ ActionMoveByPtr ActionMoveBy::Create(Duration duration, const Vec2& displacement
     return ptr;
 }
 
-ActionMoveBy::ActionMoveBy() {}
+ActionMoveByEntity::ActionMoveByEntity() {}
 
-void ActionMoveBy::Init(Actor* target)
+void ActionMoveByEntity::Init(Actor* target)
 {
     if (target)
     {
@@ -164,7 +164,7 @@ void ActionMoveBy::Init(Actor* target)
     }
 }
 
-void ActionMoveBy::UpdateTween(Actor* target, float percent)
+void ActionMoveByEntity::UpdateTween(Actor* target, float percent)
 {
     Point diff = target->GetPosition() - prev_pos_;
     start_pos_ = start_pos_ + diff;
@@ -175,19 +175,19 @@ void ActionMoveBy::UpdateTween(Actor* target, float percent)
     prev_pos_ = new_pos;
 }
 
-ActionPtr ActionMoveBy::Clone() const
+ActionEntityPtr ActionMoveByEntity::Clone() const
 {
-    return DoClone(ActionMoveBy::Create(GetDuration(), displacement_));
+    return DoClone(ActionMoveByEntity::Create(GetDuration(), displacement_));
 }
 
-ActionPtr ActionMoveBy::Reverse() const
+ActionEntityPtr ActionMoveByEntity::Reverse() const
 {
-    return DoClone(ActionMoveBy::Create(GetDuration(), -displacement_));
+    return DoClone(ActionMoveByEntity::Create(GetDuration(), -displacement_));
 }
 
-ActionMoveToPtr ActionMoveTo::Create(Duration duration, const Point& distination)
+ActionMoveToEntityPtr ActionMoveToEntity::Create(Duration duration, const Point& distination)
 {
-    ActionMoveToPtr ptr = memory::New();
+    ActionMoveToEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -196,16 +196,16 @@ ActionMoveToPtr ActionMoveTo::Create(Duration duration, const Point& distination
     return ptr;
 }
 
-ActionMoveTo::ActionMoveTo() {}
+ActionMoveToEntity::ActionMoveToEntity() {}
 
-ActionPtr ActionMoveTo::Clone() const
+ActionEntityPtr ActionMoveToEntity::Clone() const
 {
-    return DoClone(ActionMoveTo::Create(GetDuration(), distination_));
+    return DoClone(ActionMoveToEntity::Create(GetDuration(), distination_));
 }
 
-void ActionMoveTo::Init(Actor* target)
+void ActionMoveToEntity::Init(Actor* target)
 {
-    ActionMoveBy::Init(target);
+    ActionMoveByEntity::Init(target);
     displacement_ = distination_ - start_pos_;
 }
 
@@ -213,14 +213,12 @@ void ActionMoveTo::Init(Actor* target)
 // Jump Action
 //-------------------------------------------------------
 
-ActionJumpByPtr ActionJumpBy::Create(Duration duration, const Vec2& displacement, float height, int count,
-                                     EaseFunc ease)
+ActionJumpByEntityPtr ActionJumpByEntity::Create(Duration duration, const Vec2& displacement, float height, int count)
 {
-    ActionJumpByPtr ptr = memory::New();
+    ActionJumpByEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
-        ptr->SetEaseFunc(ease);
         ptr->SetJumpHeight(height);
         ptr->SetJumpCount(count);
         ptr->SetDisplacement(displacement);
@@ -228,23 +226,23 @@ ActionJumpByPtr ActionJumpBy::Create(Duration duration, const Vec2& displacement
     return ptr;
 }
 
-ActionJumpBy::ActionJumpBy()
+ActionJumpByEntity::ActionJumpByEntity()
     : height_(0.0f)
     , jump_count_(0)
 {
 }
 
-ActionPtr ActionJumpBy::Clone() const
+ActionEntityPtr ActionJumpByEntity::Clone() const
 {
-    return DoClone(ActionJumpBy::Create(GetDuration(), displacement_, height_, jump_count_));
+    return DoClone(ActionJumpByEntity::Create(GetDuration(), displacement_, height_, jump_count_));
 }
 
-ActionPtr ActionJumpBy::Reverse() const
+ActionEntityPtr ActionJumpByEntity::Reverse() const
 {
-    return DoClone(ActionJumpBy::Create(GetDuration(), -displacement_, height_, jump_count_));
+    return DoClone(ActionJumpByEntity::Create(GetDuration(), -displacement_, height_, jump_count_));
 }
 
-void ActionJumpBy::Init(Actor* target)
+void ActionJumpByEntity::Init(Actor* target)
 {
     if (target)
     {
@@ -252,7 +250,7 @@ void ActionJumpBy::Init(Actor* target)
     }
 }
 
-void ActionJumpBy::UpdateTween(Actor* target, float percent)
+void ActionJumpByEntity::UpdateTween(Actor* target, float percent)
 {
     float frac = fmod(percent * jump_count_, 1.f);
     float x    = displacement_.x * percent;
@@ -268,14 +266,12 @@ void ActionJumpBy::UpdateTween(Actor* target, float percent)
     prev_pos_ = new_pos;
 }
 
-ActionJumpToPtr ActionJumpTo::Create(Duration duration, const Point& distination, float height, int count,
-                                     EaseFunc ease)
+ActionJumpToEntityPtr ActionJumpToEntity::Create(Duration duration, const Point& distination, float height, int count)
 {
-    ActionJumpToPtr ptr = memory::New();
+    ActionJumpToEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
-        ptr->SetEaseFunc(ease);
         ptr->SetJumpHeight(height);
         ptr->SetJumpCount(count);
         ptr->SetDistination(distination);
@@ -283,16 +279,16 @@ ActionJumpToPtr ActionJumpTo::Create(Duration duration, const Point& distination
     return ptr;
 }
 
-ActionJumpTo::ActionJumpTo() {}
+ActionJumpToEntity::ActionJumpToEntity() {}
 
-ActionPtr ActionJumpTo::Clone() const
+ActionEntityPtr ActionJumpToEntity::Clone() const
 {
-    return DoClone(ActionJumpTo::Create(GetDuration(), distination_, height_, jump_count_));
+    return DoClone(ActionJumpToEntity::Create(GetDuration(), distination_, height_, jump_count_));
 }
 
-void ActionJumpTo::Init(Actor* target)
+void ActionJumpToEntity::Init(Actor* target)
 {
-    ActionJumpBy::Init(target);
+    ActionJumpByEntity::Init(target);
     displacement_ = distination_ - start_pos_;
 }
 
@@ -300,9 +296,9 @@ void ActionJumpTo::Init(Actor* target)
 // Scale Action
 //-------------------------------------------------------
 
-ActionScaleByPtr ActionScaleBy::Create(Duration duration, float scale_x, float scale_y)
+ActionScaleByEntityPtr ActionScaleByEntity::Create(Duration duration, float scale_x, float scale_y)
 {
-    ActionScaleByPtr ptr = memory::New();
+    ActionScaleByEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -312,7 +308,7 @@ ActionScaleByPtr ActionScaleBy::Create(Duration duration, float scale_x, float s
     return ptr;
 }
 
-ActionScaleBy::ActionScaleBy()
+ActionScaleByEntity::ActionScaleByEntity()
     : delta_x_(0.0f)
     , delta_y_(0.0f)
     , start_scale_x_(0.f)
@@ -320,7 +316,7 @@ ActionScaleBy::ActionScaleBy()
 {
 }
 
-void ActionScaleBy::Init(Actor* target)
+void ActionScaleByEntity::Init(Actor* target)
 {
     if (target)
     {
@@ -329,24 +325,24 @@ void ActionScaleBy::Init(Actor* target)
     }
 }
 
-void ActionScaleBy::UpdateTween(Actor* target, float percent)
+void ActionScaleByEntity::UpdateTween(Actor* target, float percent)
 {
     target->SetScale(Vec2{ start_scale_x_ + delta_x_ * percent, start_scale_y_ + delta_y_ * percent });
 }
 
-ActionPtr ActionScaleBy::Clone() const
+ActionEntityPtr ActionScaleByEntity::Clone() const
 {
-    return DoClone(ActionScaleBy::Create(GetDuration(), delta_x_, delta_y_));
+    return DoClone(ActionScaleByEntity::Create(GetDuration(), delta_x_, delta_y_));
 }
 
-ActionPtr ActionScaleBy::Reverse() const
+ActionEntityPtr ActionScaleByEntity::Reverse() const
 {
-    return DoClone(ActionScaleBy::Create(GetDuration(), -delta_x_, -delta_y_));
+    return DoClone(ActionScaleByEntity::Create(GetDuration(), -delta_x_, -delta_y_));
 }
 
-ActionScaleToPtr ActionScaleTo::Create(Duration duration, float scale_x, float scale_y)
+ActionScaleToEntityPtr ActionScaleToEntity::Create(Duration duration, float scale_x, float scale_y)
 {
-    ActionScaleToPtr ptr = memory::New();
+    ActionScaleToEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -356,20 +352,20 @@ ActionScaleToPtr ActionScaleTo::Create(Duration duration, float scale_x, float s
     return ptr;
 }
 
-ActionScaleTo::ActionScaleTo()
+ActionScaleToEntity::ActionScaleToEntity()
     : end_scale_x_(0.0f)
     , end_scale_y_(0.0f)
 {
 }
 
-ActionPtr ActionScaleTo::Clone() const
+ActionEntityPtr ActionScaleToEntity::Clone() const
 {
-    return DoClone(ActionScaleTo::Create(GetDuration(), end_scale_x_, end_scale_y_));
+    return DoClone(ActionScaleToEntity::Create(GetDuration(), end_scale_x_, end_scale_y_));
 }
 
-void ActionScaleTo::Init(Actor* target)
+void ActionScaleToEntity::Init(Actor* target)
 {
-    ActionScaleBy::Init(target);
+    ActionScaleByEntity::Init(target);
     delta_x_ = end_scale_x_ - start_scale_x_;
     delta_y_ = end_scale_y_ - start_scale_y_;
 }
@@ -378,9 +374,9 @@ void ActionScaleTo::Init(Actor* target)
 // Opacity Action
 //-------------------------------------------------------
 
-ActionFadeToPtr ActionFadeTo::Create(Duration duration, float opacity)
+ActionFadeToEntityPtr ActionFadeToEntity::Create(Duration duration, float opacity)
 {
-    ActionFadeToPtr ptr = memory::New();
+    ActionFadeToEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -389,14 +385,14 @@ ActionFadeToPtr ActionFadeTo::Create(Duration duration, float opacity)
     return ptr;
 }
 
-ActionFadeTo::ActionFadeTo()
+ActionFadeToEntity::ActionFadeToEntity()
     : delta_val_(0.0f)
     , start_val_(0.f)
     , end_val_(0.0f)
 {
 }
 
-void ActionFadeTo::Init(Actor* target)
+void ActionFadeToEntity::Init(Actor* target)
 {
     if (target)
     {
@@ -405,45 +401,23 @@ void ActionFadeTo::Init(Actor* target)
     }
 }
 
-void ActionFadeTo::UpdateTween(Actor* target, float percent)
+void ActionFadeToEntity::UpdateTween(Actor* target, float percent)
 {
     target->SetOpacity(start_val_ + delta_val_ * percent);
 }
 
-ActionPtr ActionFadeTo::Clone() const
+ActionEntityPtr ActionFadeToEntity::Clone() const
 {
-    return DoClone(ActionFadeTo::Create(GetDuration(), end_val_));
-}
-
-ActionFadeInPtr ActionFadeIn::Create(Duration duration)
-{
-    ActionFadeInPtr ptr = memory::New();
-    if (ptr)
-    {
-        ptr->SetDuration(duration);
-        ptr->SetTargetOpacity(1.0f);
-    }
-    return ptr;
-}
-
-ActionFadeOutPtr ActionFadeOut::Create(Duration duration)
-{
-    ActionFadeOutPtr ptr = memory::New();
-    if (ptr)
-    {
-        ptr->SetDuration(duration);
-        ptr->SetTargetOpacity(0.0f);
-    }
-    return ptr;
+    return DoClone(ActionFadeToEntity::Create(GetDuration(), end_val_));
 }
 
 //-------------------------------------------------------
 // Rotate Action
 //-------------------------------------------------------
 
-ActionRotateByPtr ActionRotateBy::Create(Duration duration, float rotation)
+ActionRotateByEntityPtr ActionRotateByEntity::Create(Duration duration, float rotation)
 {
-    ActionRotateByPtr ptr = memory::New();
+    ActionRotateByEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -452,13 +426,13 @@ ActionRotateByPtr ActionRotateBy::Create(Duration duration, float rotation)
     return ptr;
 }
 
-ActionRotateBy::ActionRotateBy()
+ActionRotateByEntity::ActionRotateByEntity()
     : start_val_(0.0f)
     , delta_val_(0.0f)
 {
 }
 
-void ActionRotateBy::Init(Actor* target)
+void ActionRotateByEntity::Init(Actor* target)
 {
     if (target)
     {
@@ -466,7 +440,7 @@ void ActionRotateBy::Init(Actor* target)
     }
 }
 
-void ActionRotateBy::UpdateTween(Actor* target, float percent)
+void ActionRotateByEntity::UpdateTween(Actor* target, float percent)
 {
     float rotation = start_val_ + delta_val_ * percent;
     if (rotation > 360.f)
@@ -475,19 +449,19 @@ void ActionRotateBy::UpdateTween(Actor* target, float percent)
     target->SetRotation(rotation);
 }
 
-ActionPtr ActionRotateBy::Clone() const
+ActionEntityPtr ActionRotateByEntity::Clone() const
 {
-    return DoClone(ActionRotateBy::Create(GetDuration(), delta_val_));
+    return DoClone(ActionRotateByEntity::Create(GetDuration(), delta_val_));
 }
 
-ActionPtr ActionRotateBy::Reverse() const
+ActionEntityPtr ActionRotateByEntity::Reverse() const
 {
-    return DoClone(ActionRotateBy::Create(GetDuration(), -delta_val_));
+    return DoClone(ActionRotateByEntity::Create(GetDuration(), -delta_val_));
 }
 
-ActionRotateToPtr ActionRotateTo::Create(Duration duration, float rotation)
+ActionRotateToEntityPtr ActionRotateToEntity::Create(Duration duration, float rotation)
 {
-    ActionRotateToPtr ptr = memory::New();
+    ActionRotateToEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -496,29 +470,29 @@ ActionRotateToPtr ActionRotateTo::Create(Duration duration, float rotation)
     return ptr;
 }
 
-ActionRotateTo::ActionRotateTo()
+ActionRotateToEntity::ActionRotateToEntity()
     : end_val_(0.0f)
 {
 }
 
-ActionPtr ActionRotateTo::Clone() const
+ActionEntityPtr ActionRotateToEntity::Clone() const
 {
-    return DoClone(ActionRotateTo::Create(GetDuration(), end_val_));
+    return DoClone(ActionRotateToEntity::Create(GetDuration(), end_val_));
 }
 
-void ActionRotateTo::Init(Actor* target)
+void ActionRotateToEntity::Init(Actor* target)
 {
-    ActionRotateBy::Init(target);
+    ActionRotateByEntity::Init(target);
     delta_val_ = end_val_ - start_val_;
 }
 
 //-------------------------------------------------------
-// ActionCustom
+// ActionCustomEntity
 //-------------------------------------------------------
 
-ActionCustomPtr ActionCustom::Create(Duration duration, TweenFunc tween_func)
+ActionCustomEntityPtr ActionCustomEntity::Create(Duration duration, ActionCustom::TweenFunc tween_func)
 {
-    ActionCustomPtr ptr = memory::New();
+    ActionCustomEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -527,23 +501,93 @@ ActionCustomPtr ActionCustom::Create(Duration duration, TweenFunc tween_func)
     return ptr;
 }
 
-ActionCustom::ActionCustom() {}
+ActionCustomEntity::ActionCustomEntity() {}
 
-ActionPtr ActionCustom::Clone() const
+ActionEntityPtr ActionCustomEntity::Clone() const
 {
-    return DoClone(ActionCustom::Create(GetDuration(), tween_func_));
+    return DoClone(ActionCustomEntity::Create(GetDuration(), tween_func_));
 }
 
-void ActionCustom::Init(Actor* target)
+void ActionCustomEntity::Init(Actor* target)
 {
     if (!tween_func_)
         this->Done();
 }
 
-void ActionCustom::UpdateTween(Actor* target, float percent)
+void ActionCustomEntity::UpdateTween(Actor* target, float percent)
 {
     if (tween_func_)
         tween_func_(target, percent);
 }
 
+ActionMoveBy::ActionMoveBy(Duration duration, const Vec2& displacement)
+{
+    SetEntity(ActionMoveByEntity::Create(duration, displacement));
+}
+
+ActionMoveTo::ActionMoveTo(Duration duration, const Point& distination)
+{
+    SetEntity(ActionMoveToEntity::Create(duration, distination));
+}
+
+ActionJumpBy::ActionJumpBy(Duration duration, const Vec2& displacement, float height, int count)
+{
+    SetEntity(ActionJumpByEntity::Create(duration, displacement, height, count));
+}
+
+ActionJumpTo::ActionJumpTo(Duration duration, const Point& distination, float height, int count)
+{
+    SetEntity(ActionJumpToEntity::Create(duration, distination, height, count));
+}
+
+ActionScaleBy::ActionScaleBy(Duration duration, float scale_x, float scale_y)
+{
+    SetEntity(ActionScaleByEntity::Create(duration, scale_x, scale_y));
+}
+
+ActionScaleBy::ActionScaleBy(Duration duration, Vec2 scale)
+{
+    SetEntity(ActionScaleByEntity::Create(duration, scale.x, scale.y));
+}
+
+ActionScaleTo::ActionScaleTo(Duration duration, float scale_x, float scale_y)
+{
+    SetEntity(ActionScaleToEntity::Create(duration, scale_x, scale_y));
+}
+
+ActionScaleTo::ActionScaleTo(Duration duration, Vec2 scale)
+{
+    SetEntity(ActionScaleToEntity::Create(duration, scale.x, scale.y));
+}
+
+ActionFadeTo::ActionFadeTo(Duration duration, float opacity)
+{
+    SetEntity(ActionFadeToEntity::Create(duration, opacity));
+}
+
+ActionFadeIn::ActionFadeIn(Duration duration)
+{
+    SetEntity(ActionFadeToEntity::Create(duration, 1.0f));
+}
+
+ActionFadeOut::ActionFadeOut(Duration duration)
+{
+    SetEntity(ActionFadeToEntity::Create(duration, 0.0f));
+}
+
+ActionRotateBy::ActionRotateBy(Duration duration, float rotation)
+{
+    SetEntity(ActionRotateByEntity::Create(duration, rotation));
+}
+
+ActionRotateTo::ActionRotateTo(Duration duration, float rotation)
+{
+    SetEntity(ActionRotateToEntity::Create(duration, rotation));
+}
+
+ActionCustom::ActionCustom(Duration duration, TweenFunc tween_func)
+{
+    SetEntity(ActionCustomEntity::Create(duration, tween_func));
+}
+
 }  // namespace kiwano
diff --git a/src/kiwano/2d/action/ActionTween.h b/src/kiwano/2d/action/ActionTween.h
index 626f5477..5da15354 100644
--- a/src/kiwano/2d/action/ActionTween.h
+++ b/src/kiwano/2d/action/ActionTween.h
@@ -66,19 +66,17 @@ struct Ease
     static KGE_API EaseFunc SineInOut;
 };
 
-KGE_DECLARE_SMART_PTR(ActionTween);
-KGE_DECLARE_SMART_PTR(ActionMoveBy);
-KGE_DECLARE_SMART_PTR(ActionMoveTo);
-KGE_DECLARE_SMART_PTR(ActionJumpBy);
-KGE_DECLARE_SMART_PTR(ActionJumpTo);
-KGE_DECLARE_SMART_PTR(ActionScaleBy);
-KGE_DECLARE_SMART_PTR(ActionScaleTo);
-KGE_DECLARE_SMART_PTR(ActionFadeTo);
-KGE_DECLARE_SMART_PTR(ActionFadeIn);
-KGE_DECLARE_SMART_PTR(ActionFadeOut);
-KGE_DECLARE_SMART_PTR(ActionRotateBy);
-KGE_DECLARE_SMART_PTR(ActionRotateTo);
-KGE_DECLARE_SMART_PTR(ActionCustom);
+KGE_DECLARE_SMART_PTR(ActionTweenEntity);
+KGE_DECLARE_SMART_PTR(ActionMoveByEntity);
+KGE_DECLARE_SMART_PTR(ActionMoveToEntity);
+KGE_DECLARE_SMART_PTR(ActionJumpByEntity);
+KGE_DECLARE_SMART_PTR(ActionJumpToEntity);
+KGE_DECLARE_SMART_PTR(ActionScaleByEntity);
+KGE_DECLARE_SMART_PTR(ActionScaleToEntity);
+KGE_DECLARE_SMART_PTR(ActionFadeToEntity);
+KGE_DECLARE_SMART_PTR(ActionRotateByEntity);
+KGE_DECLARE_SMART_PTR(ActionRotateToEntity);
+KGE_DECLARE_SMART_PTR(ActionCustomEntity);
 
 /**
  * \addtogroup Actions
@@ -86,17 +84,17 @@ KGE_DECLARE_SMART_PTR(ActionCustom);
  */
 
 /// \~chinese
-/// @brief 补间动画
-class KGE_API ActionTween : public Action
+/// @brief 补间动画实体
+class KGE_API ActionTweenEntity : public ActionEntity
 {
 public:
-    ActionTween();
+    ActionTweenEntity();
 
     /// \~chinese
     /// @brief 补间动画
     /// @param duration 动画时长
     /// @param func 动画速度缓动函数
-    ActionTween(Duration duration, EaseFunc ease);
+    ActionTweenEntity(Duration duration, EaseFunc ease);
 
     /// \~chinese
     /// @brief 获取动画时长
@@ -119,13 +117,43 @@ protected:
 
     virtual void UpdateTween(Actor* target, float percent) = 0;
 
-    ActionPtr DoClone(ActionTweenPtr to) const;
+    ActionEntityPtr DoClone(ActionTweenEntityPtr to) const;
 
 private:
     Duration dur_;
     EaseFunc ease_func_;
 };
 
+/// \~chinese
+/// @brief 补间动画
+struct ActionTween : Action
+{
+    /// \~chinese
+    /// @brief 设置缓动函数
+    inline ActionTween& Ease(EaseFunc ease)
+    {
+        tween_ptr->SetEaseFunc(ease);
+        return (*this);
+    }
+
+protected:
+    ActionTween() = default;
+
+    inline ActionTween(ActionTweenEntityPtr ptr)
+        : Action(ptr.Get())
+        , tween_ptr(ptr)
+    {
+    }
+
+    inline void SetEntity(ActionEntityPtr tween_ptr)
+    {
+        this->ptr       = tween_ptr;
+        this->tween_ptr = (ActionTweenEntity*)tween_ptr.Get();
+    }
+
+    ActionTweenEntityPtr tween_ptr;
+};
+
 /// \~chinese
 /// @brief 相对位移动画
 class KGE_API ActionMoveBy : public ActionTween
@@ -135,9 +163,21 @@ public:
     /// @brief 创建相对位移动画
     /// @param duration 动画时长
     /// @param displacement 位移向量
-    static ActionMoveByPtr Create(Duration duration, const Vec2& displacement);
+    ActionMoveBy(Duration duration, const Vec2& displacement);
+};
 
-    ActionMoveBy();
+/// \~chinese
+/// @brief 相对位移动画实体
+class KGE_API ActionMoveByEntity : public ActionTweenEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建相对位移动画
+    /// @param duration 动画时长
+    /// @param displacement 位移向量
+    static ActionMoveByEntityPtr Create(Duration duration, const Vec2& displacement);
+
+    ActionMoveByEntity();
 
     /// \~chinese
     /// @brief 获取位移向量
@@ -149,11 +189,11 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override;
+    ActionEntityPtr Reverse() const override;
 
 protected:
     void Init(Actor* target) override;
@@ -168,16 +208,28 @@ protected:
 
 /// \~chinese
 /// @brief 位移动画
-class KGE_API ActionMoveTo : public ActionMoveBy
+class KGE_API ActionMoveTo : public ActionTween
 {
 public:
     /// \~chinese
     /// @brief 创建位移动画
     /// @param duration 动画时长
     /// @param distination 目的坐标
-    static ActionMoveToPtr Create(Duration duration, const Point& distination);
+    ActionMoveTo(Duration duration, const Point& distination);
+};
 
-    ActionMoveTo();
+/// \~chinese
+/// @brief 位移动画实体
+class KGE_API ActionMoveToEntity : public ActionMoveByEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建位移动画
+    /// @param duration 动画时长
+    /// @param distination 目的坐标
+    static ActionMoveToEntityPtr Create(Duration duration, const Point& distination);
+
+    ActionMoveToEntity();
 
     /// \~chinese
     /// @brief 获取目的坐标
@@ -189,13 +241,13 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    virtual ActionPtr Reverse() const override
+    virtual ActionEntityPtr Reverse() const override
     {
-        KGE_ERRORF("Reverse() not supported in ActionMoveTo");
+        KGE_ERRORF("Reverse() not supported in ActionMoveToEntity");
         return nullptr;
     }
 
@@ -217,10 +269,23 @@ public:
     /// @param displacement 跳跃位移向量
     /// @param height 跳跃高度
     /// @param count 跳跃次数
-    static ActionJumpByPtr Create(Duration duration, const Vec2& displacement, float height, int count = 1,
-                                  EaseFunc ease = nullptr);
+    ActionJumpBy(Duration duration, const Vec2& displacement, float height, int count = 1);
+};
 
-    ActionJumpBy();
+/// \~chinese
+/// @brief 相对跳跃动画实体
+class KGE_API ActionJumpByEntity : public ActionTweenEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建相对跳跃动画
+    /// @param duration 动画时长
+    /// @param displacement 跳跃位移向量
+    /// @param height 跳跃高度
+    /// @param count 跳跃次数
+    static ActionJumpByEntityPtr Create(Duration duration, const Vec2& displacement, float height, int count = 1);
+
+    ActionJumpByEntity();
 
     /// \~chinese
     /// @brief 获取跳跃位移
@@ -248,11 +313,11 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override;
+    ActionEntityPtr Reverse() const override;
 
 protected:
     void Init(Actor* target) override;
@@ -269,7 +334,7 @@ protected:
 
 /// \~chinese
 /// @brief 跳跃动画
-class KGE_API ActionJumpTo : public ActionJumpBy
+class KGE_API ActionJumpTo : public ActionTween
 {
 public:
     /// \~chinese
@@ -278,10 +343,23 @@ public:
     /// @param distination 目的坐标
     /// @param height 跳跃高度
     /// @param count 跳跃次数
-    static ActionJumpToPtr Create(Duration duration, const Point& distination, float height, int count = 1,
-                                  EaseFunc ease = nullptr);
+    ActionJumpTo(Duration duration, const Point& distination, float height, int count = 1);
+};
 
-    ActionJumpTo();
+/// \~chinese
+/// @brief 跳跃动画实体
+class KGE_API ActionJumpToEntity : public ActionJumpByEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建跳跃动画
+    /// @param duration 动画时长
+    /// @param distination 目的坐标
+    /// @param height 跳跃高度
+    /// @param count 跳跃次数
+    static ActionJumpToEntityPtr Create(Duration duration, const Point& distination, float height, int count = 1);
+
+    ActionJumpToEntity();
 
     /// \~chinese
     /// @brief 获取目的坐标
@@ -293,13 +371,13 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    virtual ActionPtr Reverse() const override
+    virtual ActionEntityPtr Reverse() const override
     {
-        KGE_ERRORF("Reverse() not supported in ActionJumpTo");
+        KGE_ERRORF("Reverse() not supported in ActionJumpToEntity");
         return nullptr;
     }
 
@@ -320,9 +398,28 @@ public:
     /// @param duration 动画时长
     /// @param scale_x 横向缩放相对变化值
     /// @param scale_y 纵向缩放相对变化值
-    static ActionScaleByPtr Create(Duration duration, float scale_x, float scale_y);
+    ActionScaleBy(Duration duration, float scale_x, float scale_y);
 
-    ActionScaleBy();
+    /// \~chinese
+    /// @brief 创建相对缩放动画
+    /// @param duration 动画时长
+    /// @param scale 缩放相对变化值
+    ActionScaleBy(Duration duration, Vec2 scale);
+};
+
+/// \~chinese
+/// @brief 相对缩放动画实体
+class KGE_API ActionScaleByEntity : public ActionTweenEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建相对缩放动画
+    /// @param duration 动画时长
+    /// @param scale_x 横向缩放相对变化值
+    /// @param scale_y 纵向缩放相对变化值
+    static ActionScaleByEntityPtr Create(Duration duration, float scale_x, float scale_y);
+
+    ActionScaleByEntity();
 
     /// \~chinese
     /// @brief 获取横向缩放相对变化值
@@ -342,11 +439,11 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override;
+    ActionEntityPtr Reverse() const override;
 
 protected:
     void Init(Actor* target) override;
@@ -362,7 +459,7 @@ protected:
 
 /// \~chinese
 /// @brief 缩放动画
-class KGE_API ActionScaleTo : public ActionScaleBy
+class KGE_API ActionScaleTo : public ActionTween
 {
 public:
     /// \~chinese
@@ -370,9 +467,28 @@ public:
     /// @param duration 动画时长
     /// @param scale_x 横向缩放目标值
     /// @param scale_y 纵向缩放目标值
-    static ActionScaleToPtr Create(Duration duration, float scale_x, float scale_y);
+    ActionScaleTo(Duration duration, float scale_x, float scale_y);
 
-    ActionScaleTo();
+    /// \~chinese
+    /// @brief 创建缩放动画
+    /// @param duration 动画时长
+    /// @param scale 缩放目标值
+    ActionScaleTo(Duration duration, Vec2 scale);
+};
+
+/// \~chinese
+/// @brief 缩放动画实体
+class KGE_API ActionScaleToEntity : public ActionScaleByEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建缩放动画
+    /// @param duration 动画时长
+    /// @param scale_x 横向缩放目标值
+    /// @param scale_y 纵向缩放目标值
+    static ActionScaleToEntityPtr Create(Duration duration, float scale_x, float scale_y);
+
+    ActionScaleToEntity();
 
     /// \~chinese
     /// @brief 获取横向缩放目标值
@@ -392,13 +508,13 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    virtual ActionPtr Reverse() const override
+    virtual ActionEntityPtr Reverse() const override
     {
-        KGE_ERRORF("Reverse() not supported in ActionScaleTo");
+        KGE_ERRORF("Reverse() not supported in ActionScaleToEntity");
         return nullptr;
     }
 
@@ -419,9 +535,43 @@ public:
     /// @brief 创建透明度渐变动画
     /// @param duration 动画时长
     /// @param opacity 目标透明度
-    static ActionFadeToPtr Create(Duration duration, float opacity);
+    ActionFadeTo(Duration duration, float opacity);
+};
 
-    ActionFadeTo();
+/// \~chinese
+/// @brief 淡入动画
+class KGE_API ActionFadeIn : public ActionTween
+{
+public:
+    /// \~chinese
+    /// @brief 创建淡入动画
+    /// @param duration 动画时长
+    ActionFadeIn(Duration duration);
+};
+
+/// \~chinese
+/// @brief 淡出动画
+class KGE_API ActionFadeOut : public ActionTween
+{
+public:
+    /// \~chinese
+    /// @brief 创建淡出动画
+    /// @param duration 动画时长
+    ActionFadeOut(Duration duration);
+};
+
+/// \~chinese
+/// @brief 透明度渐变动画实体
+class KGE_API ActionFadeToEntity : public ActionTweenEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建透明度渐变动画
+    /// @param duration 动画时长
+    /// @param opacity 目标透明度
+    static ActionFadeToEntityPtr Create(Duration duration, float opacity);
+
+    ActionFadeToEntity();
 
     /// \~chinese
     /// @brief 获取目标透明度
@@ -433,13 +583,13 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    virtual ActionPtr Reverse() const override
+    virtual ActionEntityPtr Reverse() const override
     {
-        KGE_ERRORF("Reverse() not supported in ActionFadeTo");
+        KGE_ERRORF("Reverse() not supported in ActionFadeToEntity");
         return nullptr;
     }
 
@@ -454,28 +604,6 @@ private:
     float end_val_;
 };
 
-/// \~chinese
-/// @brief 淡入动画
-class KGE_API ActionFadeIn : public ActionFadeTo
-{
-public:
-    /// \~chinese
-    /// @brief 创建淡入动画
-    /// @param duration 动画时长
-    static ActionFadeInPtr Create(Duration duration);
-};
-
-/// \~chinese
-/// @brief 淡出动画
-class KGE_API ActionFadeOut : public ActionFadeTo
-{
-public:
-    /// \~chinese
-    /// @brief 创建淡出动画
-    /// @param duration 动画时长
-    static ActionFadeOutPtr Create(Duration duration);
-};
-
 /// \~chinese
 /// @brief 相对旋转动画
 class KGE_API ActionRotateBy : public ActionTween
@@ -485,9 +613,21 @@ public:
     /// @brief 创建相对旋转动画
     /// @param duration 动画时长
     /// @param rotation 角度相对变化值
-    static ActionRotateByPtr Create(Duration duration, float rotation);
+    ActionRotateBy(Duration duration, float rotation);
+};
 
-    ActionRotateBy();
+/// \~chinese
+/// @brief 相对旋转动画实体
+class KGE_API ActionRotateByEntity : public ActionTweenEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建相对旋转动画
+    /// @param duration 动画时长
+    /// @param rotation 角度相对变化值
+    static ActionRotateByEntityPtr Create(Duration duration, float rotation);
+
+    ActionRotateByEntity();
 
     /// \~chinese
     /// @brief 获取角度相对变化值
@@ -499,11 +639,11 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override;
+    ActionEntityPtr Reverse() const override;
 
 protected:
     void Init(Actor* target) override;
@@ -517,16 +657,28 @@ protected:
 
 /// \~chinese
 /// @brief 旋转动画
-class KGE_API ActionRotateTo : public ActionRotateBy
+class KGE_API ActionRotateTo : public ActionTween
 {
 public:
     /// \~chinese
     /// @brief 创建旋转动画
     /// @param duration 动画时长
     /// @param rotation 目标角度
-    static ActionRotateToPtr Create(Duration duration, float rotation);
+    ActionRotateTo(Duration duration, float rotation);
+};
 
-    ActionRotateTo();
+/// \~chinese
+/// @brief 旋转动画实体
+class KGE_API ActionRotateToEntity : public ActionRotateByEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建旋转动画
+    /// @param duration 动画时长
+    /// @param rotation 目标角度
+    static ActionRotateToEntityPtr Create(Duration duration, float rotation);
+
+    ActionRotateToEntity();
 
     /// \~chinese
     /// @brief 获取目标角度
@@ -538,13 +690,13 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    virtual ActionPtr Reverse() const override
+    virtual ActionEntityPtr Reverse() const override
     {
-        KGE_ERRORF("Reverse() not supported in ActionRotateTo");
+        KGE_ERRORF("Reverse() not supported in ActionRotateToEntity");
         return nullptr;
     }
 
@@ -569,27 +721,39 @@ public:
     /// @brief 创建自定义动画
     /// @param duration 动画时长
     /// @param tween_func 动画回调函数
-    static ActionCustomPtr Create(Duration duration, TweenFunc tween_func);
+    ActionCustom(Duration duration, TweenFunc tween_func);
+};
 
-    ActionCustom();
+/// \~chinese
+/// @brief 自定义动画实体
+class KGE_API ActionCustomEntity : public ActionTweenEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建自定义动画
+    /// @param duration 动画时长
+    /// @param tween_func 动画回调函数
+    static ActionCustomEntityPtr Create(Duration duration, ActionCustom::TweenFunc tween_func);
+
+    ActionCustomEntity();
 
     /// \~chinese
     /// @brief 获取动画回调函数
-    TweenFunc GetTweenFunc() const;
+    ActionCustom::TweenFunc GetTweenFunc() const;
 
     /// \~chinese
     /// @brief 设置动画回调函数
-    void SetTweenFunc(const TweenFunc& tween_func);
+    void SetTweenFunc(const ActionCustom::TweenFunc& tween_func);
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override
+    ActionEntityPtr Reverse() const override
     {
-        KGE_ERRORF("Reverse() not supported in ActionCustom");
+        KGE_ERRORF("Reverse() not supported in ActionCustomEntity");
         return nullptr;
     }
 
@@ -599,167 +763,167 @@ protected:
     void UpdateTween(Actor* target, float percent) override;
 
 private:
-    TweenFunc tween_func_;
+    ActionCustom::TweenFunc tween_func_;
 };
 
 /** @} */
 
-inline const EaseFunc& ActionTween::GetEaseFunc() const
+inline const EaseFunc& ActionTweenEntity::GetEaseFunc() const
 {
     return ease_func_;
 }
 
-inline Duration ActionTween::GetDuration() const
+inline Duration ActionTweenEntity::GetDuration() const
 {
     return dur_;
 }
 
-inline void ActionTween::SetDuration(Duration duration)
+inline void ActionTweenEntity::SetDuration(Duration duration)
 {
     dur_ = duration;
 }
 
-inline void ActionTween::SetEaseFunc(const EaseFunc& func)
+inline void ActionTweenEntity::SetEaseFunc(const EaseFunc& func)
 {
     ease_func_ = func;
 }
 
-inline Vec2 ActionMoveBy::GetDisplacement() const
+inline Vec2 ActionMoveByEntity::GetDisplacement() const
 {
     return displacement_;
 }
 
-inline void ActionMoveBy::SetDisplacement(const Vec2& displacement)
+inline void ActionMoveByEntity::SetDisplacement(const Vec2& displacement)
 {
     displacement_ = displacement;
 }
 
-inline Point ActionMoveTo::GetDistination() const
+inline Point ActionMoveToEntity::GetDistination() const
 {
     return distination_;
 }
 
-inline void ActionMoveTo::SetDistination(const Point& distination)
+inline void ActionMoveToEntity::SetDistination(const Point& distination)
 {
     distination_ = distination;
 }
 
-inline Vec2 ActionJumpBy::GetDisplacement() const
+inline Vec2 ActionJumpByEntity::GetDisplacement() const
 {
     return displacement_;
 }
 
-inline float ActionJumpBy::GetJumpHeight() const
+inline float ActionJumpByEntity::GetJumpHeight() const
 {
     return height_;
 }
 
-inline int ActionJumpBy::GetJumpCount() const
+inline int ActionJumpByEntity::GetJumpCount() const
 {
     return jump_count_;
 }
 
-inline void ActionJumpBy::SetDisplacement(const Vec2& displacement)
+inline void ActionJumpByEntity::SetDisplacement(const Vec2& displacement)
 {
     displacement_ = displacement;
 }
 
-inline void ActionJumpBy::SetJumpHeight(float height)
+inline void ActionJumpByEntity::SetJumpHeight(float height)
 {
     height_ = height;
 }
 
-inline void ActionJumpBy::SetJumpCount(int count)
+inline void ActionJumpByEntity::SetJumpCount(int count)
 {
     jump_count_ = count;
 }
 
-inline Point ActionJumpTo::GetDistination() const
+inline Point ActionJumpToEntity::GetDistination() const
 {
     return distination_;
 }
 
-inline void ActionJumpTo::SetDistination(const Point& distination)
+inline void ActionJumpToEntity::SetDistination(const Point& distination)
 {
     distination_ = distination;
 }
 
-inline float ActionScaleBy::GetScaleX() const
+inline float ActionScaleByEntity::GetScaleX() const
 {
     return delta_x_;
 }
 
-inline float ActionScaleBy::GetScaleY() const
+inline float ActionScaleByEntity::GetScaleY() const
 {
     return delta_y_;
 }
 
-inline void ActionScaleBy::SetScaleX(float scale_x)
+inline void ActionScaleByEntity::SetScaleX(float scale_x)
 {
     delta_x_ = scale_x;
 }
 
-inline void ActionScaleBy::SetScaleY(float scale_y)
+inline void ActionScaleByEntity::SetScaleY(float scale_y)
 {
     delta_y_ = scale_y;
 }
 
-inline float ActionScaleTo::GetTargetScaleX() const
+inline float ActionScaleToEntity::GetTargetScaleX() const
 {
     return end_scale_x_;
 }
 
-inline float ActionScaleTo::GetTargetScaleY() const
+inline float ActionScaleToEntity::GetTargetScaleY() const
 {
     return end_scale_y_;
 }
 
-inline void ActionScaleTo::SetTargetScaleX(float scale_x)
+inline void ActionScaleToEntity::SetTargetScaleX(float scale_x)
 {
     end_scale_x_ = scale_x;
 }
 
-inline void ActionScaleTo::SetTargetScaleY(float scale_y)
+inline void ActionScaleToEntity::SetTargetScaleY(float scale_y)
 {
     end_scale_y_ = scale_y;
 }
 
-inline float ActionFadeTo::GetTargetOpacity() const
+inline float ActionFadeToEntity::GetTargetOpacity() const
 {
     return end_val_;
 }
 
-inline void ActionFadeTo::SetTargetOpacity(float opacity)
+inline void ActionFadeToEntity::SetTargetOpacity(float opacity)
 {
     end_val_ = opacity;
 }
 
-inline float ActionRotateBy::GetRotation() const
+inline float ActionRotateByEntity::GetRotation() const
 {
     return delta_val_;
 }
 
-inline void ActionRotateBy::SetRotation(float rotation)
+inline void ActionRotateByEntity::SetRotation(float rotation)
 {
     delta_val_ = rotation;
 }
 
-inline float ActionRotateTo::GetTargetRotation() const
+inline float ActionRotateToEntity::GetTargetRotation() const
 {
     return end_val_;
 }
 
-inline void ActionRotateTo::SetTargetRotation(float rotation)
+inline void ActionRotateToEntity::SetTargetRotation(float rotation)
 {
     end_val_ = rotation;
 }
 
-inline ActionCustom::TweenFunc ActionCustom::GetTweenFunc() const
+inline ActionCustom::TweenFunc ActionCustomEntity::GetTweenFunc() const
 {
     return tween_func_;
 }
 
-inline void ActionCustom::SetTweenFunc(const TweenFunc& tween_func)
+inline void ActionCustomEntity::SetTweenFunc(const ActionCustom::TweenFunc& tween_func)
 {
     tween_func_ = tween_func;
 }
diff --git a/src/kiwano/2d/action/ActionWalk.cpp b/src/kiwano/2d/action/ActionWalk.cpp
index c286e764..8a1eb12c 100644
--- a/src/kiwano/2d/action/ActionWalk.cpp
+++ b/src/kiwano/2d/action/ActionWalk.cpp
@@ -24,9 +24,14 @@
 namespace kiwano
 {
 
-ActionWalkPtr ActionWalk::Create(Duration duration, ShapePtr path, bool rotating, float start, float end)
+ActionWalk::ActionWalk(Duration duration, ShapePtr path, bool rotating, float start, float end)
 {
-    ActionWalkPtr ptr = memory::New();
+    SetEntity(ActionWalkEntity::Create(duration, path, rotating, start, end));
+}
+
+ActionWalkEntityPtr ActionWalkEntity::Create(Duration duration, ShapePtr path, bool rotating, float start, float end)
+{
+    ActionWalkEntityPtr ptr = memory::New();
     if (ptr)
     {
         ptr->SetDuration(duration);
@@ -38,7 +43,7 @@ ActionWalkPtr ActionWalk::Create(Duration duration, ShapePtr path, bool rotating
     return ptr;
 }
 
-ActionWalk::ActionWalk()
+ActionWalkEntity::ActionWalkEntity()
     : start_(0.0f)
     , end_(1.0f)
     , rotating_(false)
@@ -46,17 +51,17 @@ ActionWalk::ActionWalk()
 {
 }
 
-ActionPtr ActionWalk::Clone() const
+ActionEntityPtr ActionWalkEntity::Clone() const
 {
-    return DoClone(ActionWalk::Create(GetDuration(), path_, rotating_, start_, end_));
+    return DoClone(ActionWalkEntity::Create(GetDuration(), path_, rotating_, start_, end_));
 }
 
-ActionPtr ActionWalk::Reverse() const
+ActionEntityPtr ActionWalkEntity::Reverse() const
 {
-    return DoClone(ActionWalk::Create(GetDuration(), path_, rotating_, end_, start_));
+    return DoClone(ActionWalkEntity::Create(GetDuration(), path_, rotating_, end_, start_));
 }
 
-void ActionWalk::Init(Actor* target)
+void ActionWalkEntity::Init(Actor* target)
 {
     if (!path_ || !path_->IsValid())
     {
@@ -68,7 +73,7 @@ void ActionWalk::Init(Actor* target)
     length_    = path_->GetLength();
 }
 
-void ActionWalk::UpdateTween(Actor* target, float percent)
+void ActionWalkEntity::UpdateTween(Actor* target, float percent)
 {
     float distance = length_ * std::min(std::max((end_ - start_) * percent + start_, 0.f), 1.f);
 
diff --git a/src/kiwano/2d/action/ActionWalk.h b/src/kiwano/2d/action/ActionWalk.h
index 97241db0..4f373f22 100644
--- a/src/kiwano/2d/action/ActionWalk.h
+++ b/src/kiwano/2d/action/ActionWalk.h
@@ -25,7 +25,7 @@
 
 namespace kiwano
 {
-KGE_DECLARE_SMART_PTR(ActionWalk);
+KGE_DECLARE_SMART_PTR(ActionWalkEntity);
 
 /**
  * \addtogroup Actions
@@ -44,10 +44,25 @@ public:
     /// @param rotating 是否沿路径切线方向旋转
     /// @param start 路径起点(百分比)
     /// @param end 路径终点(百分比)
-    static ActionWalkPtr Create(Duration duration, ShapePtr path, bool rotating = false, float start = 0.f,
-                                float end = 1.f);
+    ActionWalk(Duration duration, ShapePtr path, bool rotating = false, float start = 0.f, float end = 1.f);
+};
 
-    ActionWalk();
+/// \~chinese
+/// @brief 路径行走动画实体
+class KGE_API ActionWalkEntity : public ActionTweenEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建路径行走动画
+    /// @param duration 持续时长
+    /// @param path 路径形状
+    /// @param rotating 是否沿路径切线方向旋转
+    /// @param start 路径起点(百分比)
+    /// @param end 路径终点(百分比)
+    static ActionWalkEntityPtr Create(Duration duration, ShapePtr path, bool rotating = false, float start = 0.f,
+                                      float end = 1.f);
+
+    ActionWalkEntity();
 
     /// \~chinese
     /// @brief 获取路线
@@ -83,11 +98,11 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override;
+    ActionEntityPtr Reverse() const override;
 
 protected:
     void Init(Actor* target) override;
@@ -105,42 +120,42 @@ private:
 
 /** @} */
 
-inline ShapePtr ActionWalk::GetPath() const
+inline ShapePtr ActionWalkEntity::GetPath() const
 {
     return path_;
 }
 
-inline bool ActionWalk::IsRotating() const
+inline bool ActionWalkEntity::IsRotating() const
 {
     return rotating_;
 }
 
-inline float ActionWalk::GetStartValue() const
+inline float ActionWalkEntity::GetStartValue() const
 {
     return start_;
 }
 
-inline float ActionWalk::GetEndValue() const
+inline float ActionWalkEntity::GetEndValue() const
 {
     return end_;
 }
 
-inline void ActionWalk::SetPath(ShapePtr path)
+inline void ActionWalkEntity::SetPath(ShapePtr path)
 {
     path_ = path;
 }
 
-inline void ActionWalk::SetRotating(bool rotating)
+inline void ActionWalkEntity::SetRotating(bool rotating)
 {
     rotating_ = rotating;
 }
 
-inline void ActionWalk::SetStartValue(float start)
+inline void ActionWalkEntity::SetStartValue(float start)
 {
     start_ = start;
 }
 
-inline void ActionWalk::SetEndValue(float end)
+inline void ActionWalkEntity::SetEndValue(float end)
 {
     end_ = end;
 }
diff --git a/src/kiwano/2d/action/Animation.cpp b/src/kiwano/2d/action/Animation.cpp
index bb52344a..3e494f48 100644
--- a/src/kiwano/2d/action/Animation.cpp
+++ b/src/kiwano/2d/action/Animation.cpp
@@ -25,37 +25,42 @@
 namespace kiwano
 {
 
-AnimationPtr Animation::Create(Duration duration, FrameSequencePtr frame_seq)
+Animation::Animation(Duration dur, FrameSequencePtr frame_seq)
 {
-    AnimationPtr ptr = memory::New();
+    SetEntity(AnimationEntity::Create(dur, frame_seq));
+}
+
+AnimationEntityPtr AnimationEntity::Create(Duration dur, FrameSequencePtr frame_seq)
+{
+    AnimationEntityPtr ptr = memory::New();
     if (ptr)
     {
-        ptr->SetDuration(duration);
+        ptr->SetDuration(dur);
         ptr->SetFrameSequence(frame_seq);
     }
     return ptr;
 }
 
-Animation::Animation()
+AnimationEntity::AnimationEntity()
     : frame_seq_(nullptr)
 {
 }
 
-Animation::~Animation() {}
+AnimationEntity::~AnimationEntity() {}
 
-FrameSequencePtr Animation::GetFrameSequence() const
+FrameSequencePtr AnimationEntity::GetFrameSequence() const
 {
     return frame_seq_;
 }
 
-void Animation::SetFrameSequence(FrameSequencePtr frame_seq)
+void AnimationEntity::SetFrameSequence(FrameSequencePtr frame_seq)
 {
     frame_seq_ = frame_seq;
 }
 
-void Animation::Init(Actor* target)
+void AnimationEntity::Init(Actor* target)
 {
-    KGE_ASSERT(frame_seq_ && "Animation::Init() failed: FrameSequence is NULL!");
+    KGE_ASSERT(frame_seq_ && "AnimationEntity::Init() failed: FrameSequence is NULL!");
     if (!frame_seq_ || frame_seq_->GetFrames().empty())
     {
         Done();
@@ -63,7 +68,7 @@ void Animation::Init(Actor* target)
     }
 
     auto sprite_target = dynamic_cast(target);
-    KGE_ASSERT(sprite_target && "Animation only supports Sprites!");
+    KGE_ASSERT(sprite_target && "AnimationEntity only supports Sprites!");
 
     if (sprite_target && frame_seq_)
     {
@@ -71,7 +76,7 @@ void Animation::Init(Actor* target)
     }
 }
 
-void Animation::UpdateTween(Actor* target, float percent)
+void AnimationEntity::UpdateTween(Actor* target, float percent)
 {
     auto sprite_target = dynamic_cast(target);
 
@@ -85,23 +90,23 @@ void Animation::UpdateTween(Actor* target, float percent)
     }
 }
 
-ActionPtr Animation::Clone() const
+ActionEntityPtr AnimationEntity::Clone() const
 {
     if (frame_seq_)
     {
-        return DoClone(Animation::Create(GetDuration(), frame_seq_));
+        return DoClone(AnimationEntity::Create(GetDuration(), frame_seq_));
     }
     return nullptr;
 }
 
-ActionPtr Animation::Reverse() const
+ActionEntityPtr AnimationEntity::Reverse() const
 {
     if (frame_seq_)
     {
         FrameSequencePtr frames = frame_seq_->Reverse();
         if (frames)
         {
-            return DoClone(Animation::Create(GetDuration(), frames));
+            return DoClone(AnimationEntity::Create(GetDuration(), frames));
         }
     }
     return nullptr;
diff --git a/src/kiwano/2d/action/Animation.h b/src/kiwano/2d/action/Animation.h
index 7e991c72..a161a9a5 100644
--- a/src/kiwano/2d/action/Animation.h
+++ b/src/kiwano/2d/action/Animation.h
@@ -24,7 +24,8 @@
 
 namespace kiwano
 {
-KGE_DECLARE_SMART_PTR(Animation);
+
+KGE_DECLARE_SMART_PTR(AnimationEntity);
 
 /**
  * \addtogroup Actions
@@ -38,13 +39,25 @@ class KGE_API Animation : public ActionTween
 public:
     /// \~chinese
     /// @brief 创建帧动画
-    /// @param duration 动画时长
-    /// @param[in] frame_seq 序列帧
-    static AnimationPtr Create(Duration duration, FrameSequencePtr frame_seq);
+    /// @param dur 动画时长
+    /// @param frame_seq 序列帧
+    Animation(Duration dur, FrameSequencePtr frame_seq);
+};
 
-    Animation();
+/// \~chinese
+/// @brief 帧动画实体
+class KGE_API AnimationEntity : public ActionTweenEntity
+{
+public:
+    /// \~chinese
+    /// @brief 创建帧动画
+    /// @param dur 动画时长
+    /// @param frame_seq 序列帧
+    static AnimationEntityPtr Create(Duration dur, FrameSequencePtr frame_seq);
 
-    virtual ~Animation();
+    AnimationEntity();
+
+    virtual ~AnimationEntity();
 
     /// \~chinese
     /// @brief 获取序列帧
@@ -57,11 +70,11 @@ public:
 
     /// \~chinese
     /// @brief 获取该动画的拷贝对象
-    ActionPtr Clone() const override;
+    ActionEntityPtr Clone() const override;
 
     /// \~chinese
     /// @brief 获取该动画的倒转
-    ActionPtr Reverse() const override;
+    ActionEntityPtr Reverse() const override;
 
 protected:
     void Init(Actor* target) override;
diff --git a/src/kiwano/core/Time.cpp b/src/kiwano/core/Time.cpp
index 33b120d8..eafaccf0 100644
--- a/src/kiwano/core/Time.cpp
+++ b/src/kiwano/core/Time.cpp
@@ -250,11 +250,12 @@ String Duration::ToString() const
         return String("0s");
     }
 
-    String   result;
+    StringStream stream;
+
     int64_t total_ms = milliseconds_;
     if (total_ms < 0)
     {
-        result.append("-");
+        stream << "-";
         total_ms = -total_ms;
     }
 
@@ -265,23 +266,22 @@ String Duration::ToString() const
 
     if (hour)
     {
-        result.append(std::to_string(hour)).append("h");
-        result.append(std::to_string(min)).append("m");
+        stream << hour << 'h' << min << 'm';
     }
     else if (min)
     {
-        result.append(std::to_string(min)).append("m");
+        stream << min << 'm';
     }
 
     if (ms != 0)
     {
-        result.append(std::to_string(static_cast(sec + ms) / 1000.f)).append("s");
+        stream << float(sec) + float(ms) / 1000.f << 's';
     }
     else if (sec != 0)
     {
-        result.append(std::to_string(sec)).append("s");
+        stream << sec << 's';
     }
-    return result;
+    return stream.str();
 }
 
 bool Duration::operator==(const Duration& other) const
diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h
index d4630520..e8671d7a 100644
--- a/src/kiwano/kiwano.h
+++ b/src/kiwano/kiwano.h
@@ -107,11 +107,10 @@
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
+#include 
 
 //
 // platform
diff --git a/src/kiwano/utils/Task.cpp b/src/kiwano/utils/Task.cpp
index 89f25f24..dd7dc34e 100644
--- a/src/kiwano/utils/Task.cpp
+++ b/src/kiwano/utils/Task.cpp
@@ -62,8 +62,31 @@ Task::Task()
 {
 }
 
+void Task::Start()
+{
+    if (!running_)
+    {
+        running_ = true;
+        if (ticker_)
+            ticker_->Resume();
+    }
+}
+
+void Task::Stop()
+{
+    if (running_)
+    {
+        running_ = false;
+        if (ticker_)
+            ticker_->Pause();
+    }
+}
+
 void Task::Update(Duration dt)
 {
+    if (!running_ || removeable_)
+        return;
+
     if (!ticker_ || ticker_->GetTotalTickCount() == 0)
     {
         Remove();
diff --git a/src/kiwano/utils/Task.h b/src/kiwano/utils/Task.h
index 09b27dba..d9c4ca66 100644
--- a/src/kiwano/utils/Task.h
+++ b/src/kiwano/utils/Task.h
@@ -129,16 +129,6 @@ private:
     Callback  callback_;
 };
 
-inline void Task::Start()
-{
-    running_ = true;
-}
-
-inline void Task::Stop()
-{
-    running_ = false;
-}
-
 inline void Task::Remove()
 {
     removeable_ = true;
@@ -162,6 +152,13 @@ inline TickerPtr Task::GetTicker() const
 inline void Task::SetTicker(TickerPtr ticker)
 {
     ticker_ = ticker;
+    if (ticker_)
+    {
+        if (running_)
+            ticker_->Resume();
+        else
+            ticker_->Pause();
+    }
 }
 
 inline Task::Callback Task::GetCallback() const