public SectionDisposable(string label, InGameProfiler instance) { this.instance = instance ?? InGameProfiler.latest; if (this.instance == null) { return; } this.instance.Begin(label); }
void Awake() { latest = this; current = root; }
public static System.IDisposable Section(string label, InGameProfiler instance = null) { return(new SectionDisposable(label, instance)); }
// 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"); } }
private void Awake() { // グラフの描画する場所を指定する _profiler = new InGameProfiler(new Rect(30, 30, Screen.width - 60, Screen.height - 60)); _isProfiling = true; }
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)); } } } }