コード例 #1
0
 public SectionDisposable(string label, InGameProfiler instance)
 {
     this.instance = instance ?? InGameProfiler.latest;
     if (this.instance == null)
     {
         return;
     }
     this.instance.Begin(label);
 }
コード例 #2
0
 void Awake()
 {
     latest  = this;
     current = root;
 }
コード例 #3
0
 public static System.IDisposable Section(string label, InGameProfiler instance = null)
 {
     return(new SectionDisposable(label, instance));
 }
コード例 #4
0
ファイル: Services.cs プロジェクト: zachary2234/gamebuilder
        // Ideally this wouldn't live here, but for now, whatever.
        internal void CallService(string serviceName, string argsJson, System.IntPtr reportResultPtr)
        {
            Native.ReportResultFunction reportResult = null;
            if (CacheReportResult)
            {
                if (cachedReportResult == null)
                {
                    cachedReportResult   = Marshal.GetDelegateForFunctionPointer <Native.ReportResultFunction>(reportResultPtr);
                    firstReportResultPtr = reportResultPtr;
                }

                reportResult = cachedReportResult;
                Debug.Assert(firstReportResultPtr == reportResultPtr, $"Different reportResultPtr was given!");
            }
            else
            {
                reportResult = Marshal.GetDelegateForFunctionPointer <Native.ReportResultFunction>(reportResultPtr);
            }

            try
            {
                switch (serviceName)
                {
                case "BeginProfileSample":
                {
                    InGameProfiler.BeginSection(argsJson);
                    reportResult("0");
                    break;
                }

                case "EndProfileSample":
                {
                    InGameProfiler.EndSection();
                    reportResult("0");
                    break;
                }

                case "OverlapSphere":
                    using (Util.Profile(serviceName))
                    {
                        var args    = JsonUtility.FromJson <OverlapSphereArgs>(argsJson);
                        int numHits = Physics.OverlapSphereNonAlloc(args.center, args.radius, SharedColliderBuffer, VoosActor.LayerMaskValue, QueryTriggerInteraction.Collide);
                        if (numHits == SharedColliderBuffer.Length)
                        {
                            Util.LogError($"The OverlapSphere call exceeded the maximum number of allowed results ({SharedColliderBuffer.Length}). You are probably not getting what you want. Please try to adjust the parameters so you get less hits, like reducing the radius.");
                        }
                        using (Util.Profile("report actors"))
                        {
                            var jsoner = SharedStringBuilder;
                            jsoner.Clear();
                            jsoner.Append("[");
                            bool gotOneActor = false;
                            for (int i = 0; i < numHits; i++)
                            {
                                Collider  obj   = SharedColliderBuffer[i];
                                VoosActor actor = obj.GetComponentInParent <VoosActor>();
                                if (actor == null)
                                {
                                    continue;
                                }
                                if (!args.tag.IsNullOrEmpty())
                                {
                                    if (!actor.HasTag(args.tag))
                                    {
                                        continue;
                                    }
                                }

                                if (gotOneActor)
                                {
                                    jsoner.Append(",");
                                }
                                jsoner.Append("\"");
                                jsoner.Append(actor.GetName());
                                jsoner.Append("\"");
                                gotOneActor = true;
                            }
                            jsoner.Append("]");
                            reportResult(jsoner.ToString());
                        }
                        break;
                    }

                case "CheckBox":
                    using (Util.Profile(serviceName))
                    {
                        var  args        = JsonUtility.FromJson <CheckBoxArgs>(argsJson);
                        bool hitAnything = Physics.CheckBox(args.box.center, args.box.dimensions * 0.5f, args.box.rotation,
                                                            -1,                            // We're probably looking for clearance, so return true if the box hits actors OR just static terrain.
                                                            QueryTriggerInteraction.Ignore // Ignore triggers for checks. We are probably looking for clearance, in which case triggers don't matter.
                                                            );
                        reportResult(hitAnything ? "true" : "false");
                        break;
                    }

                case "Cast":
                    using (Util.Profile(serviceName))
                    {
                        PhysicsCastRequest req = JsonUtility.FromJson <PhysicsCastRequest>(argsJson);

                        int layerMask = (req.includeActors ? VoosActor.LayerMaskValue : 0) |
                                        (req.includeTerrain ? LayerMask.GetMask("Default") : 0);
                        int numHits = req.radius < 0.01 ?
                                      Physics.RaycastNonAlloc(req.origin, req.dir, SharedRaycastHitBuffer, req.maxDist, layerMask, QueryTriggerInteraction.Collide) :
                                      Physics.SphereCastNonAlloc(req.origin, req.radius, req.dir, SharedRaycastHitBuffer, req.maxDist, layerMask, QueryTriggerInteraction.Collide);

                        // These variables things are somewhat redundant, but for performance we keep all three and
                        // only use the appropriate ones per req.castMode, to avoid unnecessary allocations.
                        // List of results. Only allocate if we have to.
                        List <PhysicsCastHit> results = null;
                        // Did we have any hit?
                        bool anyHit = false;
                        // The closest hit we got. Only valid if anyHit == true.
                        PhysicsCastHit closestHit = new PhysicsCastHit();

                        if (req.mode == CastMode.ALL_SORTED || req.mode == CastMode.ALL_UNSORTED)
                        {
                            // We will need to return a list, so allocate it.
                            results = new List <PhysicsCastHit>();
                        }

                        for (int i = 0; i < numHits; i++)
                        {
                            RaycastHit     hit = SharedRaycastHitBuffer[i];
                            PhysicsCastHit thisHit;
                            if (hit.collider != null && hit.collider.gameObject != null &&
                                hit.collider.gameObject.GetComponent <IgnoreRaycastFromScript>() != null)
                            {
                                continue;
                            }
                            if (req.includeActors && IsScriptReadyActor(hit.collider) && GetActorName(hit.collider) != req.excludeActor)
                            {
                                // Hit an actor.
                                // (PhysicsCastHit is a struct, not allocating on heap)
                                thisHit = new PhysicsCastHit
                                {
                                    actor    = GetActorName(hit.collider),
                                    distance = hit.distance,
                                    point    = hit.point
                                };
                            }
                            else if (req.includeTerrain && hit.collider.tag == "Ground")
                            {
                                // Hit terrain.
                                // (PhysicsCastHit is a struct, not allocating on heap)
                                thisHit = new PhysicsCastHit
                                {
                                    actor    = null,
                                    distance = hit.distance,
                                    point    = hit.point
                                };
                            }
                            else
                            {
                                continue;
                            }
                            closestHit = (!anyHit || thisHit.distance < closestHit.distance) ? thisHit : closestHit;
                            anyHit     = true;
                            results?.Add(thisHit);
                            if (req.mode == CastMode.BOOLEAN)
                            {
                                // If we're just returning true/false, that's all we need.
                                break;
                            }
                        }

                        // Sort results by distance, if requested.
                        if (req.mode == CastMode.ALL_SORTED)
                        {
                            results.Sort((a, b) => a.distance.CompareTo(b.distance));
                        }

                        // Report results as requested.
                        if (req.mode == CastMode.ALL_SORTED || req.mode == CastMode.ALL_UNSORTED)
                        {
                            PhysicsCastResult result = new PhysicsCastResult {
                                hits = results.ToArray()
                            };
                            reportResult(JsonUtility.ToJson(result));
                        }
                        else if (req.mode == CastMode.CLOSEST)
                        {
                            reportResult(anyHit ? JsonUtility.ToJson(closestHit) : "null");
                        }
                        else
                        {
                            reportResult(anyHit ? "true" : "false");
                        }
                        break;
                    }

                case "GetPlayerActors":
                    using (Util.Profile(serviceName))
                    {
                        var jsoner = SharedStringBuilder;
                        jsoner.Clear();
                        jsoner.Append("[");
                        bool gotOneActor = false;

                        foreach (VoosActor actor in engine.EnumerateActors())
                        {
                            if (actor.GetIsPlayerControllable())
                            {
                                if (gotOneActor)
                                {
                                    jsoner.Append(",");
                                }
                                jsoner.Append("\"");
                                jsoner.Append(actor.GetName());
                                jsoner.Append("\"");
                                gotOneActor = true;
                            }
                        }
                        jsoner.Append("]");
                        reportResult(jsoner.ToString());
                        break;
                    }

                case "SetTerrainCell":
                {
                    var args = JsonUtility.FromJson <TerrainManager.SetCellRpcJsonable>(argsJson);
                    terrainSystem.SetCellValue(args.cell, args.value);
                    reportResult("true");
                    break;
                }

                case "GetTerrainCell":
                {
                    Vector3 coords = JsonUtility.FromJson <Vector3>(argsJson);
                    TerrainManager.CellValue cellValue = terrainSystem.GetCellValue(
                        new TerrainManager.Cell((int)coords.x, (int)coords.y, (int)coords.z));
                    GetTerrainCellResult result = new GetTerrainCellResult
                    {
                        shape = (int)cellValue.blockType,
                        dir   = (int)cellValue.direction,
                        style = (int)cellValue.style
                    };
                    reportResult(JsonUtility.ToJson(result));
                    break;
                }

                case "IsMultiplayer":
                {
                    reportResult(GameBuilderApplication.CurrentGameOptions.playOptions.isMultiplayer ? "true" : "false");
                    break;
                }

                case "TransferPlayerControl":
                {
                    VoosEngine.TransferPlayerControlRequest request =
                        JsonUtility.FromJson <VoosEngine.TransferPlayerControlRequest>(argsJson);
                    // Engine will handle this asynchronously because the actor might not be immediately
                    // available (maybe it was a clone that was just created, for instance).
                    GetEngine().RequestTransferPlayerControl(request);
                    reportResult("true");
                    break;
                }

                case "GetPlayerControlledActor":
                {
                    VoosActor actor = GetUserMain().GetPlayerActor();
                    reportResult(actor == null ? "null" : "\"" + actor.GetName() + "\"");
                    break;
                }

                case "IsMasterClient":
                {
                    reportResult(PhotonNetwork.isMasterClient ? "true" : "false");
                    break;
                }

                case "GetPlayersInfo":
                {
                    Dictionary <int, string> nicknames = new Dictionary <int, string>();
                    int i;
                    for (i = 0; i < PhotonNetwork.playerList.Length; i++)
                    {
                        int    id   = PhotonNetwork.playerList[i].ID;
                        string nick = PhotonNetwork.playerList[i].NickName;
                        nicknames[id] = nick;
                    }

                    VirtualPlayersResult result = new VirtualPlayersResult();
                    result.allPlayers = new VirtualPlayerResultEntry[virtualPlayerManager.GetVirtualPlayerCount()];

                    i = 0;
                    foreach (VirtualPlayerManager.VirtualPlayerInfo virtualPlayer in virtualPlayerManager.EnumerateVirtualPlayers())
                    {
                        Debug.Assert(i < result.allPlayers.Length);
                        result.allPlayers[i].id         = virtualPlayer.virtualId;
                        result.allPlayers[i].slotNumber = virtualPlayer.slotNumber;
                        result.allPlayers[i].nickName   = virtualPlayer.nickName;
                        ++i;
                    }
                    Debug.Assert(i == result.allPlayers.Length);

                    result.localPlayerId = playerControlsManager.GetVirtualPlayerId();
                    reportResult(JsonUtility.ToJson(result));
                    break;
                }

                case "RequestUi":
                {
                    using (Util.Profile("RequestUi"))
                    {
                        GameUiMain.UiCommandList list = JsonUtility.FromJson <GameUiMain.UiCommandList>(argsJson);
                        gameUiMain.SetUiCommands(list);
                        reportResult("true");
                    }
                    break;
                }

                case "GetActorColorField":
                {
                    GetActorFieldArgs args = JsonUtility.FromJson <GetActorFieldArgs>(argsJson);
                    reportResult(JsonUtility.ToJson(engine.GetActorColor(args.actorId, args.fieldId)));
                    break;
                }

                case "SetActorColorField":
                {
                    SetActorColorFieldArgs args = JsonUtility.FromJson <SetActorColorFieldArgs>(argsJson);
                    engine.SetActorColor(args.actorId, args.fieldId, args.newValue);
                    reportResult("true");
                    break;
                }

                case "CloneActor":
                    using (Util.Profile(serviceName))
                    {
                        VoosEngine.CloneActorRequest  args     = JsonUtility.FromJson <VoosEngine.CloneActorRequest>(argsJson);
                        VoosEngine.CloneActorResponse response = GetEngine().CloneActorForScript(args);
                        reportResult(JsonUtility.ToJson(response));
                        break;
                    }

                case "InstantiatePrefab":
                    using (Util.Profile(serviceName))
                    {
                        VoosEngine.InstantiatePrefab.Request  args     = JsonUtility.FromJson <VoosEngine.InstantiatePrefab.Request>(argsJson);
                        VoosEngine.InstantiatePrefab.Response response = GetEngine().InstantiatePrefabForScript(args);
                        reportResult(JsonUtility.ToJson(response));
                        break;
                    }

                case "DestroyActors":
                    using (Util.Profile(serviceName))
                    {
                        VoosEngine.DestroyActorsRequest args = JsonUtility.FromJson <VoosEngine.DestroyActorsRequest>(argsJson);
                        GetEngine().DestroyActorsForScript(args);
                        reportResult("true");
                        break;
                    }

                case "PlaySound":
                    using (Util.Profile(serviceName))
                    {
                        PlaySoundRequest args = JsonUtility.FromJson <PlaySoundRequest>(argsJson);
                        SoundEffect      sfx  = soundEffectSystem.GetSoundEffect(args.soundId);
                        if (sfx != null)
                        {
                            if (string.IsNullOrEmpty(args.actorName))
                            {
                                soundEffectSystem.PlaySoundEffect(sfx, null, args.position);
                            }
                            else
                            {
                                VoosActor actor = engine.GetActor(args.actorName);
                                if (actor == null)
                                {
                                    Debug.LogError("Could not play sound on actor. Actor not found: " + args.actorName);
                                    reportResult("false");
                                }
                                soundEffectSystem.PlaySoundEffect(sfx, actor, Vector3.zero);
                            }
                            reportResult("true");
                        }
                        else
                        {
                            Debug.LogWarning("No SFX with ID: " + args.soundId);
                            reportResult("false");
                        }
                        break;
                    }

                case "SpawnParticleEffect":
                    using (Util.Profile(serviceName))
                    {
                        ParticleEffectRequest args = JsonUtility.FromJson <ParticleEffectRequest>(argsJson);
                        ParticleEffect        pfx  = particleEffectSystem.GetParticleEffect(args.pfxId);
                        if (pfx != null)
                        {
                            particleEffectSystem.SpawnParticleEffect(
                                pfx, args.position, args.rotation * Mathf.Rad2Deg, args.scale);
                            reportResult("true");
                        }
                        else
                        {
                            Debug.LogWarning("No particle effect with ID: " + args.pfxId);
                            reportResult("false");
                        }
                        break;
                    }

                case "PlayOneShotAnimation":
                {
                    OneShotAnimationRequest req = JsonUtility.FromJson <OneShotAnimationRequest>(argsJson);
                    VoosActor actor             = engine.GetActorByTempId(req.actorTempId);
                    if (actor != null)
                    {
                        actor.PlayOneShotAnimation(req.animationName);
                    }
                    else
                    {
                        Util.LogError($"PlayOneShotAnimation: Could not find actor for temp ID {req.actorTempId}. Ignoring.");
                    }
                    reportResult("true");
                    break;
                }

                case "ProjectPoint":
                {
                    Camera  cam         = GetUserMain().GetCamera();
                    Vector3 point       = JsonUtility.FromJson <Vector3>(argsJson);
                    Vector3 screenPoint = cam.WorldToScreenPoint(point);
                    if (screenPoint.z > 0)
                    {
                        Vector2 gameUiPoint = gameUiMain.UnityScreenPointToGameUiPoint(screenPoint);
                        reportResult(JsonUtility.ToJson(gameUiPoint));
                    }
                    else
                    {
                        reportResult("null");
                    }
                    break;
                }

                case "ProjectSphere":
                {
                    Camera    cam          = GetUserMain().GetCamera();
                    SphereArg inSphere     = JsonUtility.FromJson <SphereArg>(argsJson);
                    Vector3   screenCenter = cam.WorldToScreenPoint(inSphere.center);
                    if (screenCenter.z > 0)
                    {
                        Vector3   centerGameUi     = gameUiMain.UnityScreenPointToGameUiPoint(screenCenter);
                        Vector3   rightPoint       = cam.WorldToScreenPoint(inSphere.center + cam.transform.right * inSphere.radius);
                        Vector3   rightPointGameUi = gameUiMain.UnityScreenPointToGameUiPoint(rightPoint);
                        SphereArg outSphere        = new SphereArg
                        {
                            center = centerGameUi,
                            radius = Mathf.Abs(rightPointGameUi.x - centerGameUi.x)
                        };
                        reportResult(JsonUtility.ToJson(outSphere));
                    }
                    else
                    {
                        reportResult("null");
                    }
                    break;
                }

                case "GetActorScreenRect":
                {
                    string    actorName   = JsonUtility.FromJson <GetActorScreenRectRequest>(argsJson).actor;
                    VoosActor actor       = engine.GetActor(actorName);
                    Bounds    worldBounds = new Bounds(actor.GetWorldRenderBoundsCenter(), actor.GetWorldRenderBoundsSize());

                    // Depending on the orientation, any of the 8 corners of the world-space bounding box
                    // can contribute to the screen-space bounding box, so we have to go through them all.
                    Bounds screenBounds = new Bounds();
                    bool   success      = true;
                    for (int i = 0; i < 8; i++)
                    {
                        Vector3 worldPoint = new Vector3(
                            (i & 1) > 0 ? worldBounds.min.x : worldBounds.max.x,
                            (i & 2) > 0 ? worldBounds.min.y : worldBounds.max.y,
                            (i & 4) > 0 ? worldBounds.min.z : worldBounds.max.z);
                        Vector3 screenPoint = GetUserMain().GetCamera().WorldToScreenPoint(worldPoint);
                        if (screenPoint.z < 0)
                        {
                            // Off-screen (behind camera).
                            success = false;
                            break;
                        }
                        Vector2 gameUiPoint = gameUiMain.UnityScreenPointToGameUiPoint(screenPoint);
                        if (i == 0)
                        {
                            // Note: due to the Bounds() constructor assuming Vector3.zero as the center
                            // (known Unity bug), we have to reinitialize it here:
                            screenBounds = new Bounds(gameUiPoint, Vector3.zero);
                        }
                        else
                        {
                            screenBounds.Encapsulate(gameUiPoint);
                        }
                    }
                    reportResult(success ? JsonUtility.ToJson(new GetActorScreenRectResponse
                        {
                            x = screenBounds.min.x,
                            y = screenBounds.min.y,
                            w = screenBounds.size.x,
                            h = screenBounds.size.y
                        }) : "null");
                    break;
                }

                case "GetCameraInfo":
                {
                    Transform  cameraTransform = GetUserMain().GetCamera().transform;
                    CameraInfo info            = new CameraInfo
                    {
                        pos = cameraTransform.position,
                        rot = cameraTransform.rotation
                    };
                    reportResult(JsonUtility.ToJson(info));
                    break;
                }

                case "ReportBehaviorException":
                {
                    Util.LogError($"ReportBehaviorException {argsJson}");
                    VoosEngine.BehaviorLogItem e = JsonUtility.FromJson <VoosEngine.BehaviorLogItem>(argsJson);
                    engine.HandleBehaviorException(e);
                    reportResult("true");
                    break;
                }

                case "LogBehaviorMessage":
                {
                    Util.Log($"LogBehaviorMessage {argsJson}");
                    VoosEngine.BehaviorLogItem msg = JsonUtility.FromJson <VoosEngine.BehaviorLogItem>(argsJson);
                    engine.HandleBehaviorLogMessage(msg);
                    reportResult("true");
                    break;
                }

                case "GetCameraActor":
                {
                    string cameraActorName = GetUserMain().GetCameraActor()?.GetName();
                    reportResult(cameraActorName == null ? "null" : ("\"" + cameraActorName + "\""));
                    break;
                }

                case "RequestTempCameraOffset":
                {
                    TempCameraOffsetRequest request = JsonUtility.FromJson <TempCameraOffsetRequest>(argsJson);
                    if (request.actor == GetUserMain().GetPlayerActor()?.GetName())
                    {
                        GetUserMain().GetNavigationControls().RequestTemporaryCameraOffset(request.offset);
                    }
                    reportResult("true");
                    break;
                }

                case "GetScreenInfo":
                {
                    reportResult(JsonUtility.ToJson(gameUiMain.GetScreenInfoForScript()));
                    break;
                }

                case "SetSkyType":
                {
                    JsonWrapper <string>     request = JsonUtility.FromJson <JsonWrapper <string> >(argsJson);
                    GameBuilderStage.SkyType skyType;
                    if (Util.TryParseEnum(request.value ?? "", out skyType, true))
                    {
                        gbStage.SetSkyType(skyType);
                        reportResult("true");
                    }
                    else
                    {
                        Debug.LogError("Invalid sky type requested: " + request.value);
                        reportResult("false");
                    }
                    break;
                }

                case "GetSkyType":
                {
                    reportResult(JsonUtility.ToJson(JsonWrapper <string> .Wrap(gbStage.GetSkyType().ToString())));
                    break;
                }

                case "SetSkyColor":
                {
                    JsonWrapper <Color> request = JsonUtility.FromJson <JsonWrapper <Color> >(argsJson);
                    gbStage.SetSkyColor(request.value);
                    reportResult("true");
                    break;
                }

                case "GetSkyColor":
                {
                    reportResult(JsonUtility.ToJson(JsonWrapper <Color> .Wrap(gbStage.GetSkyColor())));
                    break;
                }

                case "SetSceneLighting":
                {
                    JsonWrapper <string> request = JsonUtility.FromJson <JsonWrapper <string> >(argsJson);
                    GameBuilderStage.SceneLightingMode sceneLightingMode;
                    if (Util.TryParseEnum <GameBuilderStage.SceneLightingMode>(request.value, out sceneLightingMode, ignoreCase: true))
                    {
                        gbStage.SetSceneLightingMode(sceneLightingMode);
                        reportResult("true");
                    }
                    else
                    {
                        Debug.LogError("Invalid scene lighting mode: " + request.value);
                        reportResult("false");
                    }
                    break;
                }

                case "GetSceneLighting":
                {
                    reportResult(JsonUtility.ToJson(JsonWrapper <string> .Wrap(gbStage.GetSceneLightingMode().ToString().ToUpperInvariant())));
                    break;
                }

                default:
                    Util.LogError($"VOOS script tried to call unknown service {serviceName}.");
                    break;
                }
            }
            catch (System.Exception e)
            {
                // We cannot let exceptions escape. It will tend to crash the process.
                Util.LogError($"Exception during CallService({serviceName}):\n{e}");
                reportResult("false");
            }
        }
コード例 #5
0
 private void Awake()
 {
     // グラフの描画する場所を指定する
     _profiler    = new InGameProfiler(new Rect(30, 30, Screen.width - 60, Screen.height - 60));
     _isProfiling = true;
 }
コード例 #6
0
ファイル: Native.cs プロジェクト: zachary2234/gamebuilder
        public static Util.Maybe <TResponse> UpdateAgent <TRequest, TResponse>(string brainUid, string agentUid,
                                                                               TRequest input, byte[] bytes,
                                                                               UpdateCallbacks callbacks)
        {
            using (new UpdateAgentLock())
                using (InGameProfiler.Section("Native.UpdateAgent"))
                    using (var pinnedBytes = Util.Pin(bytes))
                    {
                        NumUpdateCalls++;
                        bool   ok         = false;
                        string inputJson  = null;
                        string outputJson = null;

                        using (InGameProfiler.Section("ToJson"))
                        {
                            inputJson = JsonUtility.ToJson(input, false);
                        }
                        using (InGameProfiler.Section("UpdateAgentJsonNative"))
                        {
                            UserErrorHandler.Push(callbacks.handleError);
                            UserLogMessageHandler.Push(callbacks.handleLog);

                            userActorStringGetter = callbacks.getActorString;
                            userActorStringSetter = callbacks.setActorString;

                            using (InGameProfiler.Section("setting callbacks"))
                            {
                                // Avoid unnecessary calls to the Set... delegate bind functions,
                                // since those can take ~0.2ms each! Also, any pinning is
                                // unnecessary, since the life time of use is limited to this
                                // function. See:
                                // https://blogs.msdn.microsoft.com/cbrumme/2003/05/06/asynchronous-operations-pinning/

                                if (lastCallServiceFunction != callbacks.callService)
                                {
                                    SetCallServiceFunction(callbacks.callService);
                                    lastCallServiceFunction = callbacks.callService;
                                }

                                // BEGIN_GAME_BUILDER_CODE_GEN ACTOR_ACCESSOR_DELEGATE_MAYBE_SETS
                                if (lastBooleanGetterCallback != callbacks.getActorBoolean) // GENERATED
                                {
                                    SetActorBooleanGetter(callbacks.getActorBoolean);       // GENERATED
                                    lastBooleanGetterCallback = callbacks.getActorBoolean;  // GENERATED
                                }

                                if (lastBooleanSetterCallback != callbacks.setActorBoolean) // GENERATED
                                {
                                    SetActorBooleanSetter(callbacks.setActorBoolean);       // GENERATED
                                    lastBooleanSetterCallback = callbacks.setActorBoolean;  // GENERATED
                                }

                                if (lastVector3GetterCallback != callbacks.getActorVector3) // GENERATED
                                {
                                    SetActorVector3Getter(callbacks.getActorVector3);       // GENERATED
                                    lastVector3GetterCallback = callbacks.getActorVector3;  // GENERATED
                                }

                                if (lastVector3SetterCallback != callbacks.setActorVector3) // GENERATED
                                {
                                    SetActorVector3Setter(callbacks.setActorVector3);       // GENERATED
                                    lastVector3SetterCallback = callbacks.setActorVector3;  // GENERATED
                                }

                                if (lastQuaternionGetterCallback != callbacks.getActorQuaternion) // GENERATED
                                {
                                    SetActorQuaternionGetter(callbacks.getActorQuaternion);       // GENERATED
                                    lastQuaternionGetterCallback = callbacks.getActorQuaternion;  // GENERATED
                                }

                                if (lastQuaternionSetterCallback != callbacks.setActorQuaternion) // GENERATED
                                {
                                    SetActorQuaternionSetter(callbacks.setActorQuaternion);       // GENERATED
                                    lastQuaternionSetterCallback = callbacks.setActorQuaternion;  // GENERATED
                                }

                                if (lastFloatGetterCallback != callbacks.getActorFloat) // GENERATED
                                {
                                    SetActorFloatGetter(callbacks.getActorFloat);       // GENERATED
                                    lastFloatGetterCallback = callbacks.getActorFloat;  // GENERATED
                                }

                                if (lastFloatSetterCallback != callbacks.setActorFloat) // GENERATED
                                {
                                    SetActorFloatSetter(callbacks.setActorFloat);       // GENERATED
                                    lastFloatSetterCallback = callbacks.setActorFloat;  // GENERATED
                                }

                                // END_GAME_BUILDER_CODE_GEN
                            }
                            // Safe callback passing: https://docs.microsoft.com/en-us/dotnet/framework/interop/marshaling-a-delegate-as-a-callback-method
                            StringFunction captureJsonFunction = new StringFunction(json => outputJson = json);
                            ok = UpdateAgentJsonBytes(brainUid, agentUid,
                                                      inputJson, pinnedBytes.GetPointer(), bytes.Length,
                                                      captureJsonFunction);

                            UserErrorHandler.Pop();
                            UserLogMessageHandler.Pop();
                        }

                        if (!ok)
                        {
                            // TODO consider using the JSON return value for communicating the
                            // exception from JS...and throwing an exception!!
                            Debug.LogError("UpdateAgent failed. inputJson: " + inputJson);
                            return(Util.Maybe <TResponse> .CreateEmpty());
                        }
                        else
                        {
                            using (InGameProfiler.Section("FromJson"))
                            {
#if UNITY_EDITOR
                                if (outputJson.Length > 5 * 1024 * 1024)
                                {
                                    Util.LogError($"JSON response from VOOS update is getting dangerously large..exceeding 5MB. Full content: {outputJson}");
                                    Debug.Assert(false, "Editor-only JSON size check. See log for more details.");
                                }
#endif
                                TResponse response = JsonUtility.FromJson <TResponse>(outputJson);
                                return(Util.Maybe <TResponse> .CreateWith(response));
                            }
                        }
                    }
        }