~hristoast/hristoast

hristoast/site/blog/godot-engine-editing-gdscript-with-emacs.html -rw-r--r-- 10.5 KiB
c6cb18fbHristos N. Triantafillou End of an era a month ago
                                                                                
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
<h1 id="title">Godot Engine: Editing GDScript With Emacs</h1>

<div id="dates">
  <span>Posted: <time id="post-date">2021-12-24</time></span>
</div>

<p id="post-excerpt">
  <a href="https://godotengine.org/">Godot Engine</a> is an exquisitely powerful, free game engine. One of my favorite aspects of Godot is that its editor was created with Godot itself! And indeed, it's an excellent showcase of how the engine could be used for building a great GUI program. But as excellent as the editor is, including the code editor for the bespoke scripting language GDScript, as an Emacs user it doesn't quite fit into my workflow. Thankfully, Godot has support for the <a href="https://microsoft.github.io/language-server-protocol/">Language Server Protocol</a>, so I'm able to use Emacs in my game development workflow. In this post I'll describe what's required to do this, and how it compares to the stock Godot editor.
</p>

<div id="toc"></div>

<h3>Why Godot?</h3>

<p>
  There are countless options for game development, including robust engines such as: <a href="https://www.yoyogames.com/en/gamemaker">Game Maker</a>, <a href="https://www.unrealengine.com/">Unreal</a>, <a href="https://unity.com/">Unity</a>, and others, as well as more general and less featureful libraries that allow more freedom to do things in a specific way. Given these options, why choose Godot? I initially decided to try out Godot because I loved the fact that it was a totally free, permissably-licensed game engine that seemed pretty powerful.
</p>

<p>
  With the help of some great learning resources such as <a href="https://www.gdquest.com/">GDQuest</a>, I've gone from knowing almost nothing about creating games to being proficient enough to produce several small game demos. With this experience under my belt, I'm happy to say that Godot is not only conceptually awesome, but it's actually a joy to work with and a lot of fun.
</p>

<p>
  I've only written with GDScript, which will feel very familiar to those who know a bit of Python. However there's also GDNative, which allows writing C or C++, Mono support if you prefer C#, and no matter what language you choose to go with, it's relatively simple to export your game to a variety of platforms including: Linux, macOS, Windows, HTML5, and Android.
</p>

<h4>Why GDScript?</h4>

<p>
  Since Godot allows writing code in C, C++, and even C#, why would I want to use a custom language that's specific to the engine? Indeed, projects that demand high levels of performance could benefit greatly from skipping GDScript and going for a known, established alternative. But for me GDScript feels very familiar, like a "better Python" almost. Additionally: for the 2D games that I'm making, it should be more than performant enough to get the job done. <span class="footnote"> I love Python, but GDScript's tight integration with Godot is what really makes it great in my opinion.</span>
</p>

<h3>Why Emacs?</h3>

<p>
  If Godot is so great, why would I bother going through the extra work to use Emacs instead of its built-in code editor (which again, is quite nice)? It's a matter workflow, for me; the vast majority of my general text editing and basically all of my code writing is done in Emacs. I've got a <a href="/blog/my-custom-emacs-setup/">customized setup</a> including many personal changes and keybindings, so it's quite jarring to use another editor for any reason. Even if I think to myself "I'll just deal with the differences", I will inevitably find myself using Emacs-specific keybindings and patterns, and my workflow will be disrupted. Given the availability of LSP support for both Emacs and Godot, it just makes sense for me to go this route.
</p>

<h3>GDScript X Emacs</h3>

<p>
  With motivation out of the way: let's talk about the "how", starting with what's needed on the Emacs side of things and then moving on to what you need to do in the Godot editor itself.
</p>

<h4>Emacs Setup</h4>

<p>
  The list of requirements for Emacs is somewhat short, but it isn't without options.
</p>

<h5>lsp-mode (or eglot)</h5>

<p>
  The first thing you'll need is a functional LSP setup - with either <a href="https://emacs-lsp.github.io/lsp-mode/">lsp-mode</a> or <a href="https://github.com/joaotavora/eglot#m-x-eglot">eglot</a>. Going into the difference between these two and how to set either of them up, is outside of the scope of this post. I'm personally using lsp-mode rather than eglot, but I'm sure eglot would be just as functional. <span class="footnote"> Please refer to the relevant documentation for setting up either lsp-mode or eglot. If you aren't sure which you want, even after reading about both, just go with lsp-mode and revisit the question later on.</span>
</p>

<h5>gdscript-mode</h5>

<p>
  Next up you'll need <a href="https://github.com/godotengine/emacs-gdscript-mode#gdscript-mode-for-emacs">gdscript mode</a>. Aside from autocompletion offered by LSP integration, there are a few extra goodies that are worth considering:
</p>

<ul>
  <li><a href="https://github.com/godotengine/emacs-gdscript-mode#formatting-code-with-gdformat">Formatting code with gdformat</a>: this requires installing a Python package, but it's worth it. You can then set a <code>before-save</code> hook to run <code>gdscript-format-buffer</code> when you save to get an effect similar to what gofmt or Python black would get you - nicely and consistently-formatted code in every file.</li>
  <li><a href="https://github.com/godotengine/emacs-gdscript-mode#browsing-the-godot-api-with-eww">Browsing the Godot API with eww</a>: this one requires a local copy of <a href="https://github.com/godotengine/godot-docs/">the Godot docs repo</a>, but it'll get you functionality similar to what the Godot editor has; easy access to documentation for everything in the engine, right in your editor. It's definitely worth it, even if internet access isn't an issue for you. You can build the docs yourself; I was actually unable to successfully do so and ended up using an unofficial build that was recommended in the gdscript-mode README.</li>
</ul>

<h5>Emacs Daemon</h5>

<p>
  Running an Emacs daemon isn't strictly required, but I found that without it anytime I opened a new script, a totally new instance of Emacs would be opened. With the daemon, you can easily open new scripts in an existing Emacs frame (if you have one already open). I've written about setting up the Emacs daemon before, so please refer to those posts if you want a reference. <span class="footnote"> See: <a href="/blog/emacs-daemon-runit-service/">Emacs daemon as a runit service</a> and <a href="/blog/emacs-daemon-runit-user-service/">Emacs daemon as a runit "user service" </a></span>
</p>

<p>
  At this point, you should be ready to configure Godot to use an external editor.
</p>

<h4>Godot Editor Setup</h4>

<p>
  It's important to note that Emacs will not totally replace the Godot editor; you'll still use that for the scene editor and other things such as audio and animation editing. Emacs will take over code-editing duties, as well as debugging code.
</p>

<p>
  From the main Godot editor window, click the <code>Editor</code> menu, then <code>Editor Settings...</code>. This will open the "Editor Settings" window. In the lefthand pane scroll down to the "Text Editor" section and click "External". Check the box next to "Use External Editor", enter <code>emacsclient</code> for the "Exec Path" option, and <code>--socket-name=SOCKET_NAME_HERE -n {file} +{line}</code> for the "Exec Flags" option (changing the socket name to whatever yours is).
</p>

<img src="/i/godot-external-editor-settings.png" />

<p>
  That should be it; go ahead close the "Editor Settings" window, and open a script (make sure you've got an existing Emacs frame already opened). Emacs should take focus with the script you clicked open, with all the LSP features at your fingertips.
</p>

<h3>Results</h3>

<p>
  And now for the burning questions: how is it, and is it good enough to use instead of the stock Godot editor?
</p>

<p>
  I'm pleased to report that: it's pretty great, and <span class="bold">yes</span> it is! But it isn't a one-to-one experience. Here are some problems I've encountered:
</p>

<ul>
  <li>It is quite a bit slower than using Godot's built-in code editor. Most of the time it's not so bad, but every now and then I'll see some major unresponsiveness from LSP stuff like autocompletion and so on. I can still type into Emacs and otherwise use it, but the performance of LSP features seems to greatly vary. I think this is something that could be improved, although for now I've yet to dive into where the problem is. <span class="footnote"> This also results in a somewhat visually jarring experience. At least compared to the experience I have with other languages and lsp-mode, such as Go.</span></li>
  <li>Some nice things are missing such as the ability to open other scripts by clicking on <code>res://</code> links.</li>
  <li>Some things are autocompleted incorrectly. For instance when you autocomplete a <code>_ready</code> method, it erroneously adds a <code>()</code> after the colon at the end of the func definition. This is incorrect syntax and requires a few keystrokes to correct on my part.</li>
  <li>I've yet to use debugger via Emacs, but I have a feeling it isn't going to be quite as slick as the one built into Godot's editor. There's just a lot of UI/UX that seems like it will be tough to map over to Emacs without some amazing Magit-like interface. Once I actually get to using this feature, I'll update the post and describe my experience.</li>
</ul>

<p>
  As I re-read over the points above, it does sound kinda bleak. But honestly the overall experience is awesome. Even with the quirks I mentioned above, being able to integrate Emacs with the Godot editor as much as I can is really huge for me. If I wasn't so invested in Emacs I'm not sure if the experience would be acceptable, but as an Emacs user I love what we've got and am looking forward to building out and improving the ecosystem.
</p>

<p>
  I'll also update this post when I finish the demo I'm currently working on, just to give readers a sample of what I'm trying to do here. For now, have a gif of me writing some GDScript with Emacs: <span class="footnote"> This gif was created with <a href="https://gitlab.com/ambrevar/emacs-gif-screencast">emacs-gif-screencast</a>. The code is based on GDQuest's <a href="https://github.com/GDQuest/godot-make-pro-2d-games">Make Pro 2d Games with Godot Open Source A-RPG Demo</a> project. Big thanks and a lot of respect to the GDQuest folks!</span>
</p>

<img src="/i/editing-gdscript-with-emacs.gif" />

<h3>Footnotes And References</h3>

<div id="footnotes"></div>