Unity 捕获IronPython脚本错误

捕获的方法摘自《IronPython in Action》一书,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

using IronPython.Hosting;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using Microsoft.Scripting;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Hosting;

using Plugins;


namespace EmbeddingPlugin
{
     internal  class PythonStream: MemoryStream
    {
        TextBox _output;
         public PythonStream(TextBox textbox)
        {
            _output = textbox;
        }

         public  override  void Write( byte[] buffer,  int offset,  int count)
        {
            _output.AppendText(Encoding.UTF8.GetString(buffer, offset, count));
        }
    }

     internal  class Engine
    {
        ScriptEngine _engine;
        ScriptRuntime _runtime;
        TextBox _box;

         public List<PluginBase> Plugins
        {
            get {  return PluginStore.Plugins; }
        }


         public Engine(TextBox textbox)
        {
            _engine = Python.CreateEngine();
            _runtime = _engine.Runtime;
            _box = textbox;

            SetStreams();
             string rootDir = AddAssemblies();
            LoadPlugins(rootDir);
        }

         public  void SetStreams()
        {
            PythonStream stream =  new PythonStream(_box);
            _runtime.IO.SetOutput(stream, Encoding.UTF8);
            _runtime.IO.SetErrorOutput(stream, Encoding.UTF8);
        }

         public  string AddAssemblies()
        {
            Assembly mainAssembly = Assembly.GetExecutingAssembly();

             string rootDir = Directory.GetParent(mainAssembly.Location).FullName;
             string pluginsPath = Path.Combine(rootDir,  "Plugins.dll");

            Assembly pluginsAssembly = Assembly.LoadFile(pluginsPath);

            _runtime.LoadAssembly(mainAssembly);
            _runtime.LoadAssembly(pluginsAssembly);
            _runtime.LoadAssembly( typeof(String).Assembly);
            _runtime.LoadAssembly( typeof(Uri).Assembly);

             return rootDir;
        }

         public  void LoadPlugins( string rootDir)
        {
             string pluginsDir = Path.Combine(rootDir,  "plugins");
             foreach ( string path  in Directory.GetFiles(pluginsDir))
            {
                 if (path.ToLower().EndsWith( ".py"))
                {
                    CreatePlugin(path);
                }
            }
        }

         public  void CreatePlugin( string path)
        {
             try
            {
                ScriptSource script = _engine.CreateScriptSourceFromFile(path);
                CompiledCode code = script.Compile();
                ScriptScope scope = _engine.CreateScope();
                script.Execute(scope);
            }
             catch (SyntaxErrorException e)
            {
                 string msg =  "Syntax error in \"{0}\"";
                ShowError(msg, Path.GetFileName(path), e);
            }
             catch (SystemExitException e)
            {
                 string msg =  "SystemExit in \"{0}\"";
                ShowError(msg, Path.GetFileName(path), e);
            }

             catch (Exception e)
            {
                 string msg =  "Error loading plugin \"{0}\"";
                ShowError(msg, Path.GetFileName(path), e);
            }
        }

         public  void ShowError( string title,  string name, Exception e)
        {
             string caption = String.Format(title, name);
            ExceptionOperations eo = _engine.GetService<ExceptionOperations>();
             string error = eo.FormatException(e);
            MessageBox.Show(error, caption, MessageBoxButtons.OK, MessageBoxIcon.Error);

        }

         public  void ExecutePluginAtIndex( int index)
        {
            PluginBase plugin = Plugins[index];

             try
            {
                plugin.Execute(_box);
            }
             catch (Exception e)
            {
                 string msg =  "Error executing plugin \"{0}\"";
                ShowError(msg, plugin.Name, e);
            }
        }
    }
}

结果如:

移植到Unity中,则只取关键性代码即可。

### 如何在 Unity 中集成和使用 Python 脚本 #### 使用插件实现无缝集成 为了实现在Unity中直接运行Python代码,可以借助专门设计用于此目的的插件。例如`unity-python`这个工具就是一个适用于Unity3D的Python插件,它允许开发者无需额外配置就能轻松地在游戏引擎内部执行Python脚本[^2]。 #### 安装与设置 对于希望在Unity环境中加入Python支持的情况,一种常见的方式是按照特定指南完成开发环境的搭建工作。这通常涉及到下载并安装必要的组件以及确保两者之间能够正常交互[^1]。 #### C# 和 Python 的通信机制 当考虑将Python逻辑嵌入到基于C#编写的Unity应用程序里时,可以通过多种手段达成目标之一便是利用命令行接口来启动外部Python进程,并捕捉其标准输出作为响应数据。这种方法虽然简单直接但却可能带来性能上的开销[^3]。 ```csharp using System.Diagnostics; // 创建一个新的ProcessStartInfo对象指定要执行的文件路径及参数 var start = new ProcessStartInfo(); start.FileName = "python"; // 或者 python.exe, 取决于系统的默认解释器名称 start.Arguments = string.Format("{0} {1}", scriptPath, argument); start.UseShellExecute = false; start.RedirectStandardOutput = true; using (Process process = Process.Start(start)) { using (StreamReader reader = process.StandardOutput) { string result = reader.ReadToEnd(); Console.Write(result); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值