예제 #1
0
        private static async void HandleScriptModifiedAsync(string assetPath)
        {
            if (!Engine.Initialized || !(Engine.Behaviour is RuntimeBehaviour) || !configuration.HotReloadScripts ||
                !ObjectUtils.IsValid(player.PlayedScript) || player.Playlist?.Count == 0)
            {
                return;
            }

            var scriptGuid = AssetDatabase.AssetPathToGUID(assetPath);
            var scriptName = editorResources.GetRecordByGuid(scriptGuid)?.Name;

            if (player.PlayedScript.Name != scriptName)
            {
                return;
            }

            var lastPlayedLineIndex = (player.PlayedCommand ?? player.Playlist.Last()).PlaybackSpot.LineIndex;

            // Find the first modified line in the updated script (before the played line).
            var rollbackIndex = -1;

            for (int i = 0; i < lastPlayedLineIndex; i++)
            {
                if (!player.PlayedScript.Lines.IsIndexValid(i)) // The updated script ends before the currently played line.
                {
                    rollbackIndex = player.Playlist.GetCommandBeforeLine(i - 1, 0)?.PlaybackSpot.LineIndex ?? 0;
                    break;
                }

                var oldLineHash = playedLineHashes[i];
                var newLine     = player.PlayedScript.Lines[i];
                if (oldLineHash.EqualsFast(newLine.LineHash))
                {
                    continue;
                }

                rollbackIndex = player.Playlist.GetCommandBeforeLine(i, 0)?.PlaybackSpot.LineIndex ?? 0;
                break;
            }

            if (rollbackIndex > -1) // Script has changed before the played line.
            // Rollback to the line before the first modified one.
            {
                await stateManager.RollbackAsync(s => s.PlaybackSpot.LineIndex == rollbackIndex);
            }

            // Update the playlist and play.
            var resumeLineIndex = rollbackIndex > -1 ? rollbackIndex : lastPlayedLineIndex;
            var playlist        = new ScriptPlaylist(player.PlayedScript, scriptManager);
            var playlistIndex   = player.Playlist.FindIndex(c => c.PlaybackSpot.LineIndex == resumeLineIndex);

            player.Play(playlist, playlistIndex);

            if (player.WaitingForInput)
            {
                player.SetWaitingForInputEnabled(false);
            }
        }
예제 #2
0
        /// <summary>
        /// Performs hot-reload of the currently played script.
        /// </summary>
        public static async UniTask ReloadPlayedScriptAsync()
        {
            if (player?.Playlist is null || player.Playlist.Count == 0 || !player.PlayedScript)
            {
                Debug.LogError("Failed to perform hot reload: script player is not available or no script is currently played.");
                return;
            }

            var requireReload = string.IsNullOrEmpty(AssetDatabase.GetAssetPath(player.PlayedScript));

            if (requireReload)                         // In case the played script is stored outside of Unity project, force reload it.
            {
                var prevLineHashes = playedLineHashes; // Otherwise they're overridden when playing the loaded script below.
                var scriptName     = player.PlayedScript.Name;
                scriptManager.UnloadScript(scriptName);
                var script = await scriptManager.LoadScriptAsync(scriptName);

                player.Play(script, player.PlaybackSpot.LineIndex, player.PlaybackSpot.InlineIndex);
                playedLineHashes = prevLineHashes;
            }

            var lastPlayedLineIndex = (player.PlayedCommand ?? player.Playlist.Last()).PlaybackSpot.LineIndex;

            // Find the first modified line in the updated script (before the played line).
            var rollbackIndex = -1;

            for (int i = 0; i < lastPlayedLineIndex; i++)
            {
                if (!player.PlayedScript.Lines.IsIndexValid(i)) // The updated script ends before the currently played line.
                {
                    rollbackIndex = player.Playlist.GetCommandBeforeLine(i - 1, 0)?.PlaybackSpot.LineIndex ?? 0;
                    break;
                }

                var oldLineHash = playedLineHashes[i];
                var newLine     = player.PlayedScript.Lines[i];
                if (oldLineHash.EqualsFast(newLine.LineHash))
                {
                    continue;
                }

                rollbackIndex = player.Playlist.GetCommandBeforeLine(i, 0)?.PlaybackSpot.LineIndex ?? 0;
                break;
            }

            if (rollbackIndex > -1) // Script has changed before the played line.
            // Rollback to the line before the first modified one.
            {
                await stateManager.RollbackAsync(s => s.PlaybackSpot.LineIndex == rollbackIndex);
            }

            // Update the playlist and play.
            var resumeLineIndex = rollbackIndex > -1 ? rollbackIndex : lastPlayedLineIndex;
            var playlist        = new ScriptPlaylist(player.PlayedScript, scriptManager);
            var playlistIndex   = player.Playlist.FindIndex(c => c.PlaybackSpot.LineIndex == resumeLineIndex);

            player.Play(playlist, playlistIndex);

            if (player.WaitingForInput)
            {
                player.SetWaitingForInputEnabled(false);
            }
        }