mirror of
https://github.com/godotengine/godot-website.git
synced 2025-12-31 09:48:43 +03:00
77 lines
31 KiB
HTML
77 lines
31 KiB
HTML
<!doctype html><html lang=en><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Godot Engine"><meta name=description content="A short introduction to the new GDNative module (formerly DLScript) and how to use it in a project. This is a very early version, but the overall process will stay the same."><script defer data-domain=godotengine.org src=https://plausible.godot.foundation/js/script.file-downloads.outbound-links.js></script><meta property="og:site_name" content="Godot Engine"><meta property="og:url" content="https://godotengine.org/article/dlscript-here/"><meta property="og:type" content="website"><meta property="og:description" content="A short introduction to the new GDNative module (formerly DLScript) and how to use it in a project. This is a very early version, but the overall process will stay the same."><meta property="og:image" content="https://godotengine.org/storage/app/uploads/public/58e/4eb/cb6/58e4ebcb63d98659868573.png"><meta name=twitter:card content="summary_large_image"><meta property="twitter:domain" content="godotengine.org"><meta property="twitter:url" content="https://godotengine.org/article/dlscript-here/"><meta property="og:title" content="GDNative is here! – Godot Engine"><title>GDNative is here! – Godot Engine</title>
|
||
<link rel=alternate type=application/rss+xml title="Godot News" href=/rss.xml><link rel=alternate type=application/json title="Godot News" href=/rss.json><link rel=alternate type=application/atom+xml title="Godot News" href=/atom.xml><link rel=icon href=/assets/favicon.png sizes=any><link rel=icon href=/assets/favicon.svg type=image/svg+xml><link rel=stylesheet href=/assets/css/main.css?121><link rel=stylesheet href=/assets/css/header.css?6><link rel=stylesheet href=/assets/css/tobii.min.css><link rel=preload as=font href=/assets/fonts/Montserrat-Italic-VariableFont_wght.woff2 crossorigin><link rel=preload as=font href=/assets/fonts/Montserrat-VariableFont_wght.woff2 crossorigin><link rel=me href=https://mastodon.gamedev.place/@godotengine><style>.donation-header{background-color:#ffa700;color:#000;padding:15px;text-align:center;padding:40px 15px;font-size:1.5em;display:none}.donation-header.visible{display:block}.donation-header h2{color:#000;margin-bottom:0;font-size:1.5em}.donation-header p{margin-top:0}.donation-header img{position:absolute;right:10px;top:10px;filter:invert(1);cursor:pointer}.donation-header .btn{background:#000;color:#fff}@media(max-width:600px){.donation-header{font-size:1.2em}}</style><div class=donation-header id=donation-header><img src=/assets/icons/cross.svg width=24 height=24 alt=Close title=Close id=donation-header-close onclick=dismissHeader()><h2>Donate to Godot!</h2><p>This has been a great year for the engine, but there are still a lot of things we would love to do.<br>If everyone visiting the site would donate €5, we could hire 5 more developers to work on Godot full-time.<br></p><a class=btn href="https://fund.godotengine.org/?ref=december-2025" onclick=dismissHeader(!0)>Donate Now</a></div><script>function dismissHeader(e=!1){var t=new Date;e?t.setTime(t.getTime()+30*24*60*60*1e3):(t.setTime(t.getTime()+48*60*60*1e3),document.getElementById("donation-header").classList.remove("visible")),document.cookie="donationHeaderClosed=1;expires="+t.toUTCString()+";path=/"}document.addEventListener("DOMContentLoaded",function(){var e=document.getElementById("donation-header");document.cookie.includes("donationHeaderClosed=1")||e.classList.add("visible")})</script><input type=checkbox id=nav_toggle_cb><header class="flex column"><div class="container flex align-center"><div id=nav_head><a href=/ id=logo-link><img class=nav-logo src=/assets/logo.svg width=136 height=48 alt="Godot Engine">
|
||
<img class="nav-logo dark-logo" src=/assets/logo_dark.svg width=136 height=48 alt="Godot Engine"></a><div class=mobile-links><span class="fund mobile"><a href=https://fund.godotengine.org><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="width:13px;fill:#fff;margin-right:4px"><path d="M47.6 300.4 228.3 469.1c7.5 7 17.4 10.9 27.7 10.9s20.2-3.9 27.7-10.9L464.4 300.4c30.4-28.3 47.6-68 47.6-109.5v-5.8c0-69.9-50.5-129.5-119.4-141C347 36.5 300.6 51.4 268 84L256 96 244 84c-32.6-32.6-79-47.5-124.6-39.9C50.5 55.6.0 115.2.0 185.1v5.8c0 41.5 17.2 81.2 47.6 109.5z"/></svg> Donate</a></span>
|
||
<label for=nav_toggle_cb id=nav_toggle_btn><img src=/assets/icons/hamburger.svg width=24 height=24 alt="Main menu"></label></div></div><nav id=nav><ul class=left><li><a href=/features/ data-dropdown=features-dropdown>Features</a><li class=mobile-only><a href=/consoles/>Console support</a><li class=mobile-only><a href=/priorities/>Priorities</a><li><a href=/showcase/>Showcase</a><li><a href=/blog/>Blog</a><li><a href=/community/ data-dropdown=community-dropdown>Community</a><li><a href=https://godotengine.org/asset-library/asset>Assets</a></ul><ul class=right><li><a href=/download/windows/ class=set-os-download-url>Download</a><li><a href=https://docs.godotengine.org>Docs</a><li><a href=https://contributing.godotengine.org/en/latest/organization/how_to_contribute.html>Contribute</a><li class="fund desktop"><a href=https://fund.godotengine.org><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="width:13px;fill:#fff;margin-right:4px;top:1px;position:relative"><path d="M47.6 300.4 228.3 469.1c7.5 7 17.4 10.9 27.7 10.9s20.2-3.9 27.7-10.9L464.4 300.4c30.4-28.3 47.6-68 47.6-109.5v-5.8c0-69.9-50.5-129.5-119.4-141C347 36.5 300.6 51.4 268 84L256 96 244 84c-32.6-32.6-79-47.5-124.6-39.9C50.5 55.6.0 115.2.0 185.1v5.8c0 41.5 17.2 81.2 47.6 109.5z"/></svg> Donate</a></ul></nav></div></header><div class=nav-dropdown-menu id=features-dropdown><a href=/features/ class=touch-only>Features</a>
|
||
<a href=/consoles/>Console support</a>
|
||
<a href=/priorities/>Priorities</a></div><div class=nav-dropdown-menu id=community-dropdown><a href=/community/ class=touch-only>Community</a>
|
||
<a href=https://forum.godotengine.org>Forum</a>
|
||
<a href=/events/>Events</a></div><script>document.addEventListener("DOMContentLoaded",function(){const e=document.querySelectorAll("[data-dropdown]");e.forEach(e=>{const n=e.getAttribute("data-dropdown"),t=document.getElementById(n);if(t){let n=-1;const i=()=>{if(n===-1)return;clearTimeout(n),n=-1},a=()=>t.style.display==="block",r=()=>{if(a())return;if(window.innerWidth<1200)return;i();const n=e.getBoundingClientRect();t.style.top=n.bottom+"px",t.style.left=n.left+"px",t.style.display="block",e.classList.add("dropdown-open")},s=({instant:s=!1}={})=>{if(!a())return;const o=()=>{i(),t.style.display="none",e.classList.remove("dropdown-open")};if(s){o();return}n=setTimeout(o,100)},l=e=>{if(window.innerWidth<1200)return;e.preventDefault(),a()?s({instant:!0}):r()},c=e=>t=>{t.pointerType==="touch"&&e(t)},o=e=>t=>{t.pointerType!=="touch"&&e(t)};e.addEventListener("pointerup",c(e=>l(e))),document.documentElement.addEventListener("pointerup",c(n=>{!e.contains(n.target)&&!t.contains(n.target)&&s({instant:!0})})),e.addEventListener("pointerenter",o(e=>r())),e.addEventListener("pointerleave",o(e=>s())),t.addEventListener("pointerenter",o(e=>i())),t.addEventListener("pointerleave",o(e=>s()))}})})</script><main><style>body{background-color:var(--background-color)}h1{margin-bottom:8px;margin-top:32px}:not(pre)>code{background:var(--code-background-color);padding:1px 4px;font-size:.95em;border-radius:3px}pre{background:var(--codeblock-background-color);color:var(--codeblock-color)}pre code{display:block;overflow-x:auto;padding:.5em}.date-big{line-height:2;margin-left:32px}article{background-color:var(--base-color);box-shadow:0 3px 2px rgba(0,0,0,.15)}figure{margin:0}figure img{margin:0}article img,article video{max-width:100%;height:auto;display:block;margin:auto;margin-top:16px;margin-bottom:16px}article h1{margin-top:64px}article h2,article h3,article h4{margin-top:42px}.article-info{display:flex;flex-direction:column;gap:8px}.article-metadata{display:flex;gap:24px;align-items:center;font-family:var(--header-font-family);margin-bottom:12px}@media(max-width:900px){.article-metadata{flex-direction:column;align-items:flex-start;gap:16px}}.article-author{color:var(--base-color-text-subtitle-date);font-weight:700;font-size:18px;flex-grow:1;display:flex;gap:12px;align-items:center}.article-author .avatar{border-radius:100%;margin:0;background:0 0}.article-author .by{color:var(--base-color-text-subtitle)}.article-metadata .date{color:var(--base-color-text-subtitle-date)}.article-metadata .date.post-recent-highlight{color:var(--post-recent-highlight-color);opacity:.8}.article-metadata .date.post-recent-highlight::after{font-size:80%;content:"NEW";border:2px solid var(--post-recent-highlight-color);padding:2px 3px;margin-left:8px}.tag.active{filter:saturate(.75)}@media screen and (min-width:900px){article .content{width:70%;margin:auto}}@media(max-width:900px){body{background-color:var(--base-color)}article{background-color:initial;box-shadow:none}article img:first-child,article video:first-child{max-width:100%}}.blog-navigation{display:grid;grid-template-columns:1fr 1fr;padding-top:30px;padding-bottom:60px}.blog-navigation .next{text-align:right}@media(max-width:900px){.blog-navigation{grid-template-columns:1fr;gap:20px;border-top:1px solid var(--code-background-color)}.blog-navigation .next{text-align:left}}.blog-navigation span{opacity:.6;font-weight:700;margin-bottom:5px;display:block}.blog-navigation a{display:inline-block;text-decoration:none;color:inherit;opacity:.6;transition:opacity .2s}.blog-navigation a:hover{opacity:1}</style><link rel=stylesheet href=/assets/css/highlight.obsidian.min.css><div class=container><article class=padded><div class="content article-container"><figure class=article-cover><img src=/storage/app/uploads/public/58e/4eb/cb6/58e4ebcb63d98659868573.png title alt=" " class=rounded-lg style=width:100%;height:auto;background-color:initial></figure><div class=article-info><h1>GDNative is here!</h1><div class=article-metadata><div class=article-author><span>By: </span><img class=avatar width=25 height=25 src=/assets/images/authors/default_avatar.svg alt=karroffel loading=lazy>
|
||
<span class=by>karroffel</span></div><span class=date data-post-date="2017-04-05 00:00:00 +0000">5 April 2017</span></div><div class=tags><a href=/blog/progress-report><div class="tag active">Progress Report</div></a></div></div><div class="card card-warning"><p>This article is from <strong>April 2017</strong>, some of its contents might be outdated and no longer accurate.<br>You can find up-to-date information about the engine in the <a href=https://docs.godotengine.org/en/stable/>official documentation</a>.</div><div class=article-body><p><strong>Edit:</strong> Based on community feedback and to avoid confusion (DLScript is not yet another domain specific language), the module was renamed to <em>GDNative</em>.<hr><p>… at least the first usable version, there’s still work to do, <em>but</em> it’s usable!<p>As some of you might have heard, we were working on a module that lets you use shared libraries as scripts.<p>I’ll explain what GDNative exactly is, what it is <em>not</em>, what you can use it for and lastly show you <em>how</em> to use it.<h2 id=so-what-is-gdnative>So what is GDNative?</h2><p>It is a module for Godot that adds a new “scripting language” to it. I put “scripting language” in quotes because it’s not a language.<p>A “script” in Godot is defined as something that has methods, properties and signals.
|
||
It also offers a way to use these things (calling methods, get and set properties…).
|
||
Instead of having a text file representing these things (like a GDScript file for example),
|
||
GDNative uses shared libraries, which can be attached to nodes via <em>Native</em> “scripts”.<p>In some ways, shared libraries have things in common with scripts.<ul><li>you can load them<li>you can unload them<li>you can load function symbols<li>you can call functions</ul><p>A method in a Native script is just native machine code. You can call third party libraries from that code as well.
|
||
You can call GDScript functions from a Native script and vice versa. When C# will be supported optionally, you’ll be able to call C# code as well.<h2 id=so-what-is-gdnative-not>So what is GDNative not?</h2><p>I want to keep this section short. A Native script is not a module.
|
||
Modules have access to all the C++ classes available in Godot and can extend engine functionality.
|
||
You want a different renderer? Module. You want to add networking capabilities to all nodes (<a href=/article/godots-new-high-level-networking-preview><em>ahem</em></a>)? Modules.<p>“A Native script”, as in “a script you’re writing”, is just a script, just like a GDScript file, so it doesn’t have access to those classes, it also can’t extend engine functionality.
|
||
But it has access to the whole script API (aka the class API you know from the <a href=http://docs.godotengine.org/en/latest/classes/>docs</a>).<p>This is one way of communication. A Native script can access the class API and can register methods and properties.<p><img src=/storage/app/media/dlscript/godot_dlscript.png alt=godot_dlscript><p>The other way is like the opposite direction: a Native script can also access code from third party libraries.<p><img src=/storage/app/media/dlscript/godot_dlscript_thirdparty.png alt=godot_dlscript_thirdparty><p>Methods that are registered to the scripting system can call third party code, but a Native script can’t integrate something into the engine - it can only “proxy” direct calls.<p>So Native scripts can’t “hack the engine”, but you can build some nice scripts that enable you to use the steamworks API, or Google Play Services <strong>without recompiling the engine</strong>.<h2 id=what-can-you-use-gdnative-for>What can you use GDNative for?</h2><p>There are basically two big use cases:<ul><li><p><strong>performance critical code</strong>. GDScript is an excellent language for making games and quick prototyping. It was designed with simplicity in mind, not performance. Some users report that they reached GDScript’s limits while e.g. procedurally generating terrain. Since GDNative runs native code it has literally <em>zero</em> overhead when it comes to raw computation power (provided you don’t make calls into the script system all the time).<li><p><strong>binding third party code to Godot</strong>. The nature of dynamic linking allows Native scripts to load other libraries as well - and use those. Like explained above, Native scripts are not a replacement for modules, but for binding an independent library (for example steamworks) it’s a much better choice than developing a module.</ul><h2 id=how-to-use-gdnative>How to use GDNative?</h2><p>This part is like a little tutorial to get you started.<p>I mentioned that GDNative is not a <em>language</em>. It loads shared libraries. These shared libraries can be written in any language you want. Godot just needs to know how to use them.
|
||
Because of that, there’s no code editor for GDNative in the Godot editor. Because <em>there is no source code</em>. There only is a shared library, nothing more, nothing less.
|
||
So you have to write your code outside of the editor.<p>The GDNative API is a C API. Because writing code in C (especially more “high level code” like you’d write for Godot) can get very messy very fast I wrote C++ bindings.
|
||
I’ll show how to use these C++ bindings to write a script for a node.<p>You’ll need a relatively fresh build of Godot (for example from <a href=https://github.com/GodotBuilder/godot-builds/releases/tag/master_20170405>here</a>, or you can build it yourself (or wait for 3.0)).
|
||
Like I said, the GDNative API is a C API, so you’ll need headers to access this C API. Additionally you want C++ headers to use the C++ bindings. You can download a <em>starter kit</em> <a href=https://github.com/GodotNativeTools/cpp_bindings/releases/download/starter_kit/godot_cpp_starter_kit.zip>here</a>.<p>This starter kit is just to get you started. It’ll probably be outdated very soon. New versions of the C++ bindings and the C Headers can be found <a href=https://github.com/GodotNativeTools/cpp_bindings>here</a> and <a href=https://github.com/GodotNativeTools/godot_headers>here</a>. Since this is all very WIP, it’s possible that there are no recent uploaded binaries for you on these repos. Just be patient or get in touch with me (you can find out how on the bottom of this blog).<p>Just leave the starter kit alone for now. We’ll create a project and a very basic scene first.
|
||
(If you are not familiar with making scenes and setting up nodes you should check out the <a href=http://docs.godotengine.org/en/latest/learning/step_by_step/>step by step tutorial</a>)<h3 id=setting-up-the-scene>Setting up the scene</h3><p>Create a project and set up the scene. I just created a Node2D as the root node, added a KinematicBody2D and a Sprite using the lovely default icon.<p><img src=/storage/app/media/dlscript/tutorial/scene_setup.png alt><p>I saved the scene in the project root with the name <code class="language-plaintext highlighter-rouge">main.tscn</code>.<p>Okay, for now that’s all we do with the scene. Now we’ll set up the code for the library. For that you should unpack the zip file you downloaded earlier in your project root.
|
||
Your project directory should now look like this. (and two .dll files lying around there too)<p><img src=/storage/app/media/dlscript/tutorial/project_organization.png alt><h3 id=building-the-library>Building the library</h3><p>The <code class="language-plaintext highlighter-rouge">include</code> directory contains all the needed headers. The <code class="language-plaintext highlighter-rouge">lib</code> directory contains the C++ binding implementation. We’ll also compile our game code library into that directory. The <code class="language-plaintext highlighter-rouge">src</code> directory will contain the source code from which we’ll build the library for our game. It contains a simple build script. Fill in the name of the project (into the variable <code class="language-plaintext highlighter-rouge">project_name</code>) in the SConstruct file.<p>For this example, we’ll create a class called <code class="language-plaintext highlighter-rouge">Player</code> that will move the KinematicBody2D.<p>Add a file <code class="language-plaintext highlighter-rouge">src/init.cpp</code>. For simplicity we’ll have all the code in this file. For a more serious project you’d want to split the code in headers and implementations.<p>Write following code into the <code class="language-plaintext highlighter-rouge">src/init.cpp</code> file:<div class="language-plaintext highlighter-rouge"><div class=highlight><pre class=highlight><code>#include <godot_cpp/Godot.hpp>
|
||
|
||
#include <godot_cpp/KinematicBody2D.hpp>
|
||
#include <godot_cpp/Input.hpp>
|
||
|
||
using namespace godot;
|
||
|
||
class Player : public KinematicBody2D {
|
||
GODOT_CLASS(Player, KinematicBody2D)
|
||
|
||
float speed = 200; // pixel/second
|
||
|
||
public:
|
||
|
||
void _fixed_process(float delta)
|
||
{
|
||
Vector2 input;
|
||
|
||
if (Input::is_action_pressed("ui_up")) {
|
||
input.y -= 1;
|
||
}
|
||
if (Input::is_action_pressed("ui_down")) {
|
||
input.y += 1;
|
||
}
|
||
if (Input::is_action_pressed("ui_left")) {
|
||
input.x -= 1;
|
||
}
|
||
if (Input::is_action_pressed("ui_right")) {
|
||
input.x += 1;
|
||
}
|
||
|
||
self->move(input.normalized() * speed * delta);
|
||
}
|
||
|
||
static void _register_methods()
|
||
{
|
||
register_method("_fixed_process", &Player::_fixed_process);
|
||
}
|
||
|
||
};
|
||
|
||
GODOT_DLSCRIPT_INIT(godot_dlscript_init_options *options)
|
||
{
|
||
register_class<Player>();
|
||
}
|
||
</code></pre></div></div><p>If you open a terminal in <code class="language-plaintext highlighter-rouge">src/</code> and execute <code class="language-plaintext highlighter-rouge">scons p=linux</code> (or <code class="language-plaintext highlighter-rouge">scons p=windows</code> for windows) then you should see it successfully compile the code into a library in <code class="language-plaintext highlighter-rouge">lib/</code>.<p>Ok, now we only need to do two more things.<ul><li>add a Native script to the KinematicBody2D<li>tell Godot where it can find our library</ul><p>To add a Native script to the node you attach a script as always <em>but select Native and type in “Player” for the class name</em>. Also I’m going to use a built-in-script.<p><img src=/storage/app/media/dlscript/tutorial/attach_script.png alt><p><em>Edit:</em> Since DLScript was renamed to GDNative, the above screenshot is now slightly inaccurate, but should give the idea.<p>This was the “add a Native script to the node” part. Now we need to tell Godot in which library it can find our class definition.<p><img src=/storage/app/media/dlscript/tutorial/new_dllibrary.png alt><p>Then click the small arrow to the right, fill in path to (<code class="language-plaintext highlighter-rouge">lib/</code> + projectname) for your OS.
|
||
Then save it under <code class="language-plaintext highlighter-rouge">lib/library.tres</code>.<p><img src=/storage/app/media/dlscript/tutorial/save_dllibrary.png alt><p>If you play the scene now, you should be able to control the icon with your arrow keys.<h2 id=further-notes>Further notes</h2><p>This C++ binding is subject to change. It’s more low level and most stuff is still undocumented (did you notice the <code class="language-plaintext highlighter-rouge">self->move(...)</code>? You need to use <code class="language-plaintext highlighter-rouge">self</code> to refer to the node the current class is attached to).
|
||
I’ll write documentation for the C++ bindings. I’ll also write documentation for the C API so the community can create their own language bindings.<p>I also mentioned that the GDNative module still needs some work. For example in-editor initialization of libraries is currently disabled. This feature is required to have exported properties and signals. This doesn’t really make sense without proper reloading of libraries. This is on my TODO list, but everyone is welcome to help with that task.
|
||
If you’re interested, message me (<em>karroffel</em>) on IRC or Discord.<p>Thanks for reading this and happy waiting for Godot!</div></div></article><div class=blog-navigation><div class=previous><span>Previous</span>
|
||
<a rel=prev href=/article/meet-nodes-godot-event-paris/>Meet the Nodes - Godot event in Paris</a></div><div class=next><span>Next</span>
|
||
<a rel=next href=/article/godot-30-progress-report-6/>Godot 3.0 progress report #6</a></div></div></div><link rel=stylesheet href=/assets/css/anchor-link.css?1><link rel=stylesheet href=/assets/css/article-cards.css?3><script src=/assets/js/anchor-link.js></script><script>document.addEventListener("DOMContentLoaded",()=>{window.applyAnchorLinks(".article-body"),document.querySelectorAll(".article-cover img, .article-body img").forEach(e=>{if(e.classList.contains("lightbox-ignore"))return;const t=document.createElement("a");t.href=e.src,t.classList.add("lightbox"),t.dataset.group="article",e.parentNode.appendChild(t),t.appendChild(e)})})</script></main><footer class=footer-global><div class=wrapper><div class=columns><div class=col><h2>Godot Engine</h2><ul><li><a class=set-os-download-url href=/download>Download</a><li><a href=https://docs.godotengine.org>Documentation</a><li><a href=/features/>Features</a><li><a href=https://editor.godotengine.org/releases/latest/>Web editor</a><li><a href=/download/archive/>Release archive</a><li><a href=https://github.com/godotengine>Source code</a></ul></div><div class=col><h2>Project</h2><ul><li><a href=/blog/>Blog</a><li><a href=/code-of-conduct/>Code of conduct</a><li><a href=/governance/>Governance</a><li><a href=/teams/>Teams</a><li><a href=/priorities/>Priorities</a><li><a href=/community/>Communities</a></ul></div><div class=col><h2>Resources</h2><ul><li><a href=https://godotengine.org/asset-library/asset>Asset library</a><li><a href=/press/>Press kit</a><li><a href=/showcase/>Showcase</a><li><a href=/education/>Education</a><li><a href=/consoles/>Console support</a></ul></div><div class=col><h2>Foundation</h2><ul><li><a href=https://godot.foundation/>About</a><li><a href=https://fund.godotengine.org>Donate</a><li><a href=/license/>License</a><li><a href=/privacy-policy/>Privacy policy</a><li><a href=/contact/>Contact us</a></ul></div></div><hr><div class=credits-and-socials><p>© 2007-2025 Juan Linietsky, Ariel Manzur and <a href=https://github.com/godotengine/godot/blob/master/AUTHORS.md target=_blank rel=noopener>contributors</a>. Hosted by the <a href=https://godot.foundation/ target=_blank rel=noopener>Godot Foundation</a>. Website <a href=https://github.com/godotengine/godot-website target=_blank rel=noopener>source code on GitHub</a>.<div class=social><a href=https://github.com/godotengine target=_blank rel=noopener title=GitHub><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6.0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6.0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3.0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1.0-6.2-.3-40.4-.3-61.4.0.0-70 15-84.7-29.8.0.0-11.4-29.1-27.8-36.6.0.0-22.9-15.7 1.6-15.4.0.0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5.0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9.0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4.0 33.7-.3 75.4-.3 83.6.0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6.0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9.0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
||
</a><a href=https://bsky.app/profile/godotengine.org target=_blank rel=noopener title=Bluesky><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M407.8 294.7c-3.3-.4-6.7-.8-10-1.3 3.4.4 6.7.9 10 1.3zM288 227.1C261.9 176.4 190.9 81.9 124.9 35.3 61.6-9.4 37.5-1.7 21.6 5.5 3.3 13.8.0 41.9.0 58.4S9.1 194 15 213.9c19.5 65.7 89.1 87.9 153.2 80.7 3.3-.5 6.6-.9 10-1.4-3.3.5-6.6 1-10 1.4-93.9 14-177.3 48.2-67.9 169.9C220.6 589.1 265.1 437.8 288 361.1c22.9 76.7 49.2 222.5 185.6 103.4 102.4-103.4 28.1-156-65.8-169.9-3.3-.4-6.7-.8-10-1.3 3.4.4 6.7.9 10 1.3 64.1 7.1 133.6-15.1 153.2-80.7C566.9 194 576 75 576 58.4s-3.3-44.7-21.6-52.9c-15.8-7.1-40-14.9-103.2 29.8C385.1 81.9 314.1 176.4 288 227.1z"/></svg>
|
||
</a><a href=https://mastodon.gamedev.place/@godotengine target=_blank rel=noopener title=Mastodon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M433 179.1c0-97.2-63.7-125.7-63.7-125.7-62.5-28.7-228.6-28.4-290.5.0.0.0-63.7 28.5-63.7 125.7.0 115.7-6.6 259.4 105.6 289.1 40.5 10.7 75.3 13 103.3 11.4 50.8-2.8 79.3-18.1 79.3-18.1l-1.7-36.9s-36.3 11.4-77.1 10.1c-40.4-1.4-83-4.4-89.6-54a102.5 102.5.0 01-.9-13.9c85.6 20.9 158.7 9.1 178.8 6.7 56.1-6.7 105-41.3 111.2-72.9 9.8-49.8 9-121.5 9-121.5zm-75.1 125.2h-46.6V190.1c0-49.7-64-51.6-64 6.9v62.5H201V197c0-58.5-64-56.6-64-6.9v114.2H90.2c0-122.1-5.2-147.9 18.4-175 25.9-28.9 79.8-30.8 103.8 6.1l11.6 19.5 11.6-19.5c24.1-37.1 78.1-34.8 103.8-6.1 23.7 27.3 18.4 53 18.4 175z"/></svg>
|
||
</a><a href=https://discord.gg/godotengine target=_blank rel=noopener title=Discord><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M524.5 69.8a1.5 1.5.0 00-.8-.7A485.1 485.1.0 00404.1 32a1.8 1.8.0 00-1.9.9 337.5 337.5.0 00-14.9 30.6 447.8 447.8.0 00-134.4.0 309.5 309.5.0 00-15.1-30.6 1.9 1.9.0 00-1.9-.9A483.7 483.7.0 00116.1 69.1a1.7 1.7.0 00-.8.7C39.1 183.7 18.2 294.7 28.4 404.4a2 2 0 00.8 1.4A487.7 487.7.0 00176 479.9a1.9 1.9.0 002.1-.7 348.2 348.2.0 0030-48.8 1.9 1.9.0 00-1-2.6 321.2 321.2.0 01-45.9-21.9 1.9 1.9.0 01-.2-3.1c3.1-2.3 6.2-4.7 9.1-7.1a1.8 1.8.0 011.9-.3c96.2 43.9 200.4 43.9 295.5.0a1.8 1.8.0 011.9.2c2.9 2.4 6 4.9 9.1 7.2a1.9 1.9.0 01-.2 3.1 301.4 301.4.0 01-45.9 21.8 1.9 1.9.0 00-1 2.6 391.1 391.1.0 0030 48.8 1.9 1.9.0 002.1.7 486 486 0 00147.2-74.1 1.9 1.9.0 00.8-1.4c12.2-126.7-20.6-236.8-87-334.5zm-302 267.8c-29 0-52.8-26.6-52.8-59.2s23.4-59.3 52.8-59.3c29.7.0 53.3 26.8 52.8 59.2.0 32.7-23.4 59.3-52.8 59.3zm195.4.0c-29 0-52.8-26.6-52.8-59.2s23.3-59.3 52.8-59.3c29.7.0 53.3 26.8 52.8 59.2.0 32.7-23.2 59.3-52.8 59.3z"/></svg>
|
||
</a><a href=https://www.reddit.com/r/godot title=Reddit target=_blank rel=noopener><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M0 256C0 114.6 114.6.0 256 0S512 114.6 512 256 397.4 512 256 512H37.1c-13.7.0-20.5-16.5-10.9-26.2L75 437C28.7 390.7.0 326.7.0 256zM349.6 153.6c23.6.0 42.7-19.1 42.7-42.7s-19.1-42.7-42.7-42.7c-20.6.0-37.8 14.6-41.8 34-34.5 3.7-61.4 33-61.4 68.4v.2c-37.5 1.6-71.8 12.3-99 29.1-10.1-7.8-22.8-12.5-36.5-12.5-33 0-59.8 26.8-59.8 59.8.0 24 14.1 44.6 34.4 54.1 2 69.4 77.6 125.2 170.6 125.2s168.7-55.9 170.6-125.3c20.2-9.6 34.1-30.2 34.1-54 0-33-26.8-59.8-59.8-59.8-13.7.0-26.3 4.6-36.4 12.4-27.4-17-62.1-27.7-1e2-29.1v-.2c0-25.4 18.9-46.5 43.4-49.9 4.4 18.8 21.3 32.8 41.5 32.8zM177.1 246.9c16.7.0 29.5 17.6 28.5 39.3s-13.5 29.6-30.3 29.6-31.4-8.8-30.4-30.5S160.3 247 177 247zm190.1 38.3c1 21.7-13.7 30.5-30.4 30.5s-29.3-7.9-30.3-29.6c-1-21.7 11.8-39.3 28.5-39.3s31.2 16.6 32.1 38.3zm-48.1 56.7c-10.3 24.6-34.6 41.9-63 41.9s-52.7-17.3-63-41.9c-1.2-2.9.8-6.2 3.9-6.5 18.4-1.9 38.3-2.9 59.1-2.9s40.7 1 59.1 2.9c3.1.3 5.1 3.6 3.9 6.5z"/></svg>
|
||
</a><a href=/rss.xml title=RSS target=_blank rel=noopener><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M64 32C28.7 32 0 60.7.0 96V416c0 35.3 28.7 64 64 64h320c35.3.0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64zM96 136c0-13.3 10.7-24 24-24 137 0 248 111 248 248 0 13.3-10.7 24-24 24s-24-10.7-24-24c0-110.5-89.5-2e2-2e2-2e2-13.3.0-24-10.7-24-24zm0 96c0-13.3 10.7-24 24-24 83.9.0 152 68.1 152 152 0 13.3-10.7 24-24 24s-24-10.7-24-24c0-57.4-46.6-104-104-104-13.3.0-24-10.7-24-24zm0 120a32 32 0 1164 0 32 32 0 11-64 0z"/></svg></a></div></div></div></footer><script defer src=/assets/js/localize.js?7></script><script defer src=/assets/js/tobii.min.js></script><script defer src=/assets/js/highlight.min.js?1></script><script defer src=/assets/js/highlight.gdscript.min.js?1></script><script>document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll("pre:not(.manual) code").forEach(e=>{hljs.highlightBlock(e)}),document.querySelectorAll("[data-post-date]").forEach(e=>{Date.parse(e.dataset.postDate)>Date.now()-1e3*60*60*48&&e.classList.add("post-recent-highlight")}),new Tobii({zoom:!1});const e=document.querySelectorAll(".set-os-download-url");for(let n=0;n<e.length;n++){const s=e[n];let o="download";"version"in s.dataset&&s.dataset.version==="3"&&(o="download/3.x");let t="windows";navigator.platform.indexOf("Mac")!==-1?t="macos":navigator.userAgent.indexOf("Android")!==-1?t="android":navigator.platform.indexOf("Linux")!==-1&&(t="linux"),s.href=`/${o}/${t}/`}})</script> |