diff --git a/Bin/Data/Scripts/NinjaSnowWar.as b/Bin/Data/Scripts/NinjaSnowWar.as
index 3b2ecc8cf..d942abd2e 100644
--- a/Bin/Data/Scripts/NinjaSnowWar.as
+++ b/Bin/Data/Scripts/NinjaSnowWar.as
@@ -180,7 +180,7 @@ void updateControls()
     Entity@ playerEntity = gameScene.getEntity("ObjPlayer");
     if (@playerEntity == null)
         return;
-    
+
     ScriptInstance@ instance = playerEntity.getComponent("ScriptInstance");
     GameObject@ object = cast<GameObject>(instance.getScriptObject());
     object.setControls(playerControls);
@@ -205,7 +205,7 @@ void updateCamera()
     // Collide camera ray with static objects (collision mask 2)
     Vector3 rayDir = (maxDist - minDist).getNormalized();
     float rayDistance = cameraMaxDist - cameraMinDist + cameraSafetyDist;
-    array<PhysicsRaycastResult> result = gameScene.getPhysicsWorld().raycast(Ray(minDist, rayDir), rayDistance, 2);
+    array<PhysicsRaycastResult>@ result = gameScene.getPhysicsWorld().raycast(Ray(minDist, rayDir), rayDistance, 2);
     if (result.length() > 0)
         rayDistance = min(rayDistance, result[0].distance - cameraSafetyDist);
     
diff --git a/Engine/Engine/RegisterScene.cpp b/Engine/Engine/RegisterScene.cpp
index 02671f7e3..172f636f8 100644
--- a/Engine/Engine/RegisterScene.cpp
+++ b/Engine/Engine/RegisterScene.cpp
@@ -388,7 +388,6 @@ static CScriptArray* SceneGetEntitiesWithClass(const std::string& className, Sce
             }
         }
     }
-    
     return vectorToHandleArray<Entity*>(result, "array<Entity@>");
 }
 
diff --git a/Engine/Script/ScriptFile.cpp b/Engine/Script/ScriptFile.cpp
index b5a57d3ec..e3389fefa 100644
--- a/Engine/Script/ScriptFile.cpp
+++ b/Engine/Script/ScriptFile.cpp
@@ -28,6 +28,7 @@
 #include "ResourceCache.h"
 #include "ScriptEngine.h"
 #include "ScriptFile.h"
+#include "ScriptInstance.h"
 #include "SharedArrayPtr.h"
 #include "StringUtils.h"
 
@@ -72,10 +73,17 @@ void ScriptFile::load(Deserializer& source, ResourceCache* cache)
 {
     PROFILE(Script_Load);
     
-    // Discard the previous module if there was one
+    // If script instances have created objects from this file, release them now
+    // Make a copy of the vector because the script instances will remove themselves from the member vector
+    std::vector<ScriptInstance*> instances = mScriptInstances;
+    for (std::vector<ScriptInstance*>::iterator i = instances.begin(); i != instances.end(); ++i)
+        (*i)->releaseObject();
+    
+    // Discard the previous module if there was one, and clear search caches
     mCompiled = false;
     mAllIncludeFiles.clear();
-    mInterfaceFound.clear();
+    mCheckedClasses.clear();
+    mFunctions.clear();
     setMemoryUse(0);
     removeAllEventHandlers();
     
@@ -101,6 +109,10 @@ void ScriptFile::load(Deserializer& source, ResourceCache* cache)
     
     LOGINFO("Compiled script module " + getName());
     mCompiled = true;
+    
+    // Now let the script instances recreate their objects
+    for (std::vector<ScriptInstance*>::iterator i = instances.begin(); i != instances.end(); ++i)
+        (*i)->setScriptClass(this, (*i)->getClassName());
 }
 
 void ScriptFile::addEventHandler(StringHash eventType, const std::string& handlerName)
@@ -262,8 +274,10 @@ asIScriptObject* ScriptFile::createObject(const std::string& className, asIScrip
     
     // Ensure that the type implements the "ScriptObject" interface, so it can be returned also to script properly
     bool found = false;
-    std::map<asIObjectType*, bool>::const_iterator i = mInterfaceFound.find(type);
-    if (i == mInterfaceFound.end())
+    std::map<asIObjectType*, bool>::const_iterator i = mCheckedClasses.find(type);
+    if (i != mCheckedClasses.end())
+        found = i->second;
+    else
     {
         unsigned numInterfaces = type->GetInterfaceCount();
         for (unsigned j = 0; j < numInterfaces; ++j)
@@ -275,10 +289,8 @@ asIScriptObject* ScriptFile::createObject(const std::string& className, asIScrip
                 break;
             }
         }
-        mInterfaceFound[type] = found;
+        mCheckedClasses[type] = found;
     }
-    else
-        found = i->second;
     if (!found)
     {
         LOGERROR("Script class " + className + " does not implement the ScriptObject interface");
@@ -302,13 +314,19 @@ asIScriptObject* ScriptFile::createObject(const std::string& className, asIScrip
     return obj;
 }
 
-asIScriptFunction* ScriptFile::getFunction(const std::string& declaration) const
+asIScriptFunction* ScriptFile::getFunction(const std::string& declaration)
 {
     if (!mCompiled)
         return 0;
     
+    std::map<std::string, asIScriptFunction*>::const_iterator i = mFunctions.find(declaration);
+    if (i != mFunctions.end())
+        return i->second;
+    
     int id = mScriptModule->GetFunctionIdByDecl(declaration.c_str());
-    return mScriptModule->GetFunctionDescriptorById(id);
+    asIScriptFunction* function = mScriptModule->GetFunctionDescriptorById(id);
+    mFunctions[declaration] = function;
+    return function;
 }
 
 asIScriptFunction* ScriptFile::getMethod(asIScriptObject* object, const std::string& declaration) const
@@ -324,6 +342,23 @@ asIScriptFunction* ScriptFile::getMethod(asIScriptObject* object, const std::str
     return mScriptModule->GetFunctionDescriptorById(id);
 }
 
+void ScriptFile::addScriptInstance(ScriptInstance* instance)
+{
+    mScriptInstances.push_back(instance);
+}
+
+void ScriptFile::removeScriptInstance(ScriptInstance* instance)
+{
+    for (std::vector<ScriptInstance*>::iterator i = mScriptInstances.begin(); i != mScriptInstances.end(); ++i)
+    {
+        if ((*i) == instance)
+        {
+            mScriptInstances.erase(i);
+            break;
+        }
+    }
+}
+
 void ScriptFile::addScriptSection(asIScriptEngine* engine, Deserializer& source, ResourceCache* cache)
 {
     unsigned dataSize = source.getSize();
diff --git a/Engine/Script/ScriptFile.h b/Engine/Script/ScriptFile.h
index acd44f736..6408af51d 100644
--- a/Engine/Script/ScriptFile.h
+++ b/Engine/Script/ScriptFile.h
@@ -33,6 +33,7 @@
 #include <vector>
 
 class ScriptEngine;
+class ScriptInstance;
 class Variant;
 class asIObjectType;
 class asIScriptContext;
@@ -76,13 +77,18 @@ public:
     ScriptEngine* getScriptEngine() const { return mScriptEngine; }
     //! Return script module
     asIScriptModule* getScriptModule() const { return mScriptModule; }
-    //! Return a function by declaration
-    asIScriptFunction* getFunction(const std::string& declaration) const;
+    //! Return a function by declaration. Will be stored to a search cache so that further searches should be faster
+    asIScriptFunction* getFunction(const std::string& declaration);
     //! Return an object method by declaration
     asIScriptFunction* getMethod(asIScriptObject* object, const std::string& declaration) const;
     //! Return whether script compiled successfully
     bool isCompiled() const { return mCompiled; }
     
+    //! Add script instance to keep track of in case of script reload
+    void addScriptInstance(ScriptInstance* instance);
+    //! Remove script instance to keep track of
+    void removeScriptInstance(ScriptInstance* instance);
+    
 private:
     //! Add a script section, checking for includes recursively
     void addScriptSection(asIScriptEngine* engine, Deserializer& source, ResourceCache* cache);
@@ -102,7 +108,11 @@ private:
     //! Encountered include files during script file loading
     std::set<std::string> mAllIncludeFiles;
     //! Search cache for checking whether script classes implement "ScriptObject" interface
-    std::map<asIObjectType*, bool> mInterfaceFound;
+    std::map<asIObjectType*, bool> mCheckedClasses;
+    //! Search cache for functions
+    std::map<std::string, asIScriptFunction*> mFunctions;
+    //! ScriptInstances that have created objects from this script file
+    std::vector<ScriptInstance*> mScriptInstances;
 };
 
 //! Get last script file that is executing or has executed script functions
diff --git a/Engine/Script/ScriptInstance.cpp b/Engine/Script/ScriptInstance.cpp
index be1afeed6..495b2ac6f 100644
--- a/Engine/Script/ScriptInstance.cpp
+++ b/Engine/Script/ScriptInstance.cpp
@@ -275,7 +275,7 @@ bool ScriptInstance::setScriptClass(ScriptFile* scriptFile, const std::string& c
         return false;
     }
     
-    if ((scriptFile == mScriptFile) && (className == mClassName))
+    if ((mScriptObject) && (scriptFile == mScriptFile) && (className == mClassName))
         return true;
     
     releaseObject();
@@ -293,6 +293,7 @@ bool ScriptInstance::setScriptClass(ScriptFile* scriptFile, const std::string& c
     mScriptObject = mScriptFile->createObject(mClassName, mScriptContext);
     if (mScriptObject)
     {
+        mScriptFile->addScriptInstance(this);
         objectToInstance[(void*)mScriptObject] = this;
         getSupportedMethods();
         if (mMethods[METHOD_START])
@@ -365,6 +366,8 @@ void ScriptInstance::releaseObject()
         
         mScriptObject->Release();
         mScriptObject = 0;
+        
+        mScriptFile->removeScriptInstance(this);
     }
 }
 
diff --git a/Engine/Script/ScriptInstance.h b/Engine/Script/ScriptInstance.h
index 175c538e5..5c4b29424 100644
--- a/Engine/Script/ScriptInstance.h
+++ b/Engine/Script/ScriptInstance.h
@@ -114,15 +114,15 @@ public:
     asIScriptObject* getScriptObject() const { return mScriptObject; }
     //! Return class name
     const std::string& getClassName() const { return mClassName; }
-    
     //! Return whether object created and running
     bool isRunning() const { return mScriptObject != 0; }
     //! Return whether scripted updates and event handlers are enabled
     bool isEnabled() const { return mEnabled; }
     
-private:
     //! Release object
     void releaseObject();
+    
+private:
     //! Clear supported methods
     void clearMethods();
     //! Check for supported methods
diff --git a/Examples/ScriptTest/Game.cpp b/Examples/ScriptTest/Game.cpp
index e3ab50342..484571308 100644
--- a/Examples/ScriptTest/Game.cpp
+++ b/Examples/ScriptTest/Game.cpp
@@ -71,11 +71,14 @@ void Game::run()
 {
     init();
     
-    if (!mRunFrameFunction)
-        return;
-    
     while (!mEngine->isExiting())
-        mScriptFile->execute(mRunFrameFunction);
+    {
+        mScriptFile->execute("void runFrame()");
+        
+        // Test reloading the ninja script
+        if (mEngine->getInput()->getKeyPress('R'))
+            mCache->reloadResource(mCache->getResource<ScriptFile>("Scripts/Ninja.as"));
+    }
 }
 
 void Game::init()
@@ -112,10 +115,7 @@ void Game::init()
     
     // Execute the rest of initialization, including scene creation, in script
     mScriptFile = mCache->getResource<ScriptFile>("Scripts/NinjaSnowWar.as");
-    mInitFunction = mScriptFile->getFunction("void init()");
-    mRunFrameFunction = mScriptFile->getFunction("void runFrame()");
-    
-    mScriptFile->execute(mInitFunction);
+    mScriptFile->execute("void init()");
 }
 
 void Game::createSkyPlaneModel()
diff --git a/Examples/ScriptTest/Game.h b/Examples/ScriptTest/Game.h
index 07d83709f..d5347e8a0 100644
--- a/Examples/ScriptTest/Game.h
+++ b/Examples/ScriptTest/Game.h
@@ -50,8 +50,6 @@ private:
     SharedPtr<Engine> mEngine;
     SharedPtr<ResourceCache> mCache;
     SharedPtr<ScriptFile> mScriptFile;
-    asIScriptFunction* mInitFunction;
-    asIScriptFunction* mRunFrameFunction;
 };
 
 #endif // GAME_H