unity-jsb icon indicating copy to clipboard operation
unity-jsb copied to clipboard

Various MonoBehaviour methods not being called

Open lorenalexm opened this issue 2 years ago • 4 comments

I have had a bit more time to explore unity-jsb, and have stumbled upon a place where I can initialize the runtime and receive Awake and OnEnable calls to my script. It seems though that no other MonoBehaviour lifecycle methods are being called.

Two scripts were created to handle creating and destroying the ScriptRuntime. I found that I needed to change the script execution order within Unity to have the runtime created before the majority of the other scripts were ran, and in like have the runtime destroyed following the other scripts.

Screen Shot 2021-07-30 at 7 06 24 AM

// CreateRuntime.cs
using QuickJS;
using QuickJS.Binding;
using QuickJS.IO;
using QuickJS.Utils;
using UnityEngine;

public class CreateRuntime : MonoBehaviour
{
    private ScriptRuntime runtime;

    private void Awake() {
        RuntimeLogger logger = new RuntimeLogger();
        runtime = ScriptEngine.CreateRuntime();
        IFileSystem fileSystem = new DefaultFileSystem(logger);
        var asyncManager = new DefaultAsyncManager();
        var pathResolver = new PathResolver();
        pathResolver.AddSearchPath("node_modules");
        pathResolver.AddSearchPath("Scripts/out");
        runtime.AddModuleResolvers();
        runtime.Initialize(new ScriptRuntimeArgs {
            fileSystem = fileSystem,
            pathResolver = pathResolver,
            asyncManager = asyncManager,
            logger = logger,
            byteBufferAllocator = new ByteBufferPooledAllocator(),
            binder = DefaultBinder.GetBinder(false),
        });
    }

    private void Update() {
        if(runtime != null) {
            runtime.Update((int)Time.deltaTime);
        } else {
            Debug.LogError("Lost reference to the runtime!");
        }
    }
}

// DestroyRuntime.cs
using System;
using QuickJS;
using UnityEngine;

public class DestroyRuntime : MonoBehaviour
{
    private void OnDestroy()
    {
        ScriptEngine.Shutdown();
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

Everything seems to work without issue at this point. At least in the sense of no errors being thrown, and the console not reporting anything amiss. When I attach a JSBehaviour, with its source file pointing to the below script, to an empty object though, the runtime seems to fail at calling the Update, OnDisable, or the OnDestroy methods that are defined. It does not report any issues to the Unity console, in fact it does not do anything despite the console.log calls. As reported earlier, the Awake and OnEnable do correctly report their messages to the console.

// Testing.ts
import { MonoBehaviour } from "UnityEngine";
import { ScriptString, ScriptType } from "./plover/editor/editor_decorators";

@ScriptType()
export class Testing extends MonoBehaviour {
    @ScriptString()
    protected message = "Hello World";

    private tick = 0

    Awake() {
        this.reportMessage();
    }

    OnEnable() {
        console.log("Enabling the test object.");
    }

    OnDisable() {
        console.log("Disabling the test object.");
    }

    OnDestroy() {
        console.log("Destroying the test object.");
    }
    
    Update() {
        this.tick++;
        if((this.tick % 100) == 0) {
            console.log("Updating the test object.");
        }
    }

    reportMessage() {
        console.log(`The message from the test object is: ${this.message}.`);
    }
}

Have I done something incorrect in creating the runtime? I have tried comparing to the example projects from this repository, and I seem to have hit on all of the key points in creating and updating the runtime. Is there something amiss that I am overlooking?

Thank you!

lorenalexm avatar Aug 01 '21 13:08 lorenalexm

The Update call was moved into another MonoBehaviour JSBehaviourFull (I'm finding a better way to friendly switch between JSBehaviour and JSBehaviourFull (You can not change one into another in Unity Editor at present). Anyway, I'll check it in my environment.

ialex32x avatar Aug 01 '21 14:08 ialex32x

Changing over to the JSBehaviourFull component does seem to resolve the issue with the Update method being called, so that is wonderful. Thank you!

It does seem in moving to the new component that I am having an error thrown when ending the "Play session" within the editor. It is showing a script runtime not ready error once wrapped up.

script runtime not ready UnityEngine.Debug:LogError (object) QuickJS.Unity.JSBehaviour:CreateScriptInstance () (at Assets/Jsb/Source/Unity/JSBehaviour.cs:661) QuickJS.Unity.JSInspectorBase1<QuickJS.Unity.JSBehaviour>:EnableScriptInstance () (at Assets/Jsb/Source/Unity/Editor/JSInspectorBase.cs:257) QuickJS.Unity.JSInspectorBase1<QuickJS.Unity.JSBehaviour>:OnInspectorGUI () (at Assets/Jsb/Source/Unity/Editor/JSInspectorBase.cs:474) UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&) (at /Users/bokken/buildslave/unity/build/Modules/IMGUI/GUIUtility.cs:189)

From the message provided, it does seem to be related to the editor and does not appear that it would affect the end product. Simply wanted to forward that message your way.

lorenalexm avatar Aug 01 '21 14:08 lorenalexm

I've updated the editor of JSBehaviour. It's easier to toggle whether the JSBehaviour is updatable or not. image

ialex32x avatar Aug 04 '21 02:08 ialex32x

the error script runtime not ready is caused by uncertain execution order, it's difficult to resolve, because the script engine initialization process could/should be asynchronous (e.g waiting for the async file system ready). So, it's better and safer to wrap them in a prefab, and instantiate the scripted prefab in a script.

ialex32x avatar Aug 04 '21 03:08 ialex32x