浏览代码

Merge branch 'master' into stable

Max Hilbrunner 2 年之前
父节点
当前提交
c93d9373c5
共有 100 个文件被更改,包括 1646 次插入837 次删除
  1. 3 6
      .github/workflows/build_offline_docs.yml
  2. 1 2
      .github/workflows/ci.yml
  3. 3 0
      .gitignore
  4. 25 188
      Makefile
  5. 33 15
      _extensions/gdscript.py
  6. 2 0
      _tools/codespell-ignore-lines.txt
  7. 22 24
      about/faq.rst
  8. 5 5
      about/list_of_features.rst
  9. 40 63
      about/troubleshooting.rst
  10. 二进制
      community/asset_library/img/assetlib_editor_projects.png
  11. 二进制
      community/asset_library/img/assetlib_editor_projects.webp
  12. 3 3
      community/asset_library/using_assetlib.rst
  13. 1 1
      community/asset_library/what_is_assetlib.rst
  14. 209 75
      contributing/development/compiling/compiling_for_linuxbsd.rst
  15. 3 3
      contributing/development/compiling/compiling_for_macos.rst
  16. 90 14
      contributing/development/compiling/introduction_to_the_buildsystem.rst
  17. 84 3
      contributing/development/configuring_an_ide/android_studio.rst
  18. 1 1
      contributing/development/configuring_an_ide/clion.rst
  19. 二进制
      contributing/development/configuring_an_ide/img/android_studio_app_build_variant.webp
  20. 二进制
      contributing/development/configuring_an_ide/img/android_studio_app_configurations_drop_down.webp
  21. 二进制
      contributing/development/configuring_an_ide/img/android_studio_app_debug_type_setup.webp
  22. 二进制
      contributing/development/configuring_an_ide/img/android_studio_editor_build_variant.webp
  23. 二进制
      contributing/development/configuring_an_ide/img/android_studio_editor_configurations_drop_down.webp
  24. 二进制
      contributing/development/configuring_an_ide/img/android_studio_editor_debug_type_setup.webp
  25. 二进制
      contributing/development/configuring_an_ide/img/vs_3_debug_command_line.png
  26. 二进制
      contributing/development/configuring_an_ide/img/vs_3_debug_command_line.webp
  27. 二进制
      contributing/development/configuring_an_ide/img/xcode_1_create_external_build_project.png
  28. 二进制
      contributing/development/configuring_an_ide/img/xcode_1_create_external_build_project.webp
  29. 二进制
      contributing/development/configuring_an_ide/img/xcode_2_configure_scons.png
  30. 二进制
      contributing/development/configuring_an_ide/img/xcode_2_set_external_build_project_parameters.webp
  31. 二进制
      contributing/development/configuring_an_ide/img/xcode_3_add_new_target.png
  32. 二进制
      contributing/development/configuring_an_ide/img/xcode_3_configure_scons.webp
  33. 二进制
      contributing/development/configuring_an_ide/img/xcode_4_add_new_target.webp
  34. 二进制
      contributing/development/configuring_an_ide/img/xcode_4_select_command_line_target.png
  35. 二进制
      contributing/development/configuring_an_ide/img/xcode_5_after_add_godot_source_to_project.png
  36. 二进制
      contributing/development/configuring_an_ide/img/xcode_5_select_command_line_target.webp
  37. 二进制
      contributing/development/configuring_an_ide/img/xcode_6_after_add_godot_source_to_project.webp
  38. 二进制
      contributing/development/configuring_an_ide/img/xcode_6_after_add_godot_source_to_project_2.png
  39. 二进制
      contributing/development/configuring_an_ide/img/xcode_7_setup_build_post_action.png
  40. 二进制
      contributing/development/configuring_an_ide/img/xcode_7_setup_build_post_action.webp
  41. 二进制
      contributing/development/configuring_an_ide/img/xcode_8_setup_run_scheme.png
  42. 二进制
      contributing/development/configuring_an_ide/img/xcode_8_setup_run_scheme.webp
  43. 12 0
      contributing/development/configuring_an_ide/index.rst
  44. 8 6
      contributing/development/configuring_an_ide/visual_studio.rst
  45. 21 22
      contributing/development/configuring_an_ide/xcode.rst
  46. 1 1
      contributing/development/core_and_modules/binding_to_external_libraries.rst
  47. 1 1
      contributing/development/core_and_modules/custom_audiostreams.rst
  48. 1 1
      contributing/development/core_and_modules/custom_godot_servers.rst
  49. 1 1
      contributing/development/core_and_modules/custom_modules_in_cpp.rst
  50. 190 0
      contributing/development/core_and_modules/custom_platform_ports.rst
  51. 2 2
      contributing/development/core_and_modules/custom_resource_format_loaders.rst
  52. 1 0
      contributing/development/core_and_modules/index.rst
  53. 2 2
      contributing/development/debugging/index.rst
  54. 2 2
      contributing/development/debugging/using_cpp_profilers.rst
  55. 3 3
      contributing/development/editor/introduction_to_editor_development.rst
  56. 2 2
      contributing/documentation/building_the_manual.rst
  57. 6 6
      contributing/documentation/docs_writing_guidelines.rst
  58. 1 1
      contributing/ways_to_contribute.rst
  59. 1 0
      contributing/workflow/index.rst
  60. 421 0
      contributing/workflow/pr_review_guidelines.rst
  61. 6 6
      contributing/workflow/pr_workflow.rst
  62. 1 1
      getting_started/first_2d_game/01.project_setup.rst
  63. 1 1
      getting_started/first_2d_game/02.player_scene.rst
  64. 27 20
      getting_started/first_2d_game/03.coding_the_player.rst
  65. 7 14
      getting_started/first_2d_game/04.creating_the_enemy.rst
  66. 11 14
      getting_started/first_2d_game/05.the_main_game_scene.rst
  67. 13 12
      getting_started/first_2d_game/06.heads_up_display.rst
  68. 1 1
      getting_started/first_2d_game/07.finishing-up.rst
  69. 二进制
      getting_started/first_2d_game/img/build_dotnet.webp
  70. 2 2
      getting_started/first_3d_game/01.game_setup.rst
  71. 51 37
      getting_started/first_3d_game/03.player_movement_code.rst
  72. 40 29
      getting_started/first_3d_game/04.mob_scene.rst
  73. 21 42
      getting_started/first_3d_game/05.spawning_mobs.rst
  74. 18 15
      getting_started/first_3d_game/06.jump_and_squash.rst
  75. 80 57
      getting_started/first_3d_game/07.killing_player.rst
  76. 23 19
      getting_started/first_3d_game/08.score_and_replay.rst
  77. 79 50
      getting_started/first_3d_game/09.adding_animations.rst
  78. 6 6
      getting_started/introduction/first_look_at_the_editor.rst
  79. 3 3
      getting_started/introduction/godot_design_philosophy.rst
  80. 1 1
      getting_started/introduction/key_concepts_overview.rst
  81. 4 4
      getting_started/introduction/learning_new_features.rst
  82. 二进制
      getting_started/step_by_step/img/scripting_first_script_add_sprite_node.png
  83. 二进制
      getting_started/step_by_step/img/scripting_first_script_add_sprite_node.webp
  84. 二进制
      getting_started/step_by_step/img/scripting_first_script_attach_node_script.png
  85. 二进制
      getting_started/step_by_step/img/scripting_first_script_attach_node_script.webp
  86. 二进制
      getting_started/step_by_step/img/scripting_first_script_attach_script.png
  87. 二进制
      getting_started/step_by_step/img/scripting_first_script_attach_script.webp
  88. 二进制
      getting_started/step_by_step/img/scripting_first_script_scene_tree.png
  89. 二进制
      getting_started/step_by_step/img/scripting_first_script_scene_tree.webp
  90. 二进制
      getting_started/step_by_step/img/scripting_first_script_setting_texture.png
  91. 二进制
      getting_started/step_by_step/img/scripting_first_script_setting_texture.webp
  92. 3 3
      getting_started/step_by_step/instancing.rst
  93. 13 13
      getting_started/step_by_step/scripting_first_script.rst
  94. 2 2
      getting_started/step_by_step/scripting_languages.rst
  95. 26 26
      getting_started/step_by_step/signals.rst
  96. 二进制
      img/control_gallery.webp
  97. 1 1
      tutorials/2d/2d_movement.rst
  98. 4 4
      tutorials/2d/2d_sprite_animation.rst
  99. 1 1
      tutorials/2d/2d_transforms.rst
  100. 二进制
      tutorials/2d/img/2d_animation_tree1.png

+ 3 - 6
.github/workflows/build_offline_docs.yml

@@ -15,8 +15,7 @@ jobs:
           - master
           - stable
     steps:
-      - name: Checkout
-        uses: actions/checkout@v3
+      - uses: actions/checkout@v3
         with:
           ref: ${{ matrix.branch }}
 
@@ -25,10 +24,8 @@ jobs:
           sudo pip3 install -r requirements.txt
           sudo pip3 install codespell
 
-      # Build the HTML to upload it.
-      - name: Sphinx build
-        run: |
-          sphinx-build --color -d _build/doctrees . _build/html
+      - name: Sphinx build HTML
+        run: make SPHINXOPTS='--color' html
 
       - uses: actions/upload-artifact@v3
         with:

+ 1 - 2
.github/workflows/ci.yml

@@ -25,5 +25,4 @@ jobs:
 
       # Use dummy builder to improve performance as we don't need the generated HTML in this workflow.
       - name: Sphinx build
-        run: |
-          sphinx-build --color -b dummy -d _build/doctrees -W . _build/html
+        run: make SPHINXOPTS='--color -W' dummy

+ 3 - 0
.gitignore

@@ -44,3 +44,6 @@ logo.h
 # Output of list-unused-images.sh tool
 tmp-unused-images
 tmp-unused-images-history
+
+# User created Python virtual environement as described in the docs
+godot-docs-venv/

+ 25 - 188
Makefile

@@ -1,200 +1,37 @@
 # Makefile for Sphinx documentation
-#
 
-# You can set these variables from the command line.
-SPHINXOPTS    =
-SPHINXBUILD   = sphinx-build
-PAPER         =
-BUILDDIR      = _build
-LATEXDEPS     = latex dvipng
-FILELIST      =
+SPHINXOPTS      ?=
+SPHINXBUILD     ?= sphinx-build
+SPHINXSOURCEDIR ?= .
+SPHINXBUILDDIR  ?= _build
+SPHINXPAPER     ?=
+FILELIST        ?=
 
 # User-friendly check for sphinx-build
-ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
-$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD make variable to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the executable's directory to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+ifneq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 0)
+define ERROR_MESSAGE
+The '$(SPHINXBUILD)' command was not found!
+Make sure you have Sphinx installed, then set the SPHINXBUILD make variable to the full path of the '$(SPHINXBUILD)' executable.
+Alternatively you can add the executable's directory to your PATH.
+If you don't have Sphinx installed, grab it from http://sphinx-doc.org/
+endef
+$(error ${ERROR_MESSAGE})
 endif
 
-# Internal variables.
-PAPEROPT_a4     = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) -t i18n .
+PAPEROPT_a4         = -D latex_paper_size=a4
+PAPEROPT_letter     = -D latex_paper_size=letter
+COMMONSPHINXOPTS    = $(PAPEROPT_$(SPHINXPAPER)) $(SPHINXOPTS) '$(SPHINXSOURCEDIR)'
+DEFAULTSPHINXOPTS   = -d $(SPHINXBUILDDIR)/doctrees $(COMMONSPHINXOPTS)
 
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
+.PHONY: help clean
 
 help:
-	@echo "Please run \`make <target>' where <target> is one of"
-	@echo "  html       to make standalone HTML files"
-	@echo "  dirhtml    to make HTML files named index.html in directories"
-	@echo "  singlehtml to make a single large HTML file"
-	@echo "  pickle     to make pickle files"
-	@echo "  json       to make JSON files"
-	@echo "  htmlhelp   to make HTML files and an HTML help project"
-	@echo "  qthelp     to make HTML files and a qthelp project"
-	@echo "  applehelp  to make an Apple Help Book"
-	@echo "  devhelp    to make HTML files and a Devhelp project"
-	@echo "  epub       to make an epub"
-	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
-	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
-	@echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
-	@echo "  text       to make text files"
-	@echo "  man        to make manual pages"
-	@echo "  texinfo    to make Texinfo files"
-	@echo "  info       to make Texinfo files and run them through makeinfo"
-	@echo "  gettext    to make PO message catalogs"
-	@echo "  changes    to make an overview of all changed/added/deprecated items"
-	@echo "  xml        to make Docutils-native XML files"
-	@echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
-	@echo "  linkcheck  to check all external links for integrity"
-	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
-	@echo "  coverage   to run coverage check of the documentation (if enabled)"
-	@echo "  dummy      to run only the parse steps without generating output"
-
-clean:
-	rm -rf $(BUILDDIR)/*
-
-html:
-	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html $(FILELIST)
-	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
-	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml $(FILELIST)
-	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
-	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml $(FILELIST)
-	@echo
-	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
-	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle $(FILELIST)
-	@echo
-	@echo "Build finished; now you can process the pickle files."
-
-json:
-	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json $(FILELIST)
-	@echo
-	@echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
-	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp $(FILELIST)
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
-	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp $(FILELIST)
-	@echo
-	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
-	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
-	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/GodotEngine.qhcp"
-	@echo "To view the help file:"
-	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/GodotEngine.qhc"
-
-applehelp:
-	$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp $(FILELIST)
-	@echo
-	@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
-	@echo "N.B. You won't be able to view it unless you put it in" \
-	      "~/Library/Documentation/Help or install it in your application" \
-	      "bundle."
-
-devhelp:
-	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp $(FILELIST)
-	@echo
-	@echo "Build finished."
-	@echo "To view the help file:"
-	@echo "# mkdir -p $$HOME/.local/share/devhelp/GodotEngine"
-	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/GodotEngine"
-	@echo "# devhelp"
-
-epub:
-	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub $(FILELIST)
-	@echo
-	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex $(FILELIST)
-	@echo
-	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
-	@echo "Run \`make' in that directory to run these through (pdf)latex" \
-	      "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex $(FILELIST)
-	@echo "Running LaTeX files through pdflatex..."
-	$(MAKE) -C $(BUILDDIR)/latex all-pdf
-	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-latexpdfja:
-	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex $(FILELIST)
-	@echo "Running LaTeX files through platex and dvipdfmx..."
-	$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
-	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
-	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text $(FILELIST)
-	@echo
-	@echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
-	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man $(FILELIST)
-	@echo
-	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-texinfo:
-	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo $(FILELIST)
-	@echo
-	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
-	@echo "Run \`make' in that directory to run these through makeinfo" \
-	      "(use \`make info' here to do that automatically)."
-
-info:
-	$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo $(FILELIST)
-	@echo "Running Texinfo files through makeinfo..."
-	make -C $(BUILDDIR)/texinfo info
-	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+	@$(SPHINXBUILD) -M help $(DEFAULTSPHINXOPTS) $(O) "$(SPHINXBUILDDIR)"
 
+# This is used by https://github.com/godotengine/godot-docs-l10n
+# See https://github.com/godotengine/godot-docs-l10n/blob/f157c0cacc8a6e542e06e96b983b27de91637f8b/update.sh#L92
 gettext:
-	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) ../sphinx/templates $(FILELIST)
-	@echo
-	@echo "Build finished. The message catalogs are in ../sphinx/templates."
-
-changes:
-	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes $(FILELIST)
-	@echo
-	@echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
-	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck $(FILELIST)
-	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
-	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest $(FILELIST)
-	@echo "Testing of doctests in the sources finished, look at the " \
-	      "results in $(BUILDDIR)/doctest/output.txt."
-
-coverage:
-	$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage $(FILELIST)
-	@echo "Testing of coverage in the sources finished, look at the " \
-	      "results in $(BUILDDIR)/coverage/python.txt."
-
-xml:
-	$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml $(FILELIST)
-	@echo
-	@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
-
-pseudoxml:
-	$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml $(FILELIST)
-	@echo
-	@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+	$(SPHINXBUILD) -b gettext -t i18n $(COMMONSPHINXOPTS) ../sphinx/templates $(FILELIST)
 
-dummy:
-	$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/html $(FILELIST)
-	@echo
-	@echo "Build finished. No output."
+%:
+	$(SPHINXBUILD) -M $@ $(DEFAULTSPHINXOPTS) $(O) "$(SPHINXBUILDDIR)"/$@ $(FILELIST)

+ 33 - 15
_extensions/gdscript.py

@@ -184,27 +184,37 @@ class GDScriptLexer(RegexLexer):
                         "asin",
                         "atan",
                         "atan2",
-                        "bytes2var",
-                        "bytes2var_with_objects",
+                        "bezier_derivative",
+                        "bezier_interpolate",
+                        "bytes_to_var",
+                        "bytes_to_var_with_objects",
                         "ceil",
+                        "ceilf",
+                        "ceili",
                         "clamp",
                         "clampf",
                         "clampi",
                         "cos",
                         "cosh",
                         "cubic_interpolate",
-                        "db2linear",
-                        "deg2rad",
+                        "cubic_interpolate_angle",
+                        "cubic_interpolate_angle_in_time",
+                        "cubic_interpolate_in_time",
+                        "db_to_linear",
+                        "deg_to_rad",
                         "ease",
                         "error_string",
                         "exp",
                         "floor",
+                        "floorf",
+                        "floori",
                         "fmod",
                         "fposmod",
                         "hash",
                         "instance_from_id",
                         "inverse_lerp",
                         "is_equal_approx",
+                        "is_finite",
                         "is_inf",
                         "is_instance_id_valid",
                         "is_instance_valid",
@@ -212,7 +222,8 @@ class GDScriptLexer(RegexLexer):
                         "is_zero_approx",
                         "lerp",
                         "lerp_angle",
-                        "linear2db",
+                        "lerpf",
+                        "linear_to_db",
                         "log",
                         "max",
                         "maxf",
@@ -226,6 +237,7 @@ class GDScriptLexer(RegexLexer):
                         "posmod",
                         "pow",
                         "print",
+                        "print_rich",
                         "print_verbose",
                         "printerr",
                         "printraw",
@@ -233,7 +245,7 @@ class GDScriptLexer(RegexLexer):
                         "printt",
                         "push_error",
                         "push_warning",
-                        "rad2deg",
+                        "rad_to_deg",
                         "rand_from_seed",
                         "randf",
                         "randf_range",
@@ -241,11 +253,12 @@ class GDScriptLexer(RegexLexer):
                         "randi",
                         "randi_range",
                         "randomize",
-                        "range_lerp",
-                        "range_step_decimals",
+                        "remap",
                         "rid_allocate_id",
                         "rid_from_int64",
                         "round",
+                        "roundf",
+                        "roundi",
                         "seed",
                         "sign",
                         "signf",
@@ -254,17 +267,20 @@ class GDScriptLexer(RegexLexer):
                         "sinh",
                         "smoothstep",
                         "snapped",
+                        "snappedf",
+                        "snappedi",
                         "sqrt",
                         "step_decimals",
                         "str",
-                        "str2var",
+                        "str_to_var",
                         "tan",
                         "tanh",
                         "typeof",
-                        "var2bytes",
-                        "var2bytes_with_objects",
-                        "var2str",
+                        "var_to_bytes",
+                        "var_to_bytes_with_objects",
+                        "var_to_str",
                         "weakref",
+                        "wrap",
                         "wrapf",
                         "wrapi",
 
@@ -273,9 +289,9 @@ class GDScriptLexer(RegexLexer):
                         "assert",
                         "char",
                         "convert",
-                        "dict2inst",
+                        "dict_to_inst",
                         "get_stack",
-                        "inst2dict",
+                        "inst_to_dict",
                         "len",
                         "load",
                         "preload",
@@ -315,7 +331,6 @@ class GDScriptLexer(RegexLexer):
                         "Color",
                         "RID",
                         "Object",
-                        "NodePath",
                         "Dictionary",
                         "Array",
                         "PackedByteArray",
@@ -342,6 +357,7 @@ class GDScriptLexer(RegexLexer):
                 words(
                     (
                         "@export",
+                        "@export_category",
                         "@export_color_no_alpha",
                         "@export_dir",
                         "@export_enum",
@@ -356,10 +372,12 @@ class GDScriptLexer(RegexLexer):
                         "@export_flags_3d_render",
                         "@export_global_dir",
                         "@export_global_file",
+                        "@export_group",
                         "@export_multiline",
                         "@export_node_path",
                         "@export_placeholder",
                         "@export_range",
+                        "@export_subgroup",
                         "@icon",
                         "@onready",
                         "@rpc",

+ 2 - 0
_tools/codespell-ignore-lines.txt

@@ -7,6 +7,7 @@
 | nd            | North Ndebele                 |
 | ro            | Romanian                      |
 | seh           | Sena                          |
+| shs           | Shuswap                       |
 | te            | Telugu                        |
 | tem           | Timne                         |
 | Beng        | Bengali                     |
@@ -16,3 +17,4 @@
 | MM, BU       | Myanmar                                    |
 | RO           | Romania                                    |
 | VN           | Viet Nam                                   |
+.. image:: img/expres.png

+ 22 - 24
about/faq.rst

@@ -63,7 +63,7 @@ systems with Linux, like the Raspberry Pi.
 The Godot team can't provide an open source console export due to the licensing
 terms imposed by console manufacturers. Regardless of the engine you use,
 though, releasing games on consoles is always a lot of work. You can read more
-on that here: :ref:`doc_consoles`
+about :ref:`doc_consoles`.
 
 For more on this, see the sections on :ref:`exporting <toc-learn-workflow-export>`
 and :ref:`compiling Godot yourself <toc-devel-compiling>`.
@@ -89,7 +89,7 @@ discussions on `open issues <https://github.com/godotengine/godot/issues>`_ is a
 great way to start your troubleshooting.
 
 As for new languages, support is possible via third parties with GDExtensions. (See the question
-about plugins below.) Work is currently underway, for example, on unofficial bindings for Godot
+about plugins below). Work is currently underway, for example, on unofficial bindings for Godot
 to `Python <https://github.com/touilleMan/godot-python>`_ and `Nim <https://github.com/pragmagic/godot-nim>`_.
 
 .. _doc_faq_what_is_gdscript:
@@ -113,12 +113,12 @@ Godot was two-fold: first, it reduces the amount of time necessary to get up and
 with Godot, giving developers a rapid way of exposing themselves to the engine with a
 focus on productivity; second, it reduces the overall burden of maintenance, attenuates
 the dimensionality of issues, and allows the developers of the engine to focus on squashing
-bugs and improving features related to the engine core--rather than spending a lot of time
+bugs and improving features related to the engine core, rather than spending a lot of time
 trying to get a small set of incremental features working across a large set of languages.
 
 Since Godot is an open source project, it was imperative from the start to prioritize a
 more integrated and seamless experience over attracting additional users by supporting
-more familiar programming languages--especially when supporting those more familiar
+more familiar programming languages, especially when supporting those more familiar
 languages would result in a worse experience. We understand if you would rather use
 another language in Godot (see the list of supported options above). That being said, if
 you haven't given GDScript a try, try it for **three days**. Just like Godot,
@@ -135,7 +135,7 @@ In the early days, the engine used the `Lua <https://www.lua.org>`__ scripting
 language. Lua can be fast thanks to LuaJIT, but creating bindings to an object-oriented
 system (by using fallbacks) was complex and slow and took an enormous
 amount of code. After some experiments with `Python <https://www.python.org>`__,
-it also proved difficult to embed.
+that also proved difficult to embed.
 
 The main reasons for creating a custom scripting language for Godot were:
 
@@ -145,7 +145,7 @@ The main reasons for creating a custom scripting language for Godot were:
    the way Godot works is highly inefficient (Lua, Python, JavaScript).
 3. Many existing languages have horrible interfaces for binding to C++, resulting in a
    large amount of code, bugs, bottlenecks, and general inefficiency (Lua, Python,
-   Squirrel, JavaScript, etc.) We wanted to focus on a great engine, not a great number
+   Squirrel, JavaScript, etc.). We wanted to focus on a great engine, not a great number
    of integrations.
 4. No native vector types (vector3, matrix4, etc.), resulting in highly
    reduced performance when using custom types (Lua, Python, Squirrel,
@@ -153,8 +153,7 @@ The main reasons for creating a custom scripting language for Godot were:
 5. Garbage collector results in stalls or unnecessarily large memory
    usage (Lua, Python, JavaScript, ActionScript, etc.).
 6. Difficulty integrating with the code editor for providing code
-   completion, live editing, etc. (all of them). This is well-supported
-   by GDScript.
+   completion, live editing, etc. (all of them).
 
 GDScript was designed to curtail the issues above, and more.
 
@@ -204,7 +203,7 @@ Windows
 - Move the Godot executable to a stable location (i.e. outside of your Downloads folder),
   so you don't accidentally move it and break the shortcut in the future.
 - Right-click the Godot executable and choose **Create Shortcut**.
-- Move the created shortcut to ``%LOCALAPPDATA%\Microsoft\Windows\Start Menu\Programs``.
+- Move the created shortcut to ``%APPDATA%\Microsoft\Windows\Start Menu\Programs``.
   This is the user-wide location for shortcuts that will appear in the Start menu.
   You can also pin Godot in the task bar by right-clicking the executable and choosing
   **Pin to Task Bar**.
@@ -257,7 +256,7 @@ Why does Godot use Vulkan or OpenGL instead of Direct3D?
 
 Godot aims for cross-platform compatibility and open standards first and
 foremost. OpenGL and Vulkan are the technologies that are both open and
-available (nearly) on all platforms. Thanks to this design decision, a project
+available on (nearly) all platforms. Thanks to this design decision, a project
 developed with Godot on Windows will run out of the box on Linux, macOS, and
 more.
 
@@ -267,7 +266,7 @@ on all platforms allows for greater consistency with fewer platform-specific
 issues.
 
 In the long term, we may develop a Direct3D 12 renderer for Godot (mainly for
-the Xbox's purposes), but Vulkan and OpenGL will remain the default rendering
+Xbox), but Vulkan and OpenGL will remain the default rendering
 backends on all platforms, including Windows.
 
 Why does Godot aim to keep its core feature set small?
@@ -299,7 +298,7 @@ There are several reasons for this:
 
 - **Keeping the binary size small for export templates.** This directly impacts the
   size of projects exported with Godot. On mobile and web platforms, keeping
-  file sizes low is primordial to ensure fast installation and loading on
+  file sizes low is important to ensure fast installation and loading on
   underpowered devices. Again, there are many countries where high-speed
   Internet is not readily available. To add to this, strict data usage caps are
   often in effect in those countries.
@@ -532,26 +531,25 @@ removed at run-time to dynamically add and remove behaviors.
 More information about Godot's design choices can be found in
 `this article <https://godotengine.org/article/why-isnt-godot-ecs-based-game-engine>`__.
 
-Why does Godot not force users to implement DoD (Data-oriented Design)?
+Why does Godot not force users to implement DOD (Data-Oriented Design)?
 -----------------------------------------------------------------------
 
-While Godot internally for a lot of the heavy performance tasks attempts
-to use cache coherency as well as possible, we believe most users don't
-really need to be forced to use DoD practices.
+While Godot internally attempts to use cache coherency as much as possible,
+we believe users don't need to be forced to use DOD practices.
 
-DoD is mostly a cache coherency optimization that can only gain you
+DOD is mostly a cache coherency optimization that can only provide
 significant performance improvements when dealing with dozens of
-thousands of objects (which are processed every frame with little
-modification). As in, if you are moving a few hundred sprites or enemies
-per frame, DoD won't help you, and you should consider a different approach
-to optimization.
+thousands of objects which are processed every frame with little
+modification. That is, if you are moving a few hundred sprites or enemies
+per frame, DOD won't result in a meaningful improvement in performance. In
+such a case, you should consider a different approach to optimization.
 
 The vast majority of games do not need this and Godot provides handy helpers
 to do the job for most cases when you do.
 
-If a game that really needs to process such large amount of objects is
-needed, our recommendation is to use C++ and GDExtension for the high
-performance parts and GDScript (or C#) for the rest of the game.
+If a game needs to process such a large amount of objects, our recommendation 
+is to use C++ and GDExtensions for performance-heavy tasks and GDScript (or C#)
+for the rest of the game.
 
 How can I support Godot development or contribute?
 --------------------------------------------------

+ 5 - 5
about/list_of_features.rst

@@ -34,8 +34,8 @@ Platforms
 - iOS 11.0 and later.
 - :ref:`Consoles <doc_consoles>`.
 
-Godot aims to be as platform-independent as possible and can be ported to new
-platforms with relative ease.
+Godot aims to be as platform-independent as possible and can be
+:ref:`ported to new platforms <doc_custom_platform_ports>` with relative ease.
 
 Editor
 ------
@@ -76,7 +76,7 @@ Editor
 - :ref:`Create your own plugins <doc_making_plugins>` using GDScript to add new
   features or speed up your workflow.
 - :ref:`Download projects from the asset library <doc_using_assetlib_editor>`
-  in the project manager and import them directly.
+  in the Project Manager and import them directly.
 
 Rendering
 ---------
@@ -450,7 +450,7 @@ Scripting
 
 - Actively developed GDExtension bindings for `D <https://github.com/godot-dlang/godot-dlang>`__,
   `Haxe <https://hxgodot.github.io/>`__, `Python <https://github.com/touilleMan/godot-python>`__, and `Rust <https://github.com/godot-rust/gdextension>`__
-  bindings provided by the community. (Some of these bindings may be experimental and not production-ready.)
+  bindings provided by the community. (Some of these bindings may be experimental and not production-ready).
 
 Audio
 -----
@@ -718,7 +718,7 @@ Miscellaneous
    - Print colored text to standard output on all platforms using
      :ref:`print_rich <class_@GlobalScope_method_print_rich>`.
 
-- Support for :ref:`C++ modules <doc_custom_modules_in_c++>` statically linked
+- Support for :ref:`C++ modules <doc_custom_modules_in_cpp>` statically linked
   into the engine binary.
 - Engine and editor written in C++17.
 

+ 40 - 63
about/troubleshooting.rst

@@ -9,22 +9,11 @@ This page lists common issues encountered when using Godot and possible solution
 
 .. seealso::
 
-    See :ref:`doc_using_the_web_editor` for caveats specific to the HTML5 version
+    See :ref:`doc_using_the_web_editor` for caveats specific to the Web version
     of the Godot editor.
 
-Everything I do in the editor or project manager appears delayed by one frame.
-------------------------------------------------------------------------------
-
-This is a `known bug <https://github.com/godotengine/godot/issues/23069>`__ on
-Intel graphics drivers on Windows. Updating to the latest graphics driver
-version *provided by Intel* should fix the issue.
-
-You should use the graphics driver provided by Intel rather than the one
-provided by your desktop or laptop's manufacturer because their version is often
-outdated.
-
-The editor runs slowly and uses all my CPU and GPU resources, making my computer noisy.
----------------------------------------------------------------------------------------
+The editor runs slowly and uses all my CPU and GPU resources, making my computer noisy
+--------------------------------------------------------------------------------------
 
 This is a known issue, especially on macOS since most Macs have Retina displays.
 Due to Retina displays' higher pixel density, everything has to be rendered at a
@@ -36,7 +25,7 @@ There are several ways to improve performance and battery life:
 - In 3D, click the **Perspective** button in the top left corner and enable
   **Half Resolution**. The 3D viewport will now be rendered at half resolution,
   which can be up to 4 times faster.
-- Open the Editor Settings and increase the value of **Low Processor Mode Sleep Usec**
+- Open the Editor Settings and increase the value of **Low Processor Mode Sleep (µsec)**
   to ``33000`` (30 FPS). This value determines the amount of *microseconds*
   between frames to render. Higher values will make the editor feel less reactive
   but will help decrease CPU and GPU usage significantly.
@@ -45,52 +34,50 @@ There are several ways to improve performance and battery life:
   This way, it will be hidden in the editor but will still be visible in the
   running project.
 
-The editor stutters and flickers on my variable refresh rate monitor (G-Sync/FreeSync).
----------------------------------------------------------------------------------------
+The editor stutters and flickers on my variable refresh rate monitor (G-Sync/FreeSync)
+--------------------------------------------------------------------------------------
 
 This is a `known issue <https://github.com/godotengine/godot/issues/38219>`__.
-There are two workarounds for this:
+Variable refresh rate monitors need to adjust their gamma curves continuously to
+emit a consistent amount of light over time. This can cause flicker to appear in
+dark areas of the image when the refresh rate varies a lot, which occurs as
+the Godot editor only redraws when necessary.
+
+There are several workarounds for this:
 
 - Enable **Interface > Editor > Update Continuously** in the Editor Settings. Keep in mind
   this will increase power usage and heat/noise emissions since the editor will
   now be rendering constantly, even if nothing has changed on screen. To
-  alleviate this, you can increase **Low Processor Mode Sleep Usec** to
+  alleviate this, you can increase **Low Processor Mode Sleep (µsec)** to
   ``33000`` (30 FPS) in the Editor Settings. This value determines the amount of
   *microseconds* between frames to render. Higher values will make the editor
   feel less reactive but will help decrease CPU and GPU usage significantly.
 - Alternatively, disable variable refresh rate on your monitor or in the graphics driver.
+- VRR flicker can be reduced on some displays using the **VRR Control** or
+  **Fine Tune Dark Areas** options in your monitor's OSD. These options may
+  increase input lag or result in crushed blacks.
+- If using an OLED display, use the **Black (OLED)** editor theme preset in the
+  Editor Settings. This hides VRR flicker thanks to OLED's perfect black levels.
 
-The grid disappears and meshes turn black when I rotate the 3D camera in the editor.
-------------------------------------------------------------------------------------
-
-This is a `known bug <https://github.com/godotengine/godot/issues/30330>`__ on
-Intel graphics drivers on Windows.
-
-The only workaround, for now, is to switch to the GLES2 renderer. You can switch
-the renderer in the top-right corner of the editor or the Project Settings.
-
-If you use a computer allowing you to switch your graphics card, like NVIDIA
-Optimus, you can use the dedicated graphics card to run Godot.
+The editor or project takes a very long time to start
+-----------------------------------------------------
 
-The editor or project takes a very long time to start.
-------------------------------------------------------
+When using one of the the Vulkan-based renderers (Forward+ or Forward Mobile),
+the first startup is expected to be relatively long. This is because shaders
+need to be compiled before they can be cached. Shaders also need to be cached
+again after updating Godot, after updating graphics drivers or after switching
+graphics cards.
 
-This is a `known bug <https://github.com/godotengine/godot/issues/20566>`__ on
+If the issue persists after the first startup, this is a
+`known bug <https://github.com/godotengine/godot/issues/20566>`__ on
 Windows when you have specific USB peripherals connected. In particular,
-Corsair's iCUE software seems to cause the bug. Try updating your USB
+Corsair's iCUE software seems to cause this bug. Try updating your USB
 peripherals' drivers to their latest version. If the bug persists, you need to
-disconnect the faulty peripherals before opening the editor. You can then
+disconnect the specific peripheral before opening the editor. You can then
 connect the peripheral again.
 
-Editor tooltips in the Inspector and Node docks blink when they're displayed.
------------------------------------------------------------------------------
-
-This is a `known issue <https://github.com/godotengine/godot/issues/32990>`__
-caused by the third-party Stardock Fences application on Windows.
-The only known workaround is to disable Stardock Fences while using Godot.
-
-The Godot editor appears frozen after clicking the system console.
-------------------------------------------------------------------
+The Godot editor appears frozen after clicking the system console
+-----------------------------------------------------------------
 
 When running Godot on Windows with the system console enabled, you can
 accidentally enable *selection mode* by clicking inside the command window. This
@@ -100,8 +87,8 @@ the system console. Godot cannot override this system-specific behavior.
 To solve this, select the system console window and press Enter to leave
 selection mode.
 
-Some text such as "NO DC" appears in the top-left corner of the project manager and editor window.
---------------------------------------------------------------------------------------------------
+Some text such as "NO DC" appears in the top-left corner of the Project Manager and editor window
+-------------------------------------------------------------------------------------------------
 
 This is caused by the NVIDIA graphics driver injecting an overlay to display information.
 
@@ -111,27 +98,17 @@ default values in the NVIDIA Control Panel.
 To disable this overlay on Linux, open ``nvidia-settings``, go to **X Screen 0 >
 OpenGL Settings** then uncheck **Enable Graphics API Visual Indicator**.
 
-The project window appears blurry, unlike the editor.
------------------------------------------------------
-
-Unlike the editor, the project isn't marked as DPI-aware by default. This is
-done to improve performance, especially on integrated graphics, where rendering
-3D scenes in hiDPI is slow.
-
-To resolve this, open **Project > Project Settings** and enable **Display >
-Window > Dpi > Allow Hidpi**. On top of that, make sure your project is
-configured to support :ref:`multiple resolutions <doc_multiple_resolutions>`.
-
-The project window doesn't appear centered when I run the project.
-------------------------------------------------------------------
+The project window doesn't appear centered when I run the project
+-----------------------------------------------------------------
 
 This is a `known bug <https://github.com/godotengine/godot/issues/13017>`__. To
-resolve this, open **Project > Project Settings** and enable **Display > Window
-> Dpi > Allow Hidpi**. On top of that, make sure your project is configured to
+resolve this, open **Project > Project Settings**, make sure **Advanced
+Settings** is active, and enable **Display > Window
+> DPI > Allow hiDPI**. On top of that, make sure your project is configured to
 support :ref:`multiple resolutions <doc_multiple_resolutions>`.
 
-The project works when run from the editor, but fails to load some files when running from an exported copy.
-------------------------------------------------------------------------------------------------------------
+The project works when run from the editor, but fails to load some files when running from an exported copy
+-----------------------------------------------------------------------------------------------------------
 
 This is usually caused by forgetting to specify a filter for non-resource files
 in the Export dialog. By default, Godot will only include actual *resources*

二进制
community/asset_library/img/assetlib_editor_projects.png


二进制
community/asset_library/img/assetlib_editor_projects.webp


+ 3 - 3
community/asset_library/using_assetlib.rst

@@ -109,10 +109,10 @@ In the editor
 .. note::
 
     The editor will display different categories of assets depending on whether
-    you're browsing the project manager's **Templates** tab or the editor's
+    you're browsing the Project Manager's **Asset Library Projects** tab or the editor's
     **AssetLib** tab.
 
-    The project manager's **Templates** tab will only display assets that are
+    The Project Manager's **Asset Library Projects** tab will only display assets that are
     standalone projects by themselves. This is denoted on the asset library with
     the *Templates*, *Demos* and *Projects* categories.
 
@@ -198,4 +198,4 @@ assets downloaded directly via Godot that we just covered.
 .. |image11| image:: img/assetlib_editor_installer.png
 .. |image12| image:: img/assetlib_editor_installer_error.png
 .. |image13| image:: img/assetlib_editor_installer_success.png
-.. |image14| image:: img/assetlib_editor_projects.png
+.. |image14| image:: img/assetlib_editor_projects.webp

+ 1 - 1
community/asset_library/what_is_assetlib.rst

@@ -31,7 +31,7 @@ Types of assets
 Be aware that there are, broadly, two different types of assets you can post.
 
 * Assets labeled as "Templates", "Projects", or "Demos" appear under
-  the "Templates" tab in the Godot project manager. These assets are
+  the "Asset Library Projects" tab in the Godot Project Manager. These assets are
   standalone Godot projects that can run by themselves.
 
 * Other assets show up inside of the Godot editor under the "AssetLib"

+ 209 - 75
contributing/development/compiling/compiling_for_linuxbsd.rst

@@ -17,88 +17,222 @@ For compiling under Linux or other Unix variants, the following is
 required:
 
 - GCC 7+ or Clang 6+.
+
 - `Python 3.6+ <https://www.python.org/downloads/>`_.
-- `SCons 3.0+ <https://scons.org/pages/download.html>`_ build system. If your distribution uses Python 2 by default,
-  or you are using a version of SCons prior to 3.1.2, you will need to change
-  the version of Python that SCons uses by changing the shebang (the first line)
-  of the SCons script file to ``#! /usr/bin/python3``.
-  Use the command ``which scons`` to find the location of the SCons script file.
-- pkg-config (used to detect the dependencies below).
-- X11, Xcursor, Xinerama, Xi and XRandR development libraries.
-- MesaGL development libraries.
-- ALSA development libraries.
-- PulseAudio development libraries.
+
+- `SCons 3.0+ <https://scons.org/pages/download.html>`_ build system.
+
+  .. note::
+
+      If your distribution uses Python 2 by default, or you are using a version of SCons prior to 3.1.2,
+      you will need to change the version of Python that SCons uses by changing the shebang
+      (the first line) of the SCons script file to ``#! /usr/bin/python3``.
+      Use the command ``which scons`` to find the location of the SCons script file.
+
+- pkg-config (used to detect the development libraries listed below).
+- Development libraries:
+
+  - X11, Xcursor, Xinerama, Xi and XRandR.
+  - MesaGL.
+  - ALSA.
+  - PulseAudio.
+
 - *Optional* - libudev (build with ``udev=yes``).
 
-.. seealso:: To get the Godot source code for compiling, see
-             :ref:`doc_getting_source`.
+.. seealso::
+
+    To get the Godot source code for compiling, see :ref:`doc_getting_source`.
 
-             For a general overview of SCons usage for Godot, see
-             :ref:`doc_introduction_to_the_buildsystem`.
+    For a general overview of SCons usage for Godot, see :ref:`doc_introduction_to_the_buildsystem`.
 
 .. _doc_compiling_for_linuxbsd_oneliners:
 
 Distro-specific one-liners
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **Alpine Linux** | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     apk add scons pkgconf gcc g++ libx11-dev libxcursor-dev libxinerama-dev libxi-dev libxrandr-dev \     |
-|                  |         mesa-dev libexecinfo-dev eudev-dev alsa-lib-dev pulseaudio-dev                                    |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **Arch Linux**   | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     pacman -S --needed scons pkgconf gcc libxcursor libxinerama libxi libxrandr mesa glu libglvnd \       |
-|                  |         alsa-lib pulseaudio                                                                               |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **Debian** /     | ::                                                                                                        |
-| **Ubuntu**       |                                                                                                           |
-|                  |     sudo apt-get install build-essential scons pkg-config libx11-dev libxcursor-dev libxinerama-dev \     |
-|                  |         libgl1-mesa-dev libglu-dev libasound2-dev libpulse-dev libudev-dev libxi-dev libxrandr-dev        |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **Fedora**       | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     sudo dnf install scons pkgconfig libX11-devel libXcursor-devel libXrandr-devel libXinerama-devel \    |
-|                  |         libXi-devel mesa-libGL-devel mesa-libGLU-devel alsa-lib-devel pulseaudio-libs-devel \             |
-|                  |         libudev-devel gcc-c++ libstdc++-static libatomic-static                                           |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **FreeBSD**      | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     sudo pkg install py37-scons pkgconf xorg-libraries libXcursor libXrandr libXi xorgproto libGLU \      |
-|                  |         alsa-lib pulseaudio                                                                               |
-|                  |                                                                                                           |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **Gentoo**       | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     emerge -an dev-util/scons x11-libs/libX11 x11-libs/libXcursor x11-libs/libXinerama x11-libs/libXi \   |
-|                  |         media-libs/mesa media-libs/glu media-libs/alsa-lib media-sound/pulseaudio                         |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **Mageia**       | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     urpmi scons task-c++-devel pkgconfig "pkgconfig(alsa)" "pkgconfig(glu)" "pkgconfig(libpulse)" \       |
-|                  |         "pkgconfig(udev)" "pkgconfig(x11)" "pkgconfig(xcursor)" "pkgconfig(xinerama)" "pkgconfig(xi)" \   |
-|                  |         "pkgconfig(xrandr)"                                                                               |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **OpenBSD**      | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     pkg_add python scons llvm                                                                             |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **openSUSE**     | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     sudo zypper install scons pkgconfig libX11-devel libXcursor-devel libXrandr-devel libXinerama-devel \ |
-|                  |             libXi-devel Mesa-libGL-devel alsa-devel libpulse-devel libudev-devel gcc-c++ libGLU1          |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **NetBSD**       | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     pkg_add pkg-config py37-scons                                                                         |
-|                  |                                                                                                           |
-|                  | For audio support, you can optionally install ``pulseaudio``.                                             |
-+------------------+-----------------------------------------------------------------------------------------------------------+
-| **Solus**        | ::                                                                                                        |
-|                  |                                                                                                           |
-|                  |     sudo eopkg install -c system.devel scons libxcursor-devel libxinerama-devel libxi-devel \             |
-|                  |         libxrandr-devel mesalib-devel libglu alsa-lib-devel pulseaudio-devel                              |
-+------------------+-----------------------------------------------------------------------------------------------------------+
+
+.. tabs::
+
+    .. tab:: Alpine Linux
+
+        ::
+
+            apk add \
+              scons \
+              pkgconf \
+              gcc \
+              g++ \
+              libx11-dev \
+              libxcursor-dev \
+              libxinerama-dev \
+              libxi-dev \
+              libxrandr-dev \
+              mesa-dev \
+              libexecinfo-dev \
+              eudev-dev \
+              alsa-lib-dev \
+              pulseaudio-dev
+
+    .. tab:: Arch Linux
+
+        ::
+
+            pacman -S --needed \
+              scons \
+              pkgconf \
+              gcc \
+              libxcursor \
+              libxinerama \
+              libxi \
+              libxrandr \
+              mesa \
+              glu \
+              libglvnd \
+              alsa-lib \
+              pulseaudio
+
+    .. tab:: Debian/Ubuntu
+
+        ::
+
+            apt-get install \
+              build-essential \
+              scons \
+              pkg-config \
+              libx11-dev \
+              libxcursor-dev \
+              libxinerama-dev \
+              libgl1-mesa-dev \
+              libglu-dev \
+              libasound2-dev \
+              libpulse-dev \
+              libudev-dev \
+              libxi-dev \
+              libxrandr-dev
+
+    .. tab:: Fedora
+
+        ::
+
+            dnf install \
+              scons \
+              pkgconfig \
+              libX11-devel \
+              libXcursor-devel \
+              libXrandr-devel \
+              libXinerama-devel \
+              libXi-devel \
+              mesa-libGL-devel \
+              mesa-libGLU-devel \
+              alsa-lib-devel \
+              pulseaudio-libs-devel \
+              libudev-devel \
+              gcc-c++ \
+              libstdc++-static \
+              libatomic-static
+
+    .. tab:: FreeBSD
+
+        ::
+
+            pkg install \
+              py37-scons \
+              pkgconf \
+              xorg-libraries \
+              libXcursor \
+              libXrandr \
+              libXi \
+              xorgproto libGLU \
+              alsa-lib \
+              pulseaudio
+
+    .. tab:: Gentoo
+
+        ::
+
+            emerge -an \
+              dev-util/scons \
+              x11-libs/libX11 \
+              x11-libs/libXcursor \
+              x11-libs/libXinerama \
+              x11-libs/libXi \
+              media-libs/mesa \
+              media-libs/glu \
+              media-libs/alsa-lib \
+              media-sound/pulseaudio
+
+    .. tab:: Mageia
+
+        ::
+
+            urpmi \
+              scons \
+              task-c++-devel \
+              pkgconfig \
+              "pkgconfig(alsa)" \
+              "pkgconfig(glu)" \
+              "pkgconfig(libpulse)" \
+              "pkgconfig(udev)" \
+              "pkgconfig(x11)" \
+              "pkgconfig(xcursor)" \
+              "pkgconfig(xinerama)" \
+              "pkgconfig(xi)" \
+              "pkgconfig(xrandr)"
+
+    .. tab:: OpenBSD
+
+        ::
+
+            pkg_add \
+              python \
+              scons \
+              llvm
+
+    .. tab:: openSUSE
+
+        ::
+
+            zypper install \
+              scons \
+              pkgconfig \
+              libX11-devel \
+              libXcursor-devel \
+              libXrandr-devel \
+              libXinerama-devel \
+              libXi-devel \
+              Mesa-libGL-devel \
+              alsa-devel \
+              libpulse-devel \
+              libudev-devel \
+              gcc-c++ \
+              libGLU1
+
+    .. tab:: NetBSD
+
+        ::
+
+            pkg_add \
+              pkg-config \
+              py37-scons
+
+        .. hint::
+
+            For audio support, you can optionally install ``pulseaudio``.
+
+    .. tab:: Solus
+
+        ::
+
+            eopkg install -c \
+              system.devel \
+              scons \
+              libxcursor-devel \
+              libxinerama-devel \
+              libxi-devel \
+              libxrandr-devel \
+              mesalib-devel \
+              libglu \
+              alsa-lib-devel \
+              pulseaudio-devel
 
 Compiling
 ---------
@@ -117,8 +251,8 @@ Start a terminal, go to the root dir of the engine source code and type:
 
 If all goes well, the resulting binary executable will be placed in the
 "bin" subdirectory. This executable file contains the whole engine and
-runs without any dependencies. Executing it will bring up the project
-manager.
+runs without any dependencies. Executing it will bring up the Project
+Manager.
 
 .. note::
 

+ 3 - 3
contributing/development/compiling/compiling_for_macos.rst

@@ -66,8 +66,8 @@ To support both architectures in a single "Universal 2" binary, run the above tw
 
 If all goes well, the resulting binary executable will be placed in the
 ``bin/`` subdirectory. This executable file contains the whole engine and
-runs without any dependencies. Executing it will bring up the project
-manager.
+runs without any dependencies. Executing it will bring up the Project
+Manager.
 
 .. note:: If you want to use separate editor settings for your own Godot builds
           and official releases, you can enable
@@ -180,7 +180,7 @@ JIT-enabled implementation of the Python language (which SCons is written in).
 Its "full" version is currently only compatible with Linux, but Pyston-lite is
 also compatible with macOS (both x86 and ARM). Pyston can speed up incremental
 builds significantly, often by a factor between 1.5× and 2×. Pyston can be
-combined with alternative likers such as LLD or Mold to get even faster builds.
+combined with alternative linkers such as LLD or Mold to get even faster builds.
 
 To install Pyston-lite, run ``python -m pip install pyston_lite_autoload`` then
 run SCons as usual. This will automatically load a subset of Pyston's

+ 90 - 14
contributing/development/compiling/introduction_to_the_buildsystem.rst

@@ -8,12 +8,10 @@ Introduction to the buildsystem
 SCons
 -----
 
-Godot uses `SCons <https://www.scons.org/>`__ to build. We love it, we are
-not changing it for anything else. We are not even sure other build
-systems are up to the task of building Godot. We constantly get requests
-to move the build system to CMake, or Visual Studio, but this is not
-going to happen. There are many reasons why we have chosen SCons over
-other alternatives, for example:
+Godot uses `SCons <https://www.scons.org/>`__ to build. We love it, we are not
+changing it for anything else. We constantly get requests to move the build
+system to CMake, or Visual Studio, but this is not going to happen. There are
+many reasons why we have chosen SCons over other alternatives, for example:
 
 -  Godot can be compiled for a dozen different platforms: all PC
    platforms, all mobile platforms, many consoles, and WebAssembly.
@@ -22,9 +20,8 @@ other alternatives, for example:
    can't afford reconfiguring and rebuilding the project each time.
    SCons can do this with no sweat, without breaking the builds.
 -  SCons will *never* break a build no matter how many changes,
-   configurations, additions, removals etc. You have more chances to die
-   struck by lightning than needing to clean and rebuild in SCons.
--  Godot build process is not simple. Several files are generated by
+   configurations, additions, removals etc.
+-  Godot's build process is not simple. Several files are generated by
    code (binders), others are parsed (shaders), and others need to offer
    customization (plugins). This requires complex logic which is easier
    to write in an actual programming language (like Python) rather than
@@ -33,8 +30,8 @@ other alternatives, for example:
    platform has a specific detection process, and all these must be
    handled as specific cases with special code written for each.
 
-So, please try to keep an open mind and get at least a little familiar with it
-if you are planning to build Godot yourself.
+Please try to keep an open mind and get at least a little familiar with it if
+you are planning to build Godot yourself.
 
 Setup
 -----
@@ -118,7 +115,7 @@ A Windows binary with the same configuration will look like this:
     C:\godot> dir bin/
     godot.windows.editor.64.exe
 
-Copy that binary to any location you like, as it contains the project manager,
+Copy that binary to any location you like, as it contains the Project Manager,
 editor and all means to execute the game. However, it lacks the data to export
 it to the different platforms. For that the export templates are needed (which
 can be either downloaded from `godotengine.org <https://godotengine.org/>`__, or
@@ -141,15 +138,45 @@ All builds are optimized. Each mode means:
 
 The editor is enabled by default in all PC targets (Linux, Windows, macOS),
 disabled for everything else. Disabling the editor produces a binary that can
-run projects but that does not include the editor or the project manager.
+run projects but does not include the editor or the Project Manager.
 
 ::
 
     scons platform=<platform> target=editor/template_debug/template_release
 
+Development and production aliases
+----------------------------------
+
+When creating builds for development (running debugging/:ref:`profiling <doc_using_cpp_profilers>`
+tools), you often have different goals compared to production builds
+(making binaries as fast and small as possible).
+
+Godot provides two aliases for this purpose:
+
+- ``dev_mode=yes`` is an alias for ``verbose=yes warnings=extra werror=yes
+  tests=yes``. This enables warnings-as-errors behavior (similar to Godot's
+  continuous integration setup) and also builds :ref:`unit tests
+  <doc_unit_testing>` so you can run them locally.
+- ``production=yes`` is an alias for ``use_static_cpp=yes debug_symbols=no
+  lto=auto``. Statically linking libstdc++ allows for better binary portability
+  when compiling for Linux. This alias also enables link-time optimization when
+  compiling for Linux, Web and Windows with MinGW, but keeps LTO disabled when
+  compiling for macOS, iOS or Windows with MSVC. This is because LTO on those
+  platforms is very slow to link or has issues with the generated code.
+
+You can manually override options from those aliases by specifying them on the
+same command line with different values. For example, you can use ``scons
+production=yes debug_symbols=yes`` to create production-optimized binaries with
+debugging symbols included.
+
 Dev build
 ---------
 
+.. note::
+
+    ``dev_build`` should **not** be confused with ``dev_mode``, which is an
+    alias for several development-related options (see above).
+
 When doing engine development the ``dev_build`` option can be used together
 with ``target`` to enable dev-specific code. ``dev_build`` defines ``DEV_ENABLED``,
 disables optimization (``-O0``/``/0d``), enables generating debug symbols, and
@@ -162,6 +189,55 @@ does not define ``NDEBUG`` (so ``assert()`` works in thirdparty libraries).
 This flag appends the ``.dev`` suffix (for development) to the generated
 binary name.
 
+Debugging symbols
+-----------------
+
+By default, ``debug_symbols=no`` is used, which means **no** debugging symbols
+are included in compiled binaries. Use ``debug_symbols=yes`` to include debug
+symbols within compiled binaries, which allows debuggers and profilers to work
+correctly. Debugging symbols are also required for Godot's crash stacktraces to
+display with references to source code files and lines.
+
+The downside is that debugging symbols are large files (significantly larger
+than the binaries themselves). As a result, official binaries currently do not
+include debugging symbols. This means you need to compile Godot yourself to have
+access to debugging symbols.
+
+When using ``debug_symbols=yes``, you can also use
+``separate_debug_symbols=yes`` to put debug information in a separate file with
+a ``.debug`` suffix. This allows distributing both files independently. Note
+that on Windows, when compiling with MSVC, debugging information is *always*
+written to a separate ``.pdb`` file regardless of ``separate_debug_symbols``.
+
+.. tip::
+
+    Use the ``strip <path/to/binary>`` command to remove debugging symbols from
+    a binary you've already compiled.
+
+Optimization level
+------------------
+
+Several compiler optimization levels can be chosen from:
+
+- ``optimize=speed_trace`` *(default when targeting non-Web platforms)*: Favors
+  execution speed at the cost of larger binary size. Optimizations may sometimes
+  negatively impact debugger usage (stack traces may be less accurate. If this
+  occurs to you, use ``optimize=debug`` instead.
+- ``optimize=speed``: Favors even more execution speed, at the cost of even
+  larger binary size compared to ``optimize=speed_trace``. Even less friendly to
+  debugging compared to ``optimize=debug``, as this uses the most aggressive
+  optimizations available.
+- ``optimize=size`` *(default when targeting the Web platform)*: Favors small
+  binaries at the cost of slower execution speed.
+- ``optimize=debug``: Only enables optimizations that do not impact debugging in
+  any way. This results in faster binaries than ``optimize=none``, but slower
+  binaries than ``optimize=speed_trace``.
+- ``optimize=none``: Do not perform any optimization. This provides the fastest
+  build times, but the slowest execution times.
+- ``optimize=custom`` *(advanced users only)*: Do not pass optimization
+  arguments to the C/C++ compilers. You will have to pass arguments manually
+  using the ``CFLAGS``, ``CCFLAGS`` and ``CXXFLAGS`` SCons options.
+
 Architecture
 ------------
 
@@ -208,7 +284,7 @@ directory paths containing such modules:
 
 .. seealso::
 
-    :ref:`doc_custom_modules_in_c++`
+    :ref:`doc_custom_modules_in_cpp`
 
 Cleaning generated files
 ------------------------

+ 84 - 3
contributing/development/configuring_an_ide/android_studio.rst

@@ -22,7 +22,88 @@ Importing the project
 
 - Navigate to ``<Godot root directory>/platform/android/java`` and select the ``settings.gradle`` file.
 - Android Studio will import and index the project.
-- To build the project, follow the :ref:`compiling instructions <toc-devel-compiling>`.
 
-If you run into any issues, ask for help in one of
-`Godot's community channels <https://godotengine.org/community>`__.
+Android Studio project layout
+-----------------------------
+
+The project is organized using `Android Studio's modules <https://developer.android.com/studio/projects#ApplicationModules>`_:
+
+- ``lib`` module:
+   - Located under ``<Godot root directory>/platform/android/java/lib``, this is a **library module** that organizes
+      the Godot java and native code and make it available as a reusable dependency / artifact.
+   - The artifact generated by this module is made available for other Android modules / projects to use as a dependency, via `MavenCentral <https://repo1.maven.org/maven2/org/godotengine/godot/>`_.
+
+- ``editor`` module:
+   - Located under ``<Godot root directory>/platform/android/java/editor``, this is an **application module** that holds
+      the source code for the Android port of the Godot Editor.
+   - This module has a dependency on the ``lib`` module.
+
+- ``app`` module:
+   - Located under ``<Godot root directory>/platform/android/java/app``, this is an **application module** that holds
+      the source code for the Android build templates.
+   - This module has a dependency on the ``lib`` module.
+
+Building & debugging the editor module
+--------------------------------------
+
+- To build the ``editor`` module:
+   - Select the `Run/Debug Configurations drop down <https://developer.android.com/studio/run/rundebugconfig#running>`_ and select ``editor``.
+
+   .. figure:: img/android_studio_editor_configurations_drop_down.webp
+      :figclass: figure-w480
+      :align: center
+
+   - Select **Run > Run 'editor'** from the top menu or `click the Run icon <https://developer.android.com/studio/run/rundebugconfig#running>`_.
+- To debug the ``editor`` module:
+   - Open the **Build Variants** window using **View > Tools Windows > Build Variants** from the top menu.
+   - In the **Build Variants** window, make sure that in the **Active Build Variant** column, the ``:editor`` entry is set to **dev**.
+
+   .. figure:: img/android_studio_editor_build_variant.webp
+      :figclass: figure-w480
+      :align: center
+
+   - Open the **Run/Debug Configurations** window by clicking on **Run > Edit Configurations...** on the top menu.
+   - In the **Run/Debug Configurations** window, select the ``editor`` entry, and under **Debugger** make sure the **Debug Type** is set to ``Dual (Java + Native)``
+
+   .. figure:: img/android_studio_editor_debug_type_setup.webp
+      :figclass: figure-w480
+      :align: center
+
+   - Select **Run > Debug 'editor'** from the top menu or `click the Debug icon <https://developer.android.com/studio/run/rundebugconfig#running>`_.
+
+Building & debugging the app module
+-----------------------------------
+
+The ``app`` module requires the presence of a Godot project in its ``assets`` directory (``<Godot root directory>/platform/android/java/app/assets``) to run.
+This is usually handled by the Godot Editor during the export process.
+While developing in Android Studio, it's necessary to manually add a Godot project under that directory to replicate the export process.
+Once that's done, you can follow the instructions below to run/debug the ``app`` module:
+
+- To build the ``app`` module:
+   - Select the `Run/Debug Configurations drop down <https://developer.android.com/studio/run/rundebugconfig#running>`_ and select ``app``.
+
+   .. figure:: img/android_studio_app_configurations_drop_down.webp
+      :figclass: figure-w480
+      :align: center
+
+   - Select **Run > Run 'app'** from the top menu or `click the Run icon <https://developer.android.com/studio/run/rundebugconfig#running>`_.
+- To debug the ``app`` module:
+   - Open the **Build Variants** window using **View > Tools Windows > Build Variants** from the top menu.
+   - In the **Build Variants** window, make sure that in the **Active Build Variant** column, the ``:app`` entry is set to **dev**.
+
+   .. figure:: img/android_studio_app_build_variant.webp
+      :figclass: figure-w480
+      :align: center
+
+   - Open the **Run/Debug Configurations** window by clicking on **Run > Edit Configurations...** on the top menu.
+   - In the **Run/Debug Configurations** window, select the ``app`` entry, and under **Debugger** make sure the **Debug Type** is set to ``Dual (Java + Native)``
+
+   .. figure:: img/android_studio_app_debug_type_setup.webp
+      :figclass: figure-w480
+      :align: center
+
+   - Select **Run > Debug 'app'** from the top menu or `click the Debug icon <https://developer.android.com/studio/run/rundebugconfig#running>`_.
+
+
+If you run into any issues, ask for help in
+`Godot's Android dev channel <https://chat.godotengine.org/channel/android>`__.

+ 1 - 1
contributing/development/configuring_an_ide/clion.rst

@@ -70,7 +70,7 @@ To add a custom build target that invokes SCons for compilation:
 .. figure:: img/clion-add-custom-build-application.png
    :align: center
 
-- Give the run/debug configuration a name, e.g. ``Godot debug``, select the ``Godot debug`` custom build target as the **Target**. Select the Godot executable in the ``bin/`` folder as the **Executable**, and set the **Program arguments** to ``--editor --path path-to-your-project/``, where ``path-to-your-project/`` should be a path pointing to an existing Godot project. If you omit the ``--path`` argument, you will only be able to debug the Godot project manager window. Click **OK** to create the run/debug configuration.
+- Give the run/debug configuration a name, e.g. ``Godot debug``, select the ``Godot debug`` custom build target as the **Target**. Select the Godot executable in the ``bin/`` folder as the **Executable**, and set the **Program arguments** to ``--editor --path path-to-your-project/``, where ``path-to-your-project/`` should be a path pointing to an existing Godot project. If you omit the ``--path`` argument, you will only be able to debug the Godot Project Manager window. Click **OK** to create the run/debug configuration.
 
 .. figure:: img/clion-run-configuration.png
    :align: center

二进制
contributing/development/configuring_an_ide/img/android_studio_app_build_variant.webp


二进制
contributing/development/configuring_an_ide/img/android_studio_app_configurations_drop_down.webp


二进制
contributing/development/configuring_an_ide/img/android_studio_app_debug_type_setup.webp


二进制
contributing/development/configuring_an_ide/img/android_studio_editor_build_variant.webp


二进制
contributing/development/configuring_an_ide/img/android_studio_editor_configurations_drop_down.webp


二进制
contributing/development/configuring_an_ide/img/android_studio_editor_debug_type_setup.webp


二进制
contributing/development/configuring_an_ide/img/vs_3_debug_command_line.png


二进制
contributing/development/configuring_an_ide/img/vs_3_debug_command_line.webp


二进制
contributing/development/configuring_an_ide/img/xcode_1_create_external_build_project.png


二进制
contributing/development/configuring_an_ide/img/xcode_1_create_external_build_project.webp


二进制
contributing/development/configuring_an_ide/img/xcode_2_configure_scons.png


二进制
contributing/development/configuring_an_ide/img/xcode_2_set_external_build_project_parameters.webp


二进制
contributing/development/configuring_an_ide/img/xcode_3_add_new_target.png


二进制
contributing/development/configuring_an_ide/img/xcode_3_configure_scons.webp


二进制
contributing/development/configuring_an_ide/img/xcode_4_add_new_target.webp


二进制
contributing/development/configuring_an_ide/img/xcode_4_select_command_line_target.png


二进制
contributing/development/configuring_an_ide/img/xcode_5_after_add_godot_source_to_project.png


二进制
contributing/development/configuring_an_ide/img/xcode_5_select_command_line_target.webp


二进制
contributing/development/configuring_an_ide/img/xcode_6_after_add_godot_source_to_project.webp


二进制
contributing/development/configuring_an_ide/img/xcode_6_after_add_godot_source_to_project_2.png


二进制
contributing/development/configuring_an_ide/img/xcode_7_setup_build_post_action.png


二进制
contributing/development/configuring_an_ide/img/xcode_7_setup_build_post_action.webp


二进制
contributing/development/configuring_an_ide/img/xcode_8_setup_run_scheme.png


二进制
contributing/development/configuring_an_ide/img/xcode_8_setup_run_scheme.webp


+ 12 - 0
contributing/development/configuring_an_ide/index.rst

@@ -24,3 +24,15 @@ Development Environment), here are setup instructions for some popular ones:
    xcode
 
 It is possible to use other IDEs, but their setup is not documented yet.
+
+If your editor supports the `language server protocol <https://microsoft.github.io/language-server-protocol/>`__,
+you can use `clangd <https://clangd.llvm.org>`__ for completion, diagnostics, and more.
+You can generate a compilation database for use with clangd one of two ways:
+
+.. code-block:: shell
+
+   # Generate compile_commands.json while compiling
+   scons compiledb=yes
+
+   # Generate compile_commands.json without compiling
+   scons compiledb=yes compile_commands.json

+ 8 - 6
contributing/development/configuring_an_ide/visual_studio.rst

@@ -15,7 +15,9 @@ Visual Studio requires a solution file to work on a project. While Godot does no
 with the solution file, it can be generated using SCons.
 
 - Navigate to the Godot root folder and open a Command Prompt or PowerShell window.
-- Run ``scons platform=windows vsproj=yes`` to generate the solution.
+- | Run ``scons platform=windows vsproj=yes dev_build=yes`` to generate the solution with debug symbols.
+  | The ``vsproj`` parameter signals that you want Visual Studio solution generated.
+  | The ``dev_build`` parameter makes sure the debug symbols are included, allowing to e.g. step through code using breakpoints.
 - You can now open the project by double-clicking on the ``godot.sln`` in the project root
   or by using the **Open a project or solution** option inside of the Visual Studio.
 - Use the **Build** top menu to build the project.
@@ -34,9 +36,9 @@ source code, stop at specific points in the code, inspect the current execution
 and make live changes to the codebase.
 
 You can launch the project with the debugger attached using the **Debug > Start Debugging**
-option from the top menu. However, unless you want to debug the project manager specifically,
+option from the top menu. However, unless you want to debug the Project Manager specifically,
 you'd need to configure debugging options first. This is due to the fact that when the Godot
-project manager opens a project, the initial process is terminated and the debugger gets detached.
+Project Manager opens a project, the initial process is terminated and the debugger gets detached.
 
 - To configure the launch options to use with the debugger use **Project > Properties**
   from the top menu:
@@ -45,11 +47,11 @@ project manager opens a project, the initial process is terminated and the debug
    :align: center
 
 - Open the **Debugging** section and under **Command Arguments** add two new arguments:
-  the ``-e`` flag opens the editor instead of the project manager, and the ``--path`` argument
+  the ``-e`` flag opens the editor instead of the Project Manager, and the ``--path`` argument
   tells the executable to open the specified project (must be provided as an *absolute* path
-  to the project root, not the ``project.godot`` file).
+  to the project root, not the ``project.godot`` file; if the path contains spaces be sure to pass it inside double quotation marks).
 
-.. figure:: img/vs_3_debug_command_line.png
+.. figure:: img/vs_3_debug_command_line.webp
    :align: center
 
 To learn more about command line arguments, refer to the

+ 21 - 22
contributing/development/configuring_an_ide/xcode.rst

@@ -11,35 +11,40 @@ Importing the project
 
 - From Xcode's main screen create a new project using the **Other > External Build System** template.
 
-.. figure:: img/xcode_1_create_external_build_project.png
+.. figure:: img/xcode_1_create_external_build_project.webp
+   :figclass: figure-w480
+   :align: center
+
+- Now choose a name for your project and set the path to scons executable in build tool (to find the path you can type ``where scons`` in a terminal).
+
+.. figure:: img/xcode_2_set_external_build_project_parameters.webp
+   :figclass: figure-w480
+   :align: center
+
+- Open the main target from the **Targets** section and select the **Info** tab.
+
+.. figure:: img/xcode_3_configure_scons.webp
    :figclass: figure-w480
    :align: center
 
-- Open your build targets from the **Targets** section and select the **Info** tab.
 - Fill out the form with the following settings:
 
-  +------------+------------------------------------------------------------------------------+
-  | Build Tool | A full path to the **scons** executable, e.g. **/usr/local/bin/scons**       |
   +------------+------------------------------------------------------------------------------+
   | Arguments  | See :ref:`doc_introduction_to_the_buildsystem` for a full list of arguments. |
   +------------+------------------------------------------------------------------------------+
   | Directory  | A full path to the Godot root folder                                         |
   +------------+------------------------------------------------------------------------------+
 
-.. figure:: img/xcode_2_configure_scons.png
-   :figclass: figure-w480
-   :align: center
-
 - Add a Command Line Tool target which will be used for indexing the project by
   choosing **File > New > Target...**.
 
-.. figure:: img/xcode_3_add_new_target.png
+.. figure:: img/xcode_4_add_new_target.webp
    :figclass: figure-w480
    :align: center
 
-- Select **OS X > Application > Command Line Tool**.
+- Select **macOS > Application > Command Line Tool**.
 
-.. figure:: img/xcode_4_select_command_line_target.png
+.. figure:: img/xcode_5_select_command_line_target.webp
    :figclass: figure-w480
    :align: center
 
@@ -51,16 +56,10 @@ Importing the project
   end of the path, e.g. ``/Users/me/repos/godot-source/**``.
 
 - Add the Godot source to the project by dragging and dropping it into the project file browser.
-- Uncheck **Create external build system project**.
-
-.. figure:: img/xcode_5_after_add_godot_source_to_project.png
-   :figclass: figure-w480
-   :align: center
-
-- Next select **Create groups** for the **Added folders** option and check *only*
+- Select **Create groups** for the **Added folders** option and check *only*
   your command line indexing target in the **Add to targets** section.
 
-.. figure:: img/xcode_6_after_add_godot_source_to_project_2.png
+.. figure:: img/xcode_6_after_add_godot_source_to_project.webp
    :figclass: figure-w480
    :align: center
 
@@ -84,7 +83,7 @@ To enable debugging support you need to edit the external build target's build a
 
   ln -f ${PROJECT_DIR}/godot/bin/godot.macos.tools.64 ${PROJECT_DIR}/godot/bin/godot
 
-.. figure:: img/xcode_7_setup_build_post_action.png
+.. figure:: img/xcode_7_setup_build_post_action.webp
    :figclass: figure-w480
    :align: center
 
@@ -92,14 +91,14 @@ To enable debugging support you need to edit the external build target's build a
 
 - Open the scheme editor again and select **Run**.
 
-.. figure:: img/xcode_8_setup_run_scheme.png
+.. figure:: img/xcode_8_setup_run_scheme.webp
    :figclass: figure-w480
    :align: center
 
 - Set the **Executable** to the file you linked in your post-build action script.
 - Check **Debug executable**.
 - You can add two arguments on the **Arguments** tab:
-  the ``-e`` flag opens the editor instead of the project manager, and the ``--path`` argument
+  the ``-e`` flag opens the editor instead of the Project Manager, and the ``--path`` argument
   tells the executable to open the specified project (must be provided as an *absolute* path
   to the project root, not the ``project.godot`` file).
 

+ 1 - 1
contributing/development/core_and_modules/binding_to_external_libraries.rst

@@ -6,7 +6,7 @@ Binding to external libraries
 Modules
 -------
 
-The Summator example in :ref:`doc_custom_modules_in_c++` is great for small,
+The Summator example in :ref:`doc_custom_modules_in_cpp` is great for small,
 custom modules, but what if you want to use a larger, external library?
 Let's look at an example using `Festival <http://www.cstr.ed.ac.uk/projects/festival/>`_,
 a speech synthesis (text-to-speech) library written in C++.

+ 1 - 1
contributing/development/core_and_modules/custom_audiostreams.rst

@@ -17,7 +17,7 @@ its own internal custom AudioStreamPlayback which translates
 AudioStream into PCM data.
 
 This guide assumes the reader knows how to create C++ modules. If not, refer to this guide
-:ref:`doc_custom_modules_in_c++`.
+:ref:`doc_custom_modules_in_cpp`.
 
 References:
 ~~~~~~~~~~~

+ 1 - 1
contributing/development/core_and_modules/custom_godot_servers.rst

@@ -13,7 +13,7 @@ engine and other modules. In addition, the server claims ownership for
 its RID allocations.
 
 This guide assumes the reader knows how to create C++ modules and Godot
-data types. If not, refer to :ref:`doc_custom_modules_in_c++`.
+data types. If not, refer to :ref:`doc_custom_modules_in_cpp`.
 
 References
 ~~~~~~~~~~~

+ 1 - 1
contributing/development/core_and_modules/custom_modules_in_cpp.rst

@@ -1,4 +1,4 @@
-.. _doc_custom_modules_in_c++:
+.. _doc_custom_modules_in_cpp:
 
 Custom modules in C++
 =====================

+ 190 - 0
contributing/development/core_and_modules/custom_platform_ports.rst

@@ -0,0 +1,190 @@
+.. _doc_custom_platform_ports:
+
+Custom platform ports
+=====================
+
+Similar to :ref:`doc_custom_modules_in_cpp`, Godot's multi-platform architecture
+is designed in a way that allows creating platform ports without modifying any
+existing source code.
+
+An example of a custom platform port distributed independently from the engine
+is `FRT <https://github.com/efornara/frt>`__, which targets single-board
+computers. Note that this platform port currently targets Godot 3.x; therefore,
+it does not use the :ref:`class_DisplayServer` abstraction that is new in Godot 4.
+
+Some reasons to create custom platform ports might be:
+
+- You want to :ref:`port your game to consoles <doc_consoles>`, but wish to
+  write the platform layer yourself. This is a long and arduous process, as it
+  requires signing NDAs with console manufacturers, but it allows you to have
+  full control over the console porting process.
+- You want to port Godot to an exotic platform that isn't currently supported.
+
+If you have questions about creating a custom platform port, feel free to ask in
+the ``#platforms`` channel of the
+`Godot Contributors Chat <https://chat.godotengine.org/channel/platforms>`__.
+
+.. note::
+
+    Godot is a modern engine with modern requirements. Even if you only
+    intend to run simple 2D projects on the target platform, it still requires
+    an amount of memory that makes it unviable to run on most retro consoles.
+    For reference, in Godot 4, an empty project with nothing visible requires
+    about 100 MB of RAM to run on Linux (50 MB in headless mode).
+
+    If you want to run Godot on heavily memory-constrained platforms, older
+    Godot versions have lower memory requirements. The porting process is
+    similar, with the exception of :ref:`class_DisplayServer` not being split
+    from the :ref:`class_OS` singleton.
+
+Official platform ports
+-----------------------
+
+The official platform ports can be used as a reference when creating a custom platform port:
+
+- `Windows <https://github.com/godotengine/godot/tree/master/platform/windows>`__
+- `macOS <https://github.com/godotengine/godot/tree/master/platform/macos>`__
+- `Linux/\*BSD <https://github.com/godotengine/godot/tree/master/platform/linuxbsd>`__
+- `Android <https://github.com/godotengine/godot/tree/master/platform/android>`__
+- `iOS <https://github.com/godotengine/godot/tree/master/platform/ios>`__
+- `UWP <https://github.com/godotengine/godot/tree/master/platform/uwp>`__ *(not currently working)*
+- `Web <https://github.com/godotengine/godot/tree/master/platform/web>`__
+
+While platform code is usually self-contained, there are exceptions to this
+rule. For instance, audio drivers that are shared across several platforms and
+rendering backends are located in the
+`drivers/ folder <https://github.com/godotengine/godot/tree/master/drivers>`__
+of the Godot source code.
+
+Creating a custom platform port
+-------------------------------
+
+Creating a custom platform port is a large undertaking which requires prior
+knowledge of the platform's SDKs. Depending on what features you need, the
+amount of work needed varies:
+
+Required features of a platform port
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+At the very least, a platform port must have methods from the :ref:`class_OS`
+singleton implemented to be buildable and usable for headless operation.
+A ``logo.png`` (32×32) image must also be present within the platform folder.
+This logo is displayed in the Export dialog for each export preset targeting
+the platform in question.
+
+See `this implementation <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/os_linuxbsd.cpp>`__
+for the Linux/\*BSD platform as an example. See also the
+`OS singleton header <https://github.com/godotengine/godot/blob/master/core/os/os.h>`__
+for reference.
+
+.. note::
+
+    If your target platform is UNIX-like, consider inheriting from the ``OS_Unix``
+    class to get much of the work done automatically.
+
+    If the platform is not UNIX-like, you might use the
+    `Windows port <https://github.com/godotengine/godot/blob/master/platform/windows/os_windows.cpp>`
+    as a reference.
+
+**detect.py file**
+
+A ``detect.py`` file must be created within the platform's folder with all
+methods implemented. This file is required for SCons to detect the platform as a
+valid option for compiling. See the
+`detect.py file <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/detect.py>`__
+for the Linux/\*BSD platform as an example.
+
+All methods should be implemented within ``detect.py`` as follows:
+
+- ``is_active()``: Can be used to temporarily disable building for a platform.
+  This should generally always return ``True``.
+- ``get_name()``: Returns the platform's user-visible name as a string.
+- ``can_build()``: Return ``True`` if the host system is able to build for the
+  target platform, ``False`` otherwise. Do not put slow checks here, as this is
+  queried when the list of platforms is requested by the user. Use
+  ``configure()`` for extensive dependency checks instead.
+- ``get_opts()``: Returns the list of SCons build options that can be defined by
+  the user for this platform.
+- ``get_flags()``: Returns the list of overridden SCons flags for this platform.
+- ``configure()``: Perform build configuration, such as selecting compiler
+  options depending on SCons options chosen.
+
+Optional features of a platform port
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In practice, headless operation doesn't suffice if you want to see anything on
+screen and handle input devices. You may also want audio output for most
+games.
+
+*Some links on this list point to the Linux/\*BSD platform implementation as a reference.*
+
+- One or more `DisplayServers <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/x11/display_server_x11.cpp>`__,
+  with the windowing methods implemented. DisplayServer also covers features such
+  as mouse support, touchscreen support and tablet driver (for pen input).
+  See the
+  `DisplayServer singleton header <https://github.com/godotengine/godot/blob/master/servers/display_server.h>`__
+  for reference.
+
+  - For platforms not featuring full windowing support (or if it's not relevant
+    for the port you are making), most windowing functions can be left mostly
+    unimplemented. These functions can be made to only check if the window ID is
+    ``MAIN_WINDOW_ID`` and specific operations like resizing may be tied to the
+    platform's screen resolution feature (if relevant). Any attempt to create
+    or manipulate other window IDs can be rejected.
+- *If the target platform supports the graphics APIs in question:* Rendering
+  context for `Vulkan <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/x11/vulkan_context_x11.cpp>`__,
+  `OpenGL 3.3 or OpenGL ES 3.0 <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/x11/gl_manager_x11.cpp>`__.
+- Input handlers for `keyboard <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/x11/key_mapping_x11.cpp>`__
+  and `controller <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/joypad_linux.cpp>`__.
+- One or more `audio drivers <https://github.com/godotengine/godot/blob/master/drivers/pulseaudio/audio_driver_pulseaudio.cpp>`__.
+  The audio driver can be located in the ``platform/`` folder (this is done for
+  the Android and Web platforms), or in the ``drivers/`` folder if multiple
+  platforms may be using this audio driver. See the
+  `AudioServer singleton header <https://github.com/godotengine/godot/blob/master/servers/audio_server.h>`__
+  for reference.
+- `Crash handler <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/crash_handler_linuxbsd.cpp>`__,
+  for printing crash backtraces when the game crashes. This allows for easier
+  troubleshooting on platforms where logs aren't readily accessible.
+- `Text-to-speech driver <https://github.com/godotengine/godot/blob/master/platform/linuxbsd/tts_linux.cpp>`__
+  (for accessibility).
+- `Export handler <https://github.com/godotengine/godot/tree/master/platform/linuxbsd/export>`__
+  (for exporting from the editor, including :ref:`doc_one-click_deploy`).
+  Not required if you intend to export only a PCK from the editor, then run the
+  export template binary directly by renaming it to match the PCK file. See the
+  `EditorExportPlatform header <https://github.com/godotengine/godot/blob/master/editor/export/editor_export_platform.h>`__
+  for reference.
+  ``run_icon.png`` (16×16) should be present within the platform folder if
+  :ref:`doc_one-click_deploy` is implemented for the target platform. This icon
+  is displayed at the top of the editor when one-click deploy is set up for the
+  target platform.
+
+If the target platform doesn't support running Vulkan, OpenGL 3.3 or OpenGL ES 3.0,
+you have two options:
+
+- Use a library at run-time to translate Vulkan or OpenGL calls to another graphics API.
+  For example, `MoltenVK <https://moltengl.com/moltenvk/>`__ is used on macOS
+  to translate Vulkan to Metal at run-time.
+- Create a new renderer from scratch. This is a large undertaking, especially if
+  you want to support both 2D and 3D rendering with advanced features.
+
+Distributing a custom platform port
+-----------------------------------
+
+.. warning::
+
+    Before distributing a custom platform port, make sure you're allowed to
+    distribute all the code that is being linked against. Console SDKs are
+    typically under NDAs which prevent redistribution to the public.
+
+Platform ports are designed to be as self-contained as possible. Most of the
+code can be kept within a single folder located in ``platform/``. Like
+:ref:`doc_custom_modules_in_cpp`, this allows for streamlining the build process
+by making it possible to ``git clone`` a platform folder within a Godot repository
+clone's ``platform/`` folder, then run ``scons platform=<name>``. No other steps are
+necessary for building, unless third-party platform-specific dependencies need
+to be installed first.
+
+However, when a custom rendering backend is needed, another folder must be added
+in ``drivers/``. In this case, the platform port can be distributed as a fork of
+the Godot repository, or as a collection of several folders that can be added
+over a Godot Git repository clone.

+ 2 - 2
contributing/development/core_and_modules/custom_resource_format_loaders.rst

@@ -12,7 +12,7 @@ path again, the previous loaded Resource will be referenced. Naturally,
 loaded resources must be stateless.
 
 This guide assumes the reader knows how to create C++ modules and Godot
-data types. If not, refer to this guide: :ref:`doc_custom_modules_in_c++`
+data types. If not, refer to this guide: :ref:`doc_custom_modules_in_cpp`
 
 References
 ~~~~~~~~~~
@@ -380,7 +380,7 @@ Then attach the following script to any node::
 
     extends Node
 
-    onready var json_resource = load("res://demo.json")
+    @onready var json_resource = load("res://demo.json")
 
     func _ready():
         print(json_resource.get_dict())

+ 1 - 0
contributing/development/core_and_modules/index.rst

@@ -34,4 +34,5 @@ This section covers what you can do by modifying Godot's C++ source code.
    custom_godot_servers
    custom_resource_format_loaders
    custom_audiostreams
+   custom_platform_ports
    unit_testing

+ 2 - 2
contributing/development/debugging/index.rst

@@ -16,8 +16,8 @@ Debugging the editor
 --------------------
 
 When working on the Godot editor keep in mind that by default the executable
-will start in the project manager mode. Opening a project from the project
-manager spawns a new process, which stops the debugging session. To avoid that
+will start in the Project Manager mode. Opening a project from the Project
+Manager spawns a new process, which stops the debugging session. To avoid that
 you should launch directly into the project using ``-e`` and ``--path`` launch
 options.
 

+ 2 - 2
contributing/development/debugging/using_cpp_profilers.rst

@@ -68,8 +68,8 @@ VerySleepy
 ^^^^^^^^^^
 
 - Start the Godot editor or your project first.
-  If you start the project manager, make sure to edit or run a project first.
-  Otherwise, the profiler will not track the child process since the project manager
+  If you start the Project Manager, make sure to edit or run a project first.
+  Otherwise, the profiler will not track the child process since the Project Manager
   will spawn a child process for every project edited or run.
 - Open VerySleepy and select the Godot executable in the list of processes on the left:
 

+ 3 - 3
contributing/development/editor/introduction_to_editor_development.rst

@@ -37,7 +37,7 @@ The editor's code is fully self-contained in the
 of the Godot source repository.
 
 Some editor functionality is also implemented via
-:ref:`modules <doc_custom_modules_in_c++>`. Some of these are only enabled in
+:ref:`modules <doc_custom_modules_in_cpp>`. Some of these are only enabled in
 editor builds to decrease the binary size of export templates. See the
 `modules/ <https://github.com/godotengine/godot/tree/master/modules>`__ folder
 in the Godot source repository.
@@ -47,7 +47,7 @@ Some important files in the editor are:
 - `editor/editor_node.cpp <https://github.com/godotengine/godot/blob/master/editor/editor_node.cpp>`__:
   Main editor initialization file. Effectively the "main scene" of the editor.
 - `editor/project_manager.cpp <https://github.com/godotengine/godot/blob/master/editor/project_manager.cpp>`__:
-  Main project manager initialization file. Effectively the "main scene" of the project manager.
+  Main Project Manager initialization file. Effectively the "main scene" of the Project Manager.
 - `editor/plugins/canvas_item_editor_plugin.cpp <https://github.com/godotengine/godot/blob/master/editor/plugins/canvas_item_editor_plugin.cpp>`__:
   The 2D editor viewport and related functionality (toolbar at the top, editing modes, overlaid helpers/panels, …).
 - `editor/plugins/node_3d_editor_plugin.cpp <https://github.com/godotengine/godot/blob/master/editor/plugins/node_3d_editor_plugin.cpp>`__:
@@ -84,5 +84,5 @@ Development tips
 
 To iterate quickly on the editor, we recommend to set up a test project and
 :ref:`open it from the command line <doc_command_line_tutorial>` after compiling
-the editor. This way, you don't have to go through the project manager every
+the editor. This way, you don't have to go through the Project Manager every
 time you start Godot.

+ 2 - 2
contributing/documentation/building_the_manual.rst

@@ -103,10 +103,10 @@ program manually:
 
 .. code:: sh
 
-   sphinx-build -b html ./ _build
+   sphinx-build -b html ./ _build/html
 
 You can also specify a list of files to build, which can greatly speed up compilation:
 
 .. code:: sh
 
-  sphinx-build -b html ./ _build classes/class_node.rst classes/class_resource.rst
+  sphinx-build -b html ./ _build/html classes/class_node.rst classes/class_resource.rst

+ 6 - 6
contributing/documentation/docs_writing_guidelines.rst

@@ -348,10 +348,10 @@ could use the code snippets in a live project.
 
 **Don't** write made-up examples:
 
-::
+.. code-block:: gdscript
 
-    onready var a = preload("res://MyPath")
-    onready var my_node = $MyNode
+    @onready var a = preload("res://MyPath")
+    @onready var my_node = $MyNode
 
 
     func foo():
@@ -359,10 +359,10 @@ could use the code snippets in a live project.
 
 **Do** write concrete examples:
 
-::
+.. code-block:: gdscript
 
-    onready var sfx_player_gun = preload("res://Assets/Sound/SFXPlayerGun.ogg")
-    onready var audio_player = $Audio/AudioStreamPlayer
+    @onready var sfx_player_gun = preload("res://Assets/Sound/SFXPlayerGun.ogg")
+    @onready var audio_player = $Audio/AudioStreamPlayer
 
 
     func play_shooting_sound():

+ 1 - 1
contributing/ways_to_contribute.rst

@@ -56,7 +56,7 @@ Contributing code
 The possibility to study, use, modify and redistribute modifications of the
 engine's source code are the fundamental rights that
 Godot's `MIT <https://tldrlegal.com/license/mit-license>`_ license grants you,
-making it `free and open source software <https://en.wikipedia.org/wiki/Free_and_open source_software>`_.
+making it `free and open source software <https://en.wikipedia.org/wiki/Free_and_open-source_software>`_.
 
 As such, everyone is entitled to modify
 `Godot's source code <https://github.com/godotengine/godot>`_, and send those

+ 1 - 0
contributing/workflow/index.rst

@@ -15,4 +15,5 @@ approach the project.
    bisecting_regressions
    bug_triage_guidelines
    pr_workflow
+   pr_review_guidelines
    testing_pull_requests

+ 421 - 0
contributing/workflow/pr_review_guidelines.rst

@@ -0,0 +1,421 @@
+.. _doc_pr_review_guidelines:
+
+Pull request review process
+===========================
+
+.. note::
+
+    This page is intended to provide insight into the pull request (PR) review
+    process that we aspire to. As such, it is primarily targeted at engine
+    maintainers who are responsible for reviewing and approving pull requests.
+    That being said, much of the content is useful for prospective contributors
+    wanting to know how to ensure that their PR is merged.
+
+From a high level, the ideal life cycle of a pull request looks like the
+following: 
+
+  1. A contributor opens a PR that fixes a specific problem (optimally closing
+     a GitHub `issue <https://github.com/godotengine/godot>`_ or implementing
+     a `proposal <https://github.com/godotengine/godot-proposals>`_).
+
+  2. Other contributors provide feedback on the PR (including reviewing and/or
+     approving the PR, as appropriate).
+
+  3. An engine maintainer reviews the code and provides feedback, requests
+     changes, or approves the pull request, as appropriate.
+
+  4. Another maintainer reviews the code with a focus on code style/clarity and
+     approves it once satisfied.
+
+  5. A team leader or a member of the `production team
+     <https://godotengine.org/teams#production>`_ merges the pull request if
+     satisfied that it has been sufficiently reviewed.
+
+This document will explain steps 2, 3, 4, and 5 in more detail. For a more
+detailed explanation of the pull request workflow please see the :ref:`pull
+request workflow document <doc_pr_workflow>`. 
+
+.. note:: 
+  In practice these steps may blend together. Oftentimes maintainers will
+  provide comments on code style and code quality at the same time and will
+  approve a pull request for both.
+
+Typically the first interaction on a pull request will be an engine maintainer
+assigning tags to the pull request and flagging it for review by someone
+familiar with that area of code.
+
+Engine maintainers are folks who are "members" of the Godot project repository
+on GitHub and/or are listed on the `Teams page <https://godotengine.org/teams>`_
+on the Godot website. Maintainers are responsible for a given area of the
+engine. Typically this means they are the people who are given more trust to
+approve and recommend pull requests for merging.
+
+Even if you are not a maintainer, you can still help by reviewing code,
+providing feedback on PRs and testing PRs locally on your machine to confirm
+that they work as intended. Many of the currently active maintainers started out
+doing this before they became maintainers.
+
+Code review and testing
+-----------------------
+
+The following is a list of things that contributors and engine maintainers can
+do to conduct a substantive code review of a pull request.
+
+.. note::
+  If you want to conduct a code review, but can't do everything on this list,
+  say that in your review comment. For example, it is still very helpful to
+  provide comments on code, even if you can't build the pull request locally to
+  test the pull request (or vice versa). Feel free to review the code, just
+  remember to make a note at the end of your review that you have reviewed the
+  code only and have not tested the changes locally.
+
+1. Confirm that the problem exists
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+PRs need to solve problems and problems need to be documented. Make sure that
+the pull request links and closes (or at least addresses) a bug or a proposal.
+If it doesn't, consider asking the contributor to update the opening message of
+the PR to explain the problem that the PR aims to solve in more detail.
+
+.. note::
+  It should be clear _why_ a pull request is needed before it is merged. This
+  assists reviewers in determining whether a PR does what it says it does and it
+  helps contributors in the future understand why the code is the way it is.
+
+2. Test the PR and look for regressions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+While strict code review and CI help to ensure that all pull requests work as
+intended, mistakes happen and sometimes contributors push code that creates a
+problem in addition to solving a problem. Maintainers will avoid merging code
+that contains a regression even if it solves the problem as intended.
+
+When reviewing a pull request, ensure that the PR does what it says it does
+(i.e. fixes the linked bug or implements the new feature) and nothing outside of
+the PR target area is broken by the change. You can do this by running the
+editor and trying out some common functions of the editor (adding objects to a
+scene, running GDScript, opening and closing menus etc.). Also, while reviewing
+the code, look for suspicious changes in other parts of the engine. Sometimes
+during rebasing changes slip through that contributors are not aware of.
+
+3. Do a code review
+^^^^^^^^^^^^^^^^^^^
+
+Code reviews are usually done by people who are already experienced in a given
+area. They may be able to provide ideas to make code faster, more organized, or
+more idiomatic. But, even if you are not very experienced, you may want to
+conduct a code review to provide feedback within the scope of what you are
+comfortable reviewing. Doing so is valuable for the area maintainer (as a second
+set of eyes on a problem is always helpful) and it is also helpful for you as it
+will help you get more familiar with that area of code and will expose you to
+how other people solve problems. In fact, reviewing the code of experienced
+engine maintainers is a great way to get to know the codebase.
+
+Here are some things to think about and look out for as you review the code:
+
+* **Code only touches the areas announced in the PR (and the commit
+  message).**
+
+  It can be tempting to fix random things in the code, as you see them. However,
+  this can quickly make a pull request difficult to review and can make it hard
+  to dig through in the commit history. Small touch-ups next to the related area
+  are alright, but often bugs that you can find along the way are better fixed
+  in their own PRs.
+
+* **Code properly uses Godot's own APIs and patterns.**
+
+  Consistency is very important, and a solution that already exists in the
+  codebase is preferable to an ad-hoc solution.
+
+* **Are core areas affected by the change?**
+
+  Sometimes a PR that is supposed to solve a local problem can have a
+  far-reaching effect way outside of its scope. Usually it is best to keep code
+  changes local to where the problem arises. If you think that the solution
+  requires changes outside the scope of the problem, it is usually best to seek
+  the opinion of a team leader who may have another idea for how to solve the
+  problem.
+
+4. Iterate with the contributor and improve the PR
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Maintainers should provide feedback and suggestions for improvement if they spot
+things in the code that they would like changed. Preferably, suggestions should
+come in order of importance: first, address overall code design and the approach
+to solving the problem, then make sure the code is complying with the engine's
+best practices, and lastly, do the :ref:`code style review <doc_code_style_review>`.
+
+.. note::
+
+    **Communicate barriers to merging early in the review process.**
+
+    If the PR has clear blockers or will likely not get merged for whatever other
+    reason, that fact should be communicated as early and clearly as possible. We
+    want to avoid stringing people along because it feels bad to say "sorry, no".
+
+As you review pull requests, keep the Godot `Code of Conduct
+<https://godotengine.org/code-of-conduct>`_ in mind. Especially the following:
+
+* Politeness is expected at all times. Be kind and courteous.
+
+* Always assume positive intent from others.
+
+* Feedback is always welcome but keep your criticism constructive.
+
+Here are some things to avoid as you iterate on a pull request with a
+contributor:
+
+* **Needless double reviews.**
+
+  In other words, review the full PR at once and avoid coming back endless times
+  to point out issues that you could have noted in the first review. Of course,
+  this can't always be avoided, but we should try to catch everything at once.
+
+* **Being overly nitpicky.**
+
+  Code quality can be flexible depending on the area of the engine you are
+  working in. In general, our standard for code quality is much higher in core
+  areas and in performance-sensitive areas than it is in editor code for
+  example.
+
+* **Expanding the scope of a pull request.** 
+
+  Providing context or related/similar issues or proposals that may be fixed
+  similarly can be helpful, but adding a "may as well fix that thing over there
+  as well while at it" or "could we add to this as well?" isn't always fair to
+  the contributor. Use your judgement when deciding whether additional fixes are
+  within scope, but try to keep the scope as close to the original pull request
+  as possible.
+
+And ultimately, don't feel pressured to deal with the PR all alone. Feel free to
+ask for a helping hand on the `Godot Contributors Chat
+<https://chat.godotengine.org>`_, in the appropriate channel or in #general.
+Other teams may already be tagged for review, so you can also wait or ask for
+their assistance.
+
+5. Approve the pull request
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+After reviewing the code, if you think that the code is ready to be merged into
+the engine, then go ahead and "approve" it. Make sure to also comment and
+specify the nature of your review (i.e. say whether you ran the code locally,
+whether you reviewed for style as well as correctness, etc.). Even if you are
+not an engine maintainer, approving a pull request signals to others that the
+code is good and likely solves the problem the PR says it does. Approving a pull
+request as a non-engine maintainer does not guarantee that the code will be
+merged, other people will still review it, so don't be shy.
+
+.. _doc_code_style_review:
+
+Code style review
+-----------------
+
+Generally speaking, we aim to conduct a code review before a style/clarity
+review as contributors typically want to know if their general approach is
+acceptable before putting in the effort to make nitpicky changes to style. In
+other words, maintainers shouldn't ask contributors to change the style of code
+that may need to be rewritten in subsequent reviews. Similarly, maintainers
+should avoid asking for contributors to rebase PRs if the PR has not been
+reviewed.
+
+That being said, not everyone feels confident enough to provide a review on code
+correctness, in that case, providing comments on code style and clarity ahead of
+a more substantive code review is totally appropriate and more than welcome.
+
+In practice the code style review can be done as part of the substantive code
+review. The important thing is that both the substantive code and the code style
+need to be reviewed and considered before a pull request is merged.
+
+When reviewing code style pay particular attention to ensuring that the pull
+request follows the :ref:`doc_code_style_guidelines`. While ``clang-format`` and
+various CI checks can catch a lot of inconsistencies, they are far from perfect
+and are unable to detect some issues. For example, you should check that:
+
+  * The style of header includes is respected.
+  * Identifiers use ``snake_case`` and follow our naming conventions.
+  * Method parameters start with ``p_*`` or ``r_*`` (if they are used to return
+    a value).
+  * Braces are used appropriately, even for one-liner conditionals.
+  * Code is properly spaced (exactly one empty line between methods, no
+    unnecessary empty lines inside of method bodies).
+
+.. note::
+
+    This list is not complete and doesn't aim to be complete. Refer to
+    the linked style guide document for a complete set of rules. Keep
+    in mind that ``clang-format`` may not catch things you hope it would,
+    so pay attention and try to build a sense of what exactly it can and
+    cannot detect.
+
+Merging pull requests
+---------------------
+
+In general, pull requests should only be merged by members of the production
+team or team leaders for pull requests in their area of the engine. For example,
+the networking team leader could merge a networking pull request that doesn't
+substantially change non-networking sections of code. 
+
+In practice it is best to wait for a member of the production team to merge the
+pull request as they keep a close eye on the entire codebase and will likely
+have a better sense of what other recent/upcoming changes this pull request may
+conflict with (or any other reason that it may make sense to delay the pull
+request). Feel free to leave a comment saying that the PR should be ready to
+merge.
+
+The following are the steps to take before merging a pull request. The degree to
+which you adhere to these steps can be flexible for simple/straightforward pull
+requests, but they should be carefully taken for complex or risky pull requests.
+
+As a contributor you can help move a pull request forward by doing some of these
+steps yourself.
+
+1. Get feedback from the right people/teams
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Production team members should ensure that the right people look at a pull
+request before it is merged. In some cases this may require multiple people to
+weigh in. In other cases, only one substantive approval is needed before the
+code can be merged. 
+
+In general, try not to merge things based on one review alone, especially if it
+is your own. Get a second opinion from another maintainer, and make sure all the
+teams that may be impacted have been reasonably represented by the reviewers.
+For example, if a pull request adds to the documentation, it's often useful to
+let the area maintainers check it for factual correctness and let documentation
+maintainers check it for formatting, style, and grammar.
+
+A good rule of thumb is that at least one subject matter expert should have
+approved the pull request for correctness, and at least one other maintainer
+should have approved the pull request for code style. Either of those people
+could be the person merging the pull request.
+
+Make sure that the reviews and approvals were left by people competent in that
+specific engine area. It is possible that even a long-standing member of the
+Godot organization left a review without having the relevant expertise.
+
+.. note::
+
+    An easy way to find PRs that may be ready for merging is filtering by
+    approved PRs and sorting by recently updated. For example, in the main Godot
+    repository, you can use `this link
+    <https://github.com/godotengine/godot/pulls?q=is%3Apr+is%3Aopen+review%3Aapproved+sort%3Aupdated-desc>`_.
+
+2. Get feedback from the community
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If a pull request is having trouble attracting reviewers, you may need to reach
+out more broadly to ask for help reviewing. Consider asking:
+
+* the person who reported the bug if the pull request fixes the bug for them,
+* contributors who have recently edited that file if they could take a look, or
+* a more experienced maintainer from another area if they could provide feedback.
+
+3. Git checklist
+^^^^^^^^^^^^^^^^
+
+* **Make sure that the PR comes in one commit.**
+
+  When each commit is self-contained and could be used to build a clean and
+  working version of the engine, it may be okay to merge a pull request with
+  multiple commits, but in general, we require that all pull requests only have
+  one commit. This helps us keep the Git history clean.
+
+* **Fixes made during the review process must be squashed into
+  the main commit.**
+
+  For multi-commit PRs check that those fixes are amended in the relevant
+  commits, and are not just applied on top of everything.
+
+* **Make sure that the PR has no merge conflicts.**
+
+  Contributors may need to rebase their changes on top of the relevant branch
+  (e.g. ``master`` or ``3.x``) and manually fix merge conflicts. Even if there
+  are no merge conflicts, contributors may need to rebase especially old PRs as
+  the GitHub conflict checker may not catch all conflicts, or the CI may have
+  changed since it was originally run.
+
+* **Check for proper commit attribution.**
+
+  If a contributor uses an author signature that is not listed in their GitHub
+  account, GitHub won't link the merged pull request to their account. This
+  keeps them from getting proper credit in the GitHub history and makes them
+  appear like a new contributor on the GitHub UI even after several
+  contributions.
+
+  Ultimately, it's up to the user if they want to fix it, but they can do so by
+  authoring the Git commit with the same email they use for their GitHub
+  account, or by adding the email they used for the Git commit to their GitHub
+  profile.
+
+* **Check for proper commit messages.**
+
+  While we don't have a very strict ruleset for commit messages, we still
+  require them to be short yet descriptive and use proper English. As a
+  maintainer you've probably written them enough times to know how to make one,
+  but for a general template think about *"Fix <issue> in <part of codebase>"*.
+  For a more detailed recommendation see the `contributing.md
+  <https://github.com/godotengine/godot/blob/master/CONTRIBUTING.md#format-your-commit-messages-with-readability-in-mind>`_
+  page in the main Godot repository.
+
+4. GitHub checklist
+^^^^^^^^^^^^^^^^^^^
+
+* **Validate the target branch of the PR.**
+
+  Most Godot development happens around in the ``master`` branch. Therefore most
+  pull requests must be made against it. From there pull requests can then be
+  backported to other branches. Be wary of people making PRs on the version they
+  are using (e.g, ``3.3``) and guide them to make a change against a
+  higher-order branch (e.g. ``3.x``). If the change is not applicable for the
+  ``master`` branch, the initial PR can be made against the current maintenance
+  branch, such as ``3.x``. It's okay for people to make multiple PRs for each
+  target branch, especially if the changes cannot be easily backported.
+  Cherry-picking is also an option, if possible. Use the appropriate labels if
+  the PR can be cherrypicked (e.g. ``cherrypick:3.x``).
+
+.. note::
+
+    It is possible to change the target branch of the PR, that has already been
+    submitted, but be aware of the consequences. As it cannot be synchronized
+    with the push, the target branch change will inevitable tag the entire list
+    of maintainers for review. It may also render the CI incapable of running
+    properly. A push should help with that, but if nothing else, recommend
+    opening a new, fresh PR.
+
+* **Make sure that the appropriate milestone is assigned.**
+
+  This will make it more obvious which version would include the submitted
+  changes, should the pull request be merged now. Note, that the milestone is
+  not a binding contract and does not guarantee that this version is definitely
+  going to include the PR. If the pull request is not merged before the version
+  is released, the milestone will be moved (and the PR itself may require a
+  target branch change).
+
+  Similarly, when merging a PR with a higher milestone than the current version,
+  or a "wildcard" milestone (e.g. "4.x"), ensure to update the milestone to the
+  current version.
+
+* **Make sure that the opening message of the PR contains the
+  magic words "Closes #..." or "Fixes #...".**
+
+  These link the PR and the referenced issue together and allow GitHub to
+  auto-close the latter when you merge the changes. Note, that this only works
+  for the PRs that target the ``master`` branch. For others you need to pay
+  attention and close the related issues manually. Do it with *"Fixed by #..."*
+  or *"Resolved by #..."* comment to clearly indicate the act for future
+  contributors.
+
+* **For the issues that get closed by the PR add the closest
+  relevant milestone.**
+
+  In other words, if the PR is targeting the ``master`` branch, but is then also
+  cherrypicked for ``3.x``, the next ``3.x`` release would be the appropriate
+  milestone for the closed issue.
+
+5. Merge the pull request
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If it is appropriate for you to be merging a pull request (i.e. you are on the
+production team or you are the team leader for that area), you are confident
+that the pull request has been sufficiently reviewed, and once you carry out
+these steps you can go ahead and merge the pull request.

+ 6 - 6
contributing/workflow/pr_workflow.rst

@@ -136,7 +136,7 @@ metadata is hidden in its ``.git`` subfolder).
           working in Git.
 
 In the following, we will assume as an example that you want to implement a feature in
-Godot's project manager, which is coded in the ``editor/project_manager.cpp``
+Godot's Project Manager, which is coded in the ``editor/project_manager.cpp``
 file.
 
 Branching
@@ -298,7 +298,7 @@ Here's how the shell history could look like on our example:
     # It's nice to know where you're starting from
     $ git log
 
-    # Do changes to the project manager with the nano text editor
+    # Do changes to the Project Manager with the nano text editor
     $ nano editor/project_manager.cpp
 
     # Find an unrelated bug in Control and fix it
@@ -320,7 +320,7 @@ Here's how the shell history could look like on our example:
 
     # Make our second commit
     $ git add editor/project_manager.cpp
-    $ git commit -m "Add a pretty banner to the project manager"
+    $ git commit -m "Add a pretty banner to the Project Manager"
     $ git log
 
 With this, we should have two new commits in our ``better-project-manager``
@@ -476,7 +476,7 @@ to configure your favorite one) with something which may look like this:
 
 .. code-block:: text
 
-    pick 1b4aad7 Add a pretty banner to the project manager
+    pick 1b4aad7 Add a pretty banner to the Project Manager
     pick e07077e Fix a typo in the banner's title
 
 The editor will also show instructions regarding how you can act on those
@@ -489,7 +489,7 @@ so we use:
 
 .. code-block:: text
 
-    pick 1b4aad7 Add a pretty banner to the project manager
+    pick 1b4aad7 Add a pretty banner to the Project Manager
     fixup e07077e Fix a typo in the banner's title
 
 Upon saving and quitting the editor, the rebase will occur. The second commit
@@ -531,7 +531,7 @@ Git branch for the PR. There won't be issues if you don't delete your branch, bu
 good practice to do so. You'll need to do this twice, once for the local branch and another
 for the remote branch on GitHub.
 
-To delete our better project manager branch locally, use this command:
+To delete our better Project Manager branch locally, use this command:
 
 ::
 

+ 1 - 1
getting_started/first_2d_game/01.project_setup.rst

@@ -25,7 +25,7 @@ Launch Godot and create a new project.
     and ``fonts/`` directories to your project's directory.
 
     Ensure that you have the required dependencies to use C# in Godot.
-    You need the .NET Core 3.1 SDK, and an editor such as VS Code.
+    You need the latest stable .NET SDK, and an editor such as VS Code.
     See :ref:`doc_c_sharp_setup`.
 
  .. tab:: C++

+ 1 - 1
getting_started/first_2d_game/02.player_scene.rst

@@ -65,7 +65,7 @@ display. To create one, find the ``Sprite Frames`` property in the Inspector and
 
 
 On the left is a list of animations. Click the "default" one and rename it to
-"walk". Then click the "New Animation" button to create a second animation named
+"walk". Then click the "Add Animation" button to create a second animation named
 "up". Find the player images in the "FileSystem" tab - they're in the ``art``
 folder you unzipped earlier. Drag the two images for each animation, named
 ``playerGrey_up[1/2]`` and ``playerGrey_walk[1/2]``, into the "Animation Frames"

+ 27 - 20
getting_started/first_2d_game/03.coding_the_player.rst

@@ -89,11 +89,18 @@ node and you'll see the property now appears in the "Script Variables" section
 of the Inspector. Remember, if you change the value here, it will override the
 value written in the script.
 
-.. warning:: If you're using C#, you need to (re)build the project assemblies
-             whenever you want to see new export variables or signals. This
-             build can be manually triggered by clicking the word "Mono" at the
-             bottom of the editor window to reveal the Mono Panel, then clicking
-             the "Build Project" button.
+.. warning::
+
+    If you're using C#, you need to (re)build the project assemblies
+    whenever you want to see new export variables or signals. This
+    build can be manually triggered by clicking the "Build" button at
+    the top right of the editor.
+
+    .. image:: img/build_dotnet.webp
+
+    A manual build can also be triggered from the MSBuild Panel. Click
+    the word "MSBuild" at the bottom of the editor window to reveal the
+    MSBuild Panel, then click the "Build" button.
 
 .. image:: img/export_variable.webp
 
@@ -206,22 +213,22 @@ which returns ``true`` if it's pressed or ``false`` if it isn't.
 
         if (Input.IsActionPressed("move_right"))
         {
-            velocity.x += 1;
+            velocity.X += 1;
         }
 
         if (Input.IsActionPressed("move_left"))
         {
-            velocity.x -= 1;
+            velocity.X -= 1;
         }
 
         if (Input.IsActionPressed("move_down"))
         {
-            velocity.y += 1;
+            velocity.Y += 1;
         }
 
         if (Input.IsActionPressed("move_up"))
         {
-            velocity.y -= 1;
+            velocity.Y -= 1;
         }
 
         var animatedSprite2D = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
@@ -297,8 +304,8 @@ the ``_process`` function (make sure it's not indented under the `else`):
 
         Position += velocity * (float)delta;
         Position = new Vector2(
-            x: Mathf.Clamp(Position.x, 0, ScreenSize.x),
-            y: Mathf.Clamp(Position.y, 0, ScreenSize.y)
+            x: Mathf.Clamp(Position.X, 0, ScreenSize.X),
+            y: Mathf.Clamp(Position.Y, 0, ScreenSize.Y)
         );
 
  .. code-tab:: cpp
@@ -350,17 +357,17 @@ movement. Let's place this code at the end of the ``_process()`` function:
 
  .. code-tab:: csharp
 
-        if (velocity.x != 0)
+        if (velocity.X != 0)
         {
             animatedSprite2D.Animation = "walk";
             animatedSprite2D.FlipV = false;
             // See the note below about boolean assignment.
-            animatedSprite2D.FlipH = velocity.x < 0;
+            animatedSprite2D.FlipH = velocity.X < 0;
         }
-        else if (velocity.y != 0)
+        else if (velocity.Y != 0)
         {
             animatedSprite2D.Animation = "up";
-            animatedSprite2D.FlipV = velocity.y > 0;
+            animatedSprite2D.FlipV = velocity.Y > 0;
         }
 
  .. code-tab:: cpp
@@ -390,7 +397,7 @@ movement. Let's place this code at the end of the ``_process()`` function:
 
            .. code-tab:: csharp
 
-             if (velocity.x < 0)
+             if (velocity.X < 0)
              {
                  animatedSprite2D.FlipH = true;
              }
@@ -490,12 +497,12 @@ this code to the function:
 
  .. code-tab:: csharp
 
-    public void OnBodyEntered(PhysicsBody2D body)
+    private void OnBodyEntered(PhysicsBody2D body)
     {
         Hide(); // Player disappears after being hit.
         EmitSignal(SignalName.Hit);
         // Must be deferred as we can't change physics properties on a physics callback.
-        GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred("disabled", true);
+        GetNode<CollisionShape2D>("CollisionShape2D").SetDeferred(CollisionShape2D.PropertyName.Disabled, true);
     }
 
  .. code-tab:: cpp
@@ -530,9 +537,9 @@ starting a new game.
 
  .. code-tab:: csharp
 
-    public void Start(Vector2 pos)
+    public void Start(Vector2 position)
     {
-        Position = pos;
+        Position = position;
         Show();
         GetNode<CollisionShape2D>("CollisionShape2D").Disabled = false;
     }

+ 7 - 14
getting_started/first_2d_game/04.creating_the_enemy.rst

@@ -13,7 +13,7 @@ of independent mobs in the game.
 Node setup
 ~~~~~~~~~~
 
-Click Scene -> New Scene and add the following nodes:
+Click Scene -> New Scene from the top menu and add the following nodes:
 
 - :ref:`RigidBody2D <class_RigidBody2D>` (named ``Mob``)
 
@@ -108,18 +108,16 @@ and randomly choose one of the three animation types:
  .. code-tab:: gdscript GDScript
 
     func _ready():
-        $AnimatedSprite2D.play()
-        var mob_types = $AnimatedSprite2D.get_sprite_frames().get_animation_names()
-        $AnimatedSprite2D.animation = mob_types[randi() % mob_types.size()]
+        var mob_types = $AnimatedSprite2D.sprite_frames.get_animation_names()
+        $AnimatedSprite2D.play(mob_types[randi() % mob_types.size()])
 
  .. code-tab:: csharp
 
     public override void _Ready()
     {
-        var animSprite2D = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
-        animSprite2D.Play();
-        string[] mobTypes = animSprite2D.SpriteFrames.GetAnimationNames();
-        animSprite2D.Animation = mobTypes[GD.Randi() % mobTypes.Length];
+        var animatedSprite2D = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
+        string[] mobTypes = animatedSprite2D.SpriteFrames.GetAnimationNames();
+        animatedSprite2D.Play(mobTypes[GD.Randi() % mobTypes.Length]);
     }
 
  .. code-tab:: cpp
@@ -132,7 +130,6 @@ and randomly choose one of the three animation types:
 
     void Mob::_ready() {
         godot::Ref<godot::RandomNumberGenerator> random = godot::RandomNumberGenerator::_new();
-        random->randomize();
         _animated_sprite = get_node<godot::AnimatedSprite2D>("AnimatedSprite2D");
         _animated_sprite->set_playing(true);
         godot::PoolStringArray mob_types = _animated_sprite->get_sprite_frames()->get_animation_names();
@@ -147,10 +144,6 @@ We then need to pick a random number between ``0`` and ``2`` to select one of
 these names from the list (array indices start at ``0``). ``randi() % n``
 selects a random integer between ``0`` and ``n-1``.
 
-.. note:: You must use ``randomize()`` if you want your sequence of "random"
-            numbers to be different every time you run the scene. We're going to
-            use ``randomize()`` in our ``Main`` scene, so we won't need it here.
-
 The last piece is to make the mobs delete themselves when they leave the screen.
 Connect the ``screen_exited()`` signal of the ``VisibleOnScreenNotifier2D`` node and
 add this code:
@@ -163,7 +156,7 @@ add this code:
 
  .. code-tab:: csharp
 
-    public void OnVisibleOnScreenNotifier2DScreenExited()
+    private void OnVisibleOnScreenNotifier2DScreenExited()
     {
         QueueFree();
     }

+ 11 - 14
getting_started/first_2d_game/05.the_main_game_scene.rst

@@ -93,13 +93,10 @@ to instance.
     {
         // Don't forget to rebuild the project so the editor knows about the new export variable.
 
-    #pragma warning disable 649
-        // We assign this in the editor, so we don't need the warning about not being assigned.
         [Export]
-        public PackedScene MobScene;
-    #pragma warning restore 649
+        public PackedScene MobScene { get; set; }
 
-        public int Score;
+        private int _score;
     }
 
  .. code-tab:: cpp
@@ -219,7 +216,7 @@ new game:
 
     public void NewGame()
     {
-        Score = 0;
+        _score = 0;
 
         var player = GetNode<Player>("Player");
         var startPosition = GetNode<Marker2D>("StartPosition");
@@ -249,21 +246,21 @@ the other two timers. ``ScoreTimer`` will increment the score by 1.
 .. tabs::
  .. code-tab:: gdscript GDScript
 
-    func _on_ScoreTimer_timeout():
+    func _on_score_timer_timeout():
         score += 1
 
-    func _on_StartTimer_timeout():
+    func _on_start_timer_timeout():
         $MobTimer.start()
         $ScoreTimer.start()
 
  .. code-tab:: csharp
 
-    public void OnScoreTimerTimeout()
+    private void OnScoreTimerTimeout()
     {
-        Score++;
+        _score++;
     }
 
-    public void OnStartTimerTimeout()
+    private void OnStartTimerTimeout()
     {
         GetNode<Timer>("MobTimer").Start();
         GetNode<Timer>("ScoreTimer").Start();
@@ -305,7 +302,7 @@ Note that a new instance must be added to the scene using ``add_child()``.
 .. tabs::
  .. code-tab:: gdscript GDScript
 
-    func _on_MobTimer_timeout():
+    func _on_mob_timer_timeout():
         # Create a new instance of the Mob scene.
         var mob = mob_scene.instantiate()
 
@@ -332,14 +329,14 @@ Note that a new instance must be added to the scene using ``add_child()``.
 
  .. code-tab:: csharp
 
-    public void OnMobTimerTimeout()
+    private void OnMobTimerTimeout()
     {
         // Note: Normally it is best to use explicit types rather than the `var`
         // keyword. However, var is acceptable to use here because the types are
         // obviously Mob and PathFollow2D, since they appear later on the line.
 
         // Create a new instance of the Mob scene.
-        var mob = MobScene.Instantiate<Mob>();
+        Mob mob = MobScene.Instantiate<Mob>();
 
         // Choose a random location on Path2D.
         var mobSpawnLocation = GetNode<PathFollow2D>("MobPath/MobSpawnLocation");

+ 13 - 12
getting_started/first_2d_game/06.heads_up_display.rst

@@ -233,13 +233,13 @@ We also need to process what happens when the player loses. The code below will
         ShowMessage("Game Over");
 
         var messageTimer = GetNode<Timer>("MessageTimer");
-        await ToSignal(messageTimer, "timeout");
+        await ToSignal(messageTimer, Timer.SignalName.Timeout);
 
         var message = GetNode<Label>("Message");
         message.Text = "Dodge the\nCreeps!";
         message.Show();
 
-        await ToSignal(GetTree().CreateTimer(1), "timeout");
+        await ToSignal(GetTree().CreateTimer(1.0), SceneTreeTimer.SignalName.Timeout);
         GetNode<Button>("StartButton").Show();
     }
 
@@ -297,22 +297,22 @@ signal of ``StartButton``, and add the following code to the new functions:
 .. tabs::
  .. code-tab:: gdscript GDScript
 
-    func _on_StartButton_pressed():
+    func _on_start_button_pressed():
         $StartButton.hide()
         start_game.emit()
 
-    func _on_MessageTimer_timeout():
+    func _on_message_timer_timeout():
         $Message.hide()
 
  .. code-tab:: csharp
 
-    public void OnStartButtonPressed()
+    private void OnStartButtonPressed()
     {
         GetNode<Button>("StartButton").Hide();
         EmitSignal(SignalName.StartGame);
     }
 
-    public void OnMessageTimerTimeout()
+    private void OnMessageTimerTimeout()
     {
         GetNode<Label>("Message").Hide();
     }
@@ -349,9 +349,10 @@ Now we need to connect the ``HUD`` functionality to our ``Main`` script. This
 requires a few additions to the ``Main`` scene:
 
 In the Node tab, connect the HUD's ``start_game`` signal to the ``new_game()``
-function of the Main node by typing "new_game" in the "Receiver Method" in the
-"Connect a Signal" window. Verify that the green connection icon now appears
-next to ``func new_game()`` in the script.
+function of the Main node by clicking the "Pick" button in the "Connect a Signal"
+window and selecting the ``new_game()`` method or type "new_game" below "Receiver Method"
+in the window. Verify that the green connection icon now appears next to
+``func new_game()`` in the script.
 
 In ``new_game()``, update the score display and show the "Get Ready" message:
 
@@ -364,7 +365,7 @@ In ``new_game()``, update the score display and show the "Get Ready" message:
  .. code-tab:: csharp
 
         var hud = GetNode<HUD>("HUD");
-        hud.UpdateScore(Score);
+        hud.UpdateScore(_score);
         hud.ShowMessage("Get Ready!");
 
  .. code-tab:: cpp
@@ -400,7 +401,7 @@ with the changing score:
 
  .. code-tab:: csharp
 
-        GetNode<HUD>("HUD").UpdateScore(Score);
+        GetNode<HUD>("HUD").UpdateScore(_score);
 
  .. code-tab:: cpp
 
@@ -435,7 +436,7 @@ the ``new_game()`` function in ``Main``:
 
         // Note that for calling Godot-provided methods with strings,
         // we have to use the original Godot snake_case name.
-        GetTree().CallGroup("mobs", "queue_free");
+        GetTree().CallGroup("mobs", Node.MethodName.QueueFree);
 
  .. code-tab:: cpp
 

+ 1 - 1
getting_started/first_2d_game/07.finishing-up.rst

@@ -15,7 +15,7 @@ The default gray background is not very appealing, so let's change its color.
 One way to do this is to use a :ref:`ColorRect <class_ColorRect>` node. Make it
 the first node under ``Main`` so that it will be drawn behind the other nodes.
 ``ColorRect`` only has one property: ``Color``. Choose a color you like and
-select "Layout" -> "Full Rect" so that it covers the screen.
+select "Layout" -> "Anchors Preset" -> "Full Rect" either in the toolbar at the top of the viewport or in the inspector so that it covers the screen.
 
 You could also add a background image, if you have one, by using a
 ``TextureRect`` node instead.

二进制
getting_started/first_2d_game/img/build_dotnet.webp


+ 2 - 2
getting_started/first_3d_game/01.game_setup.rst

@@ -12,7 +12,7 @@ the archive here: `Squash the Creeps assets
 <https://github.com/godotengine/godot-3d-dodge-the-creeps/releases/tag/1.1.0>`__.
 
 Once you downloaded it, extract the .zip archive on your computer. Open the
-Godot project manager and click the *Import* button.
+Godot Project Manager and click the *Import* button.
 
 .. image:: img/01.game_setup/01.import_button.png
 
@@ -40,7 +40,7 @@ Setting up the playable area
 
 We're going to create our main scene with a plain :ref:`Node <class_Node>` as its root. In the
 *Scene* dock, click the *Add Child Node* button represented by a "+" icon in the
-top-left and double-click on *Node*. Name the node ``Main``. Alternatively, to add
+top-left and double-click on *Node*. Name the node ``Main``. An alternate method to rename the node is to right-click on *Node* and choose *Rename* (or :kbd:`F2`). Alternatively, to add
 a node to the scene, you can press :kbd:`Ctrl + a` (or :kbd:`Cmd + a` on macOS).
 
 .. image:: img/01.game_setup/05.main_node.png

+ 51 - 37
getting_started/first_3d_game/03.player_movement_code.rst

@@ -38,12 +38,12 @@ character.
 
         // How fast the player moves in meters per second.
         [Export]
-        public int Speed = 14;
+        public int Speed { get; set; } = 14;
         // The downward acceleration when in the air, in meters per second squared.
         [Export]
-        public int FallAcceleration = 75;
+        public int FallAcceleration { get; set; } = 75;
 
-        private Vector3 _velocity = Vector3.Zero;
+        private Vector3 _targetVelocity = Vector3.Zero;
     }
 
 
@@ -81,29 +81,29 @@ using the global ``Input`` object, in ``_physics_process()``.
 
  .. code-tab:: csharp
 
-    public override void _PhysicsProcess(float delta)
+    public override void _PhysicsProcess(double delta)
     {
         // We create a local variable to store the input direction.
         var direction = Vector3.Zero;
 
-        // We check for each move input and update the direction accordingly
+        // We check for each move input and update the direction accordingly.
         if (Input.IsActionPressed("move_right"))
         {
-            direction.x += 1f;
+            direction.X += 1.0f;
         }
         if (Input.IsActionPressed("move_left"))
         {
-            direction.x -= 1f;
+            direction.X -= 1.0f;
         }
         if (Input.IsActionPressed("move_back"))
         {
-            // Notice how we are working with the vector's x and z axes.
+            // Notice how we are working with the vector's X and Z axes.
             // In 3D, the XZ plane is the ground plane.
-            direction.z += 1f;
+            direction.Z += 1.0f;
         }
         if (Input.IsActionPressed("move_forward"))
         {
-            direction.z -= 1f;
+            direction.Z -= 1.0f;
         }
     }
 
@@ -141,14 +141,14 @@ call its ``normalize()`` method.
 
  .. code-tab:: csharp
 
-    public override void _PhysicsProcess(float delta)
+    public override void _PhysicsProcess(double delta)
     {
         // ...
 
         if (direction != Vector3.Zero)
         {
             direction = direction.Normalized();
-            GetNode<Node3D>("Pivot").LookAt(position + direction, Vector3.Up);
+            GetNode<Node3D>("Pivot").LookAt(Position + direction, Vector3.Up);
         }
     }
 
@@ -192,27 +192,38 @@ fall speed separately. Be sure to go back one tab so the lines are inside the
         # Moving the Character
         velocity = target_velocity
         move_and_slide()
+
  .. code-tab:: csharp
 
-    public override void _PhysicsProcess(float delta)
+    public override void _PhysicsProcess(double delta)
     {
         // ...
+        if (direction != Vector3.Zero)
+        {
+            // ...
+        }
 
         // Ground velocity
-        _velocity.x = direction.x * Speed;
-        _velocity.z = direction.z * Speed;
+        _targetVelocity.X = direction.X * Speed;
+        _targetVelocity.Z = direction.Z * Speed;
+
         // Vertical velocity
-        _velocity.y -= FallAcceleration * delta;
+        if (!IsOnFloor()) // If in the air, fall towards the floor. Literally gravity
+        {
+            _targetVelocity.Y -= FallAcceleration * (float)delta;
+        }
+
         // Moving the character
-        _velocity = MoveAndSlide(_velocity, Vector3.Up);
+        Velocity = _targetVelocity;
+        MoveAndSlide();
     }
 
 The ``CharacterBody3D.is_on_floor()`` function returns ``true`` if the body collided with the floor in this frame. That's why
-we apply gravity to the ``Player`` only while he is in the air.
+we apply gravity to the ``Player`` only while it is in the air.
 
 For the vertical velocity, we subtract the fall acceleration multiplied by the
 delta time every frame.
-This line of code will cause our character to fall in every frame, as long he is not on the floor, or collides with it.
+This line of code will cause our character to fall in every frame, as long it is not on or collides with the floor.
 
 The physics engine can only detect interactions with walls, the floor, or other
 bodies during a given frame if movement and collisions happen. We will use this
@@ -269,11 +280,12 @@ Here is the complete ``Player.gd`` code for reference.
 
         # Vertical Velocity
         if not is_on_floor(): # If in the air, fall towards the floor. Literally gravity
-	        target_velocity.y = target_velocity.y - (fall_acceleration * delta)
+            target_velocity.y = target_velocity.y - (fall_acceleration * delta)
 
         # Moving the Character
         velocity = target_velocity
         move_and_slide()
+
  .. code-tab:: csharp
 
     using Godot;
@@ -282,51 +294,53 @@ Here is the complete ``Player.gd`` code for reference.
     {
         // How fast the player moves in meters per second.
         [Export]
-        public int Speed = 14;
+        public int Speed { get; set; } = 14;
         // The downward acceleration when in the air, in meters per second squared.
         [Export]
-        public int FallAcceleration = 75;
+        public int FallAcceleration { get; set; } = 75;
 
-        private Vector3 _velocity = Vector3.Zero;
+        private Vector3 _targetVelocity = Vector3.Zero;
 
-        public override void _PhysicsProcess(float delta)
+        public override void _PhysicsProcess(double delta)
         {
-            // We create a local variable to store the input direction.
             var direction = Vector3.Zero;
 
-            // We check for each move input and update the direction accordingly
             if (Input.IsActionPressed("move_right"))
             {
-                direction.x += 1f;
+                direction.X += 1.0f;
             }
             if (Input.IsActionPressed("move_left"))
             {
-                direction.x -= 1f;
+                direction.X -= 1.0f;
             }
             if (Input.IsActionPressed("move_back"))
             {
-                // Notice how we are working with the vector's x and z axes.
-                // In 3D, the XZ plane is the ground plane.
-                direction.z += 1f;
+                direction.Z += 1.0f;
             }
             if (Input.IsActionPressed("move_forward"))
             {
-                direction.z -= 1f;
+                direction.Z -= 1.0f;
             }
 
             if (direction != Vector3.Zero)
             {
                 direction = direction.Normalized();
-                GetNode<Node3D>("Pivot").LookAt(Translation + direction, Vector3.Up);
+                GetNode<Node3D>("Pivot").LookAt(Position + direction, Vector3.Up);
             }
 
             // Ground velocity
-            _velocity.x = direction.x * Speed;
-            _velocity.z = direction.z * Speed;
+            _targetVelocity.X = direction.X * Speed;
+            _targetVelocity.Z = direction.Z * Speed;
+
             // Vertical velocity
-            _velocity.y -= FallAcceleration * delta;
+            if (!IsOnFloor()) // If in the air, fall towards the floor. Literally gravity
+            {
+                _targetVelocity.Y -= FallAcceleration * (float)delta;
+            }
+
             // Moving the character
-            _velocity = MoveAndSlide(_velocity, Vector3.Up);
+            Velocity = _targetVelocity;
+            MoveAndSlide();
         }
     }
 

+ 40 - 29
getting_started/first_3d_game/04.mob_scene.rst

@@ -125,12 +125,12 @@ and ``max_speed``, to define a random speed range, which we will later use to de
 
         // Minimum speed of the mob in meters per second
         [Export]
-        public int MinSpeed = 10;
+        public int MinSpeed { get; set; } = 10;
         // Maximum speed of the mob in meters per second
         [Export]
-        public int MaxSpeed = 18;
+        public int MaxSpeed { get; set; } = 18;
 
-        public override void _PhysicsProcess(float delta)
+        public override void _PhysicsProcess(double delta)
         {
             MoveAndSlide();
         }
@@ -161,17 +161,20 @@ between ``-PI / 4`` radians and ``PI / 4`` radians.
         # We position the mob by placing it at start_position
         # and rotate it towards player_position, so it looks at the player.
         look_at_from_position(start_position, player_position, Vector3.UP)
-        # In this rotation^, the mob will move directly towards the player
-        # so we rotate it randomly within range of -90 and +90 degrees.
+        # Rotate this mob randomly within range of -90 and +90 degrees,
+        # so that it doesn't move directly towards the player.
         rotate_y(randf_range(-PI / 4, PI / 4))
+
  .. code-tab:: csharp
 
-    // We will call this function from the Main scene
+    // This function will be called from the Main scene.
     public void Initialize(Vector3 startPosition, Vector3 playerPosition)
     {
-        // We position the mob and turn it so that it looks at the player.
+        // We position the mob by placing it at startPosition
+        // and rotate it towards playerPosition, so it looks at the player.
         LookAtFromPosition(startPosition, playerPosition, Vector3.Up);
-        // And rotate it randomly so it doesn't move exactly toward the player.
+        // Rotate this mob randomly within range of -90 and +90 degrees,
+        // so that it doesn't move directly towards the player.
         RotateY((float)GD.RandRange(-Mathf.Pi / 4.0, Mathf.Pi / 4.0));
     }
 
@@ -198,12 +201,13 @@ We got a random position, now we need a ``random_speed``. ``randi_range()`` will
     {
         // ...
 
-        // We calculate a random speed.
-        float randomSpeed = (float)GD.RandRange(MinSpeed, MaxSpeed);
+        // We calculate a random speed (integer).
+        int randomSpeed = GD.RandRange(MinSpeed, MaxSpeed);
         // We calculate a forward velocity that represents the speed.
-        _velocity = Vector3.Forward * randomSpeed;
-        // We then rotate the vector based on the mob's Y rotation to move in the direction it's looking
-        _velocity = _velocity.Rotated(Vector3.Up, Rotation.y);
+        Velocity = Vector3.Forward * randomSpeed;
+        // We then rotate the velocity vector based on the mob's Y rotation
+        // in order to move in the direction the mob is looking.
+        Velocity = Velocity.Rotated(Vector3.Up, Rotation.Y);
     }
 
 Leaving the screen
@@ -239,7 +243,7 @@ method. This function destroy the instance it's called on.
  .. code-tab:: csharp
 
     // We also specified this function name in PascalCase in the editor's connection window
-    public void OnVisibilityNotifierScreenExited()
+    private void OnVisibilityNotifierScreenExited()
     {
         QueueFree();
     }
@@ -268,8 +272,8 @@ Here is the complete ``Mob.gd`` script for reference.
         # We position the mob by placing it at start_position
         # and rotate it towards player_position, so it looks at the player.
         look_at_from_position(start_position, player_position, Vector3.UP)
-        # In this rotation^, the mob will move directly towards the player
-        # so we rotate it randomly within range of -90 and +90 degrees.
+        # Rotate this mob randomly within range of -90 and +90 degrees,
+        # so that it doesn't move directly towards the player.
         rotate_y(randf_range(-PI / 4, PI / 4))
 
         # We calculate a random speed (integer)
@@ -282,39 +286,46 @@ Here is the complete ``Mob.gd`` script for reference.
 
     func _on_visible_on_screen_notifier_3d_screen_exited():
         queue_free()
+
  .. code-tab:: csharp
 
     using Godot;
 
     public partial class Mob : CharacterBody3D
     {
-        // Minimum speed of the mob in meters per second
+        // Minimum speed of the mob in meters per second.
         [Export]
-        public int MinSpeed = 10;
-        // Maximum speed of the mob in meters per second
+        public int MinSpeed { get; set; } = 10;
+        // Maximum speed of the mob in meters per second.
         [Export]
-        public int MaxSpeed = 18;
-
-        private Vector3 _velocity = Vector3.Zero;
+        public int MaxSpeed { get; set; } = 18;
 
-        public override void _PhysicsProcess(float delta)
+        public override void _PhysicsProcess(double delta)
         {
-            MoveAndSlide(_velocity);
+            MoveAndSlide();
         }
 
-        // We will call this function from the Main scene
+        // This function will be called from the Main scene.
         public void Initialize(Vector3 startPosition, Vector3 playerPosition)
         {
+            // We position the mob by placing it at startPosition
+            // and rotate it towards playerPosition, so it looks at the player.
             LookAtFromPosition(startPosition, playerPosition, Vector3.Up);
+            // Rotate this mob randomly within range of -90 and +90 degrees,
+            // so that it doesn't move directly towards the player.
             RotateY((float)GD.RandRange(-Mathf.Pi / 4.0, Mathf.Pi / 4.0));
 
-            var randomSpeed = (float)GD.RandRange(MinSpeed, MaxSpeed);
-            _velocity = Vector3.Forward * randomSpeed;
-            _velocity = _velocity.Rotated(Vector3.Up, Rotation.y);
+            // We calculate a random speed (integer).
+            int randomSpeed = GD.RandRange(MinSpeed, MaxSpeed);
+            // We calculate a forward velocity that represents the speed.
+            Velocity = Vector3.Forward * randomSpeed;
+            // We then rotate the velocity vector based on the mob's Y rotation
+            // in order to move in the direction the mob is looking.
+            Velocity = Velocity.Rotated(Vector3.Up, Rotation.Y);
         }
 
         // We also specified this function name in PascalCase in the editor's connection window
-        public void OnVisibilityNotifierScreenExited()
+        private void OnVisibilityNotifierScreenExited()
         {
             QueueFree();
         }

+ 21 - 42
getting_started/first_3d_game/05.spawning_mobs.rst

@@ -143,7 +143,7 @@ Your path should look like this.
 |image18|
 
 To sample random positions on it, we need a :ref:`PathFollow3D <class_PathFollow3D>` node. Add a
-:ref:`PathFollow3D <class_PathFollow3D>` as a child of the ``Path3d``. Rename the two nodes to ``SpawnPath`` and
+:ref:`PathFollow3D <class_PathFollow3D>` as a child of the ``Path3D``. Rename the two nodes to ``SpawnPath`` and
 ``SpawnLocation``, respectively. It's more descriptive of what we'll use them for.
 
 |image19|
@@ -158,10 +158,6 @@ Right-click on the ``Main`` node and attach a new script to it.
 We first export a variable to the *Inspector* so that we can assign ``Mob.tscn``
 or any other monster to it.
 
-Then, as we're going to spawn the monsters procedurally, we want to randomize
-numbers every time we play the game. If we don't do that, the monsters will
-always spawn following the same sequence.
-
 .. tabs::
  .. code-tab:: gdscript GDScript
 
@@ -169,10 +165,6 @@ always spawn following the same sequence.
 
    @export var mob_scene: PackedScene
 
-
-   func _ready():
-       randomize()
-
  .. code-tab:: csharp
 
     using Godot;
@@ -181,16 +173,8 @@ always spawn following the same sequence.
     {
         // Don't forget to rebuild the project so the editor knows about the new export variable.
 
-    #pragma warning disable 649
-        // We assign this in the editor, so we don't need the warning about not being assigned.
         [Export]
-        public PackedScene MobScene;
-    #pragma warning restore 649
-
-        public override void _Ready()
-        {
-            GD.Randomize();
-        }
+        public PackedScene MobScene { get; set; }
     }
 
 We want to spawn mobs at regular time intervals. To do this, we need to go back
@@ -259,22 +243,22 @@ Let's code the mob spawning logic. We're going to:
  .. code-tab:: csharp
 
     // We also specified this function name in PascalCase in the editor's connection window
-    public void OnMobTimerTimeout()
+    private void OnMobTimerTimeout()
     {
         // Create a new instance of the Mob scene.
-        Mob mob = (Mob)MobScene.Instantiate();
+        Mob mob = MobScene.Instantiate<Mob>();
 
         // Choose a random location on the SpawnPath.
         // We store the reference to the SpawnLocation node.
-        var mobSpawnLocation = GetNode<PathFollow>("SpawnPath/SpawnLocation");
+        var mobSpawnLocation = GetNode<PathFollow3D>("SpawnPath/SpawnLocation");
         // And give it a random offset.
-        mobSpawnLocation.UnitOffset = GD.Randf();
+        mobSpawnLocation.ProgressRatio = GD.Randf();
 
-        Vector3 playerPosition = GetNode<Player>("Player").position;
-        mob.Initialize(mobSpawnLocation.Translation, playerPosition);
+        Vector3 playerPosition = GetNode<Player>("Player").Position;
+        mob.Initialize(mobSpawnLocation.Position, playerPosition);
 
+        // Spawn the mob by adding it to the Main scene.
         AddChild(mob);
-
     }
 
 Above, ``randf()`` produces a random value between ``0`` and ``1``, which is
@@ -292,9 +276,6 @@ Here is the complete ``Main.gd`` script so far, for reference.
 
     @export var mob_scene: PackedScene
 
-    func _ready():
-        randomize()
-
 
     func _on_mob_timer_timeout():
         # Create a new instance of the Mob scene.
@@ -318,26 +299,24 @@ Here is the complete ``Main.gd`` script so far, for reference.
 
     public partial class Main : Node
     {
-    #pragma warning disable 649
         [Export]
-        public PackedScene MobScene;
-    #pragma warning restore 649
-
-        public override void _Ready()
-        {
-            GD.Randomize();
-        }
+        public PackedScene MobScene { get; set; }
 
-        public void OnMobTimerTimeout()
+        private void OnMobTimerTimeout()
         {
-            Mob mob = (Mob)MobScene.Instantiate();
+            // Create a new instance of the Mob scene.
+            Mob mob = MobScene.Instantiate<Mob>();
 
-            var mobSpawnLocation = GetNode<PathFollow>("SpawnPath/SpawnLocation");
-            mobSpawnLocation.UnitOffset = GD.Randf();
+            // Choose a random location on the SpawnPath.
+            // We store the reference to the SpawnLocation node.
+            var mobSpawnLocation = GetNode<PathFollow3D>("SpawnPath/SpawnLocation");
+            // And give it a random offset.
+            mobSpawnLocation.ProgressRatio = GD.Randf();
 
-            Vector3 playerPosition = GetNode<Player>("Player").position;
-            mob.Initialize(mobSpawnLocation.Translation, playerPosition);
+            Vector3 playerPosition = GetNode<Player>("Player").Position;
+            mob.Initialize(mobSpawnLocation.Position, playerPosition);
 
+            // Spawn the mob by adding it to the Main scene.
             AddChild(mob);
         }
     }

+ 18 - 15
getting_started/first_3d_game/06.jump_and_squash.rst

@@ -26,7 +26,7 @@ The important point is that you can use layers and masks to filter physics
 interactions, control performance, and remove the need for extra conditions in
 your code.
 
-By default, all physics bodies and areas are set to both layer and mask ``0``.
+By default, all physics bodies and areas are set to both layer and mask ``1``.
 This means they all collide with each other.
 
 Physics layers are represented by numbers, but we can give them names to keep
@@ -122,7 +122,7 @@ the ``jump_impulse``.
     // ...
     // Vertical impulse applied to the character upon jumping in meters per second.
     [Export]
-    public int JumpImpulse = 20;
+    public int JumpImpulse { get; set; } = 20;
 
 Inside ``_physics_process()``, add the following code before the ``move_and_slide()`` codeblock.
 
@@ -140,14 +140,14 @@ Inside ``_physics_process()``, add the following code before the ``move_and_slid
 
  .. code-tab:: csharp
 
-    public override void _PhysicsProcess(float delta)
+    public override void _PhysicsProcess(double delta)
     {
         // ...
 
         // Jumping.
         if (IsOnFloor() && Input.IsActionJustPressed("jump"))
         {
-            _velocity.y = JumpImpulse;
+            _targetVelocity.Y = JumpImpulse;
         }
 
         // ...
@@ -218,7 +218,7 @@ when jumping.
 
     // Vertical impulse applied to the character upon bouncing over a mob in meters per second.
     [Export]
-    public int BounceImpulse = 16;
+    public int BounceImpulse { get; set; } = 16;
 
 Then, after the **Jumping** codeblock we added above in ``_physics_process()``, add the following loop. With
 ``move_and_slide()``, Godot makes the body move sometimes multiple times in a
@@ -235,6 +235,7 @@ With this code, if no collisions occurred on a given frame, the loop won't run.
 
    func _physics_process(delta):
         #...
+
         # Iterate through all collisions that occurred this frame
         # in C this would be for(int i = 0; i < collisions.Count; i++)
         for index in range(get_slide_collision_count()):
@@ -256,23 +257,25 @@ With this code, if no collisions occurred on a given frame, the loop won't run.
 
  .. code-tab:: csharp
 
-    public override void _PhysicsProcess(float delta)
+    public override void _PhysicsProcess(double delta)
     {
         // ...
 
-        for (int index = 0; index < GetSlideCount(); index++)
+        // Iterate through all collisions that occurred this frame.
+        for (int index = 0; index < GetSlideCollisionCount(); index++)
         {
-            // We check every collision that occurred this frame.
+            // We get one of the collisions with the player.
             KinematicCollision3D collision = GetSlideCollision(index);
-            // If we collide with a monster...
-            if (collision.Collider is Mob mob && mob.IsInGroup("mob"))
+
+            // If the collision is with a mob.
+            if (collision.GetCollider() is Mob mob)
             {
-                // ...we check that we are hitting it from above.
-                if (Vector3.Up.Dot(collision.Normal) > 0.1f)
+                // We check that we are hitting it from above.
+                if (Vector3.Up.Dot(collision.GetNormal()) > 0.1f)
                 {
                     // If so, we squash it and bounce.
                     mob.Squash();
-                    _velocity.y = BounceImpulse;
+                    _targetVelocity.Y = BounceImpulse;
                 }
             }
         }
@@ -328,7 +331,7 @@ destroy the mob.
 
     // Don't forget to rebuild the project so the editor knows about the new signal.
 
-    // Emitted when the played jumped on the mob.
+    // Emitted when the player jumped on the mob.
     [Signal]
     public delegate void SquashedEventHandler();
 
@@ -336,7 +339,7 @@ destroy the mob.
 
     public void Squash()
     {
-        EmitSignal(nameof(Squashed));
+        EmitSignal(SignalName.Squashed);
         QueueFree();
     }
 

+ 80 - 57
getting_started/first_3d_game/07.killing_player.rst

@@ -90,12 +90,12 @@ a ``die()`` function that helps us put a descriptive label on the code.
 
     private void Die()
     {
-        EmitSignal(nameof(Hit));
+        EmitSignal(SignalName.Hit);
         QueueFree();
     }
 
     // We also specified this function name in PascalCase in the editor's connection window
-    public void OnMobDetectorBodyEntered(Node body)
+    private void OnMobDetectorBodyEntered(Node3D body)
     {
         Die();
     }
@@ -108,6 +108,11 @@ the character should die when an enemy runs into the collider. Note that without
 
     var player_position = $Player.position
 
+   .. code-tab:: csharp
+
+    Vector3 playerPosition = GetNode<Player>("Player").Position;
+
+
 gives error because there is no $Player!
 
 Also note that the enemy colliding with the player and dying depends on the size and position of the
@@ -137,7 +142,7 @@ Get the timer, and stop it, in the ``_on_player_hit()`` function.
  .. code-tab:: csharp
 
     // We also specified this function name in PascalCase in the editor's connection window
-    public void OnPlayerHit()
+    private void OnPlayerHit()
     {
         GetNode<Timer>("MobTimer").Stop();
     }
@@ -167,9 +172,6 @@ Starting with ``Main.gd``.
 
     @export var mob_scene: PackedScene
 
-    func _ready():
-        randomize()
-
 
     func _on_mob_timer_timeout():
         # Create a new instance of the Mob scene.
@@ -189,42 +191,35 @@ Starting with ``Main.gd``.
 
     func _on_player_hit():
         $MobTimer.stop()
+
  .. code-tab:: csharp
 
     using Godot;
 
     public partial class Main : Node
     {
-    #pragma warning disable 649
         [Export]
-        public PackedScene MobScene;
-    #pragma warning restore 649
+        public PackedScene MobScene { get; set; }
 
-        public override void _Ready()
-        {
-            GD.Randomize();
-        }
-
-        public void OnMobTimerTimeout()
+        private void OnMobTimerTimeout()
         {
             // Create a new instance of the Mob scene.
-            var mob = (Mob)MobScene.Instantiate();
+            Mob mob = MobScene.Instantiate<Mob>();
 
             // Choose a random location on the SpawnPath.
             // We store the reference to the SpawnLocation node.
             var mobSpawnLocation = GetNode<PathFollow>("SpawnPath/SpawnLocation");
             // And give it a random offset.
-            mobSpawnLocation.UnitOffset = GD.Randf();
+            mobSpawnLocation.ProgressRatio = GD.Randf();
 
-            // Communicate the spawn location and the player's location to the mob.
-            Vector3 playerPosition = GetNode<Player>("Player").position;
-            mob.Initialize(mobSpawnLocation.Translation, playerPosition);
+            Vector3 playerPosition = GetNode<Player>("Player").Position;
+            mob.Initialize(mobSpawnLocation.Position, playerPosition);
 
             // Spawn the mob by adding it to the Main scene.
             AddChild(mob);
         }
 
-        public void OnPlayerHit()
+        private void OnPlayerHit()
         {
             GetNode<Timer>("MobTimer").Stop();
         }
@@ -253,8 +248,8 @@ Next is ``Mob.gd``.
         # We position the mob by placing it at start_position
         # and rotate it towards player_position, so it looks at the player.
         look_at_from_position(start_position, player_position, Vector3.UP)
-        # In this rotation^, the mob will move directly towards the player
-        # so we rotate it randomly within range of -90 and +90 degrees.
+        # Rotate this mob randomly within range of -90 and +90 degrees,
+        # so that it doesn't move directly towards the player.
         rotate_y(randf_range(-PI / 4, PI / 4))
 
         # We calculate a random speed (integer)
@@ -271,6 +266,7 @@ Next is ``Mob.gd``.
     func squash():
         squashed.emit()
         queue_free() # Destroy this node
+
  .. code-tab:: csharp
 
     using Godot;
@@ -283,35 +279,42 @@ Next is ``Mob.gd``.
 
         // Minimum speed of the mob in meters per second
         [Export]
-        public int MinSpeed = 10;
+        public int MinSpeed { get; set; } = 10;
         // Maximum speed of the mob in meters per second
         [Export]
-        public int MaxSpeed = 18;
+        public int MaxSpeed { get; set; } = 18;
 
-        private Vector3 _velocity = Vector3.Zero;
-
-        public override void _PhysicsProcess(float delta)
+        public override void _PhysicsProcess(double delta)
         {
-            MoveAndSlide(_velocity);
+            MoveAndSlide();
         }
 
+        // This function will be called from the Main scene.
         public void Initialize(Vector3 startPosition, Vector3 playerPosition)
         {
+            // We position the mob by placing it at startPosition
+            // and rotate it towards playerPosition, so it looks at the player.
             LookAtFromPosition(startPosition, playerPosition, Vector3.Up);
+            // Rotate this mob randomly within range of -90 and +90 degrees,
+            // so that it doesn't move directly towards the player.
             RotateY((float)GD.RandRange(-Mathf.Pi / 4.0, Mathf.Pi / 4.0));
 
-            float randomSpeed = (float)GD.RandRange(MinSpeed, MaxSpeed);
-            _velocity = Vector3.Forward * randomSpeed;
-            _velocity = _velocity.Rotated(Vector3.Up, Rotation.y);
+            // We calculate a random speed (integer)
+            int randomSpeed = GD.RandRange(MinSpeed, MaxSpeed);
+            // We calculate a forward velocity that represents the speed.
+            Velocity = Vector3.Forward * randomSpeed;
+            // We then rotate the velocity vector based on the mob's Y rotation
+            // in order to move in the direction the mob is looking.
+            Velocity = Velocity.Rotated(Vector3.Up, Rotation.Y);
         }
 
         public void Squash()
         {
-            EmitSignal(nameof(Squashed));
-            QueueFree();
+            EmitSignal(SignalName.Squashed);
+            QueueFree(); // Destroy this node
         }
 
-        public void OnVisibilityNotifierScreenExited()
+        private void OnVisibilityNotifierScreenExited()
         {
             QueueFree();
         }
@@ -402,6 +405,7 @@ Finally, the longest script, ``Player.gd``:
 
     func _on_mob_detector_body_entered(body):
         die()
+
  .. code-tab:: csharp
 
     using Godot;
@@ -414,79 +418,98 @@ Finally, the longest script, ``Player.gd``:
 
         // How fast the player moves in meters per second.
         [Export]
-        public int Speed = 14;
+        public int Speed { get; set; } = 14;
         // The downward acceleration when in the air, in meters per second squared.
         [Export]
-        public int FallAcceleration = 75;
+        public int FallAcceleration { get; set; } = 75;
         // Vertical impulse applied to the character upon jumping in meters per second.
         [Export]
-        public int JumpImpulse = 20;
+        public int JumpImpulse { get; set; } = 20;
         // Vertical impulse applied to the character upon bouncing over a mob in meters per second.
         [Export]
-        public int BounceImpulse = 16;
+        public int BounceImpulse { get; set; } = 16;
 
-        private Vector3 _velocity = Vector3.Zero;
+        private Vector3 _targetVelocity = Vector3.Zero;
 
-        public override void _PhysicsProcess(float delta)
+        public override void _PhysicsProcess(double delta)
         {
+            // We create a local variable to store the input direction.
             var direction = Vector3.Zero;
 
+            // We check for each move input and update the direction accordingly.
             if (Input.IsActionPressed("move_right"))
             {
-                direction.x += 1f;
+                direction.X += 1.0f;
             }
             if (Input.IsActionPressed("move_left"))
             {
-                direction.x -= 1f;
+                direction.X -= 1.0f;
             }
             if (Input.IsActionPressed("move_back"))
             {
-                direction.z += 1f;
+                // Notice how we are working with the vector's X and Z axes.
+                // In 3D, the XZ plane is the ground plane.
+                direction.Z += 1.0f;
             }
             if (Input.IsActionPressed("move_forward"))
             {
-                direction.z -= 1f;
+                direction.Z -= 1.0f;
             }
 
+            // Prevent diagonal moving fast af
             if (direction != Vector3.Zero)
             {
                 direction = direction.Normalized();
-                GetNode<Node3D>("Pivot").LookAt(Translation + direction, Vector3.Up);
+                GetNode<Node3D>("Pivot").LookAt(Position + direction, Vector3.Up);
             }
 
-            _velocity.x = direction.x * Speed;
-            _velocity.z = direction.z * Speed;
+            // Ground Velocity
+            _targetVelocity.X = direction.X * Speed;
+            _targetVelocity.Z = direction.Z * Speed;
+
+            // Vertical Velocity
+            if (!IsOnFloor()) // If in the air, fall towards the floor. Literally gravity
+            {
+                _targetVelocity.Y -= FallAcceleration * (float)delta;
+            }
 
             // Jumping.
             if (IsOnFloor() && Input.IsActionJustPressed("jump"))
             {
-                _velocity.y += JumpImpulse;
+                _targetVelocity.Y = JumpImpulse;
             }
 
-            _velocity.y -= FallAcceleration * delta;
-            _velocity = MoveAndSlide(_velocity, Vector3.Up);
-
+            // Iterate through all collisions that occurred this frame.
             for (int index = 0; index < GetSlideCount(); index++)
             {
+                // We get one of the collisions with the player.
                 KinematicCollision3D collision = GetSlideCollision(index);
-                if (collision.Collider is Mob mob && mob.IsInGroup("mob"))
+
+                // If the collision is with a mob.
+                if (collision.GetCollider() is Mob mob)
                 {
-                    if (Vector3.Up.Dot(collision.Normal) > 0.1f)
+                    // We check that we are hitting it from above.
+                    if (Vector3.Up.Dot(collision.GetNormal()) > 0.1f)
                     {
+                        // If so, we squash it and bounce.
                         mob.Squash();
-                        _velocity.y = BounceImpulse;
+                        _targetVelocity.Y = BounceImpulse;
                     }
                 }
             }
+
+            // Moving the Character
+            Velocity = _targetVelocity;
+            MoveAndSlide();
         }
 
         private void Die()
         {
-            EmitSignal(nameof(Hit));
+            EmitSignal(SignalName.Hit);
             QueueFree();
         }
 
-        public void OnMobDetectorBodyEntered(Node body)
+        private void OnMobDetectorBodyEntered(Node3D body)
         {
             Die();
         }

+ 23 - 19
getting_started/first_3d_game/08.score_and_replay.rst

@@ -121,7 +121,7 @@ line:
 
   .. code-tab:: csharp
 
-    public void OnMobTimerTimeout()
+    private void OnMobTimerTimeout()
     {
         // ...
         // We connect the mob to the score label to update the score upon squashing one.
@@ -148,7 +148,7 @@ There, we increment the score and update the displayed text.
     public void OnMobSquashed()
     {
         _score += 1;
-        Text = string.Format("Score: {0}", _score);
+        Text = $"Score: {_score}";
     }
 
 The second line uses the value of the ``score`` variable to replace the
@@ -159,6 +159,7 @@ function.
 .. seealso::
 
     You can learn more about string formatting here: :ref:`doc_gdscript_printf`.
+    In C#, consider using `string interpolation with "$" <https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated>`_.
 
 
 .. note::
@@ -237,15 +238,13 @@ the game. Add this line to the ``_ready()`` function.
 .. tabs::
   .. code-tab:: gdscript GDScript
 
-    func _ready():
-        #...
-        $UserInterface/Retry.hide()
+   func _ready():
+       $UserInterface/Retry.hide()
 
   .. code-tab:: csharp
 
     public override void _Ready()
     {
-        // ...
         GetNode<Control>("UserInterface/Retry").Hide();
     }
 
@@ -260,7 +259,7 @@ Then, when the player gets hit, we show the overlay.
 
   .. code-tab:: csharp
 
-    public void OnPlayerHit()
+    private void OnPlayerHit()
     {
         //...
         GetNode<Control>("UserInterface/Retry").Show();
@@ -316,7 +315,7 @@ or by using the *+* icon next to your currently opened scene.
 
 |image15|
 
-Click the *Other Node* button to create an :ref:`AudioStreamPlayer2D <class_AudioStreamPlayer2D>` and rename it to
+Click the *Other Node* button to create an :ref:`AudioStreamPlayer <class_AudioStreamPlayer>` and rename it to
 ``MusicPlayer``.
 
 |image16|
@@ -370,7 +369,6 @@ Here is the complete ``Main.gd`` script for reference.
     @export var mob_scene: PackedScene
 
     func _ready():
-        randomize()
         $UserInterface/Retry.hide()
 
 
@@ -401,20 +399,18 @@ Here is the complete ``Main.gd`` script for reference.
         if event.is_action_pressed("ui_accept") and $UserInterface/Retry.visible:
             # This restarts the current scene.
             get_tree().reload_current_scene()
+
   .. code-tab:: csharp
 
     using Godot;
 
     public partial class Main : Node
     {
-    #pragma warning disable 649
         [Export]
-        public PackedScene MobScene;
-    #pragma warning restore 649
+        public PackedScene MobScene { get; set; }
 
         public override void _Ready()
         {
-            GD.Randomize();
             GetNode<Control>("UserInterface/Retry").Hide();
         }
 
@@ -422,25 +418,33 @@ Here is the complete ``Main.gd`` script for reference.
         {
             if (@event.IsActionPressed("ui_accept") && GetNode<Control>("UserInterface/Retry").Visible)
             {
+                // This restarts the current scene.
                 GetTree().ReloadCurrentScene();
             }
         }
 
-        public void OnMobTimerTimeout()
+        private void OnMobTimerTimeout()
         {
-            Mob mob = (Mob)MobScene.Instantiate();
+            // Create a new instance of the Mob scene.
+            Mob mob = MobScene.Instantiate<Mob>();
 
-            var mobSpawnLocation = GetNode<PathFollow>("SpawnPath/SpawnLocation");
-            mobSpawnLocation.UnitOffset = GD.Randf();
+            // Choose a random location on the SpawnPath.
+            // We store the reference to the SpawnLocation node.
+            var mobSpawnLocation = GetNode<PathFollow3D>("SpawnPath/SpawnLocation");
+            // And give it a random offset.
+            mobSpawnLocation.ProgressRatio = GD.Randf();
 
             Vector3 playerPosition = GetNode<Player>("Player").position;
-            mob.Initialize(mobSpawnLocation.Translation, playerPosition);
+            mob.Initialize(mobSpawnLocation.Position, playerPosition);
 
+            // Spawn the mob by adding it to the Main scene.
             AddChild(mob);
+
+            // We connect the mob to the score label to update the score upon squashing one.
             mob.Squashed += GetNode<ScoreLabel>("UserInterface/ScoreLabel").OnMobSquashed;
         }
 
-        public void OnPlayerHit()
+        private void OnPlayerHit()
         {
             GetNode<Timer>("MobTimer").Stop();
             GetNode<Control>("UserInterface/Retry").Show();

+ 79 - 50
getting_started/first_3d_game/09.adding_animations.rst

@@ -77,7 +77,7 @@ click any of them to create a keyframe, a time and value pair for the
 corresponding property. The keyframe gets inserted where your time cursor is in
 the timeline.
 
-Let's insert our first keys. Here, we will animate both the translation and the
+Let's insert our first keys. Here, we will animate both the position and the
 rotation of the ``Character`` node.
 
 Select the ``Character`` and in the *Inspector* expand the *Transform* section. Click the key icon next to *Position*, and *Rotation*.
@@ -93,7 +93,7 @@ Two tracks appear in the editor with a diamond icon representing each keyframe.
 |image11|
 
 You can click and drag on the diamonds to move them in time. Move the
-translation key to ``0.2`` seconds and the rotation key to ``0.1`` seconds.
+position key to ``0.2`` seconds and the rotation key to ``0.1`` seconds.
 
 |image12|
 
@@ -163,7 +163,7 @@ Apply an ease-out to the second keyframe in the rotation track.
 
 |image19|
 
-Do the opposite for the second translation keyframe, dragging it to the right.
+Do the opposite for the second position keyframe, dragging it to the right.
 
 |image20|
 
@@ -211,7 +211,7 @@ vector, add the following code.
 
  .. code-tab:: csharp
 
-    public override void _PhysicsProcess(float delta)
+    public override void _PhysicsProcess(double delta)
     {
         // ...
         if (direction != Vector3.Zero)
@@ -241,11 +241,11 @@ at the end of ``_physics_process()``.
 
  .. code-tab:: csharp
 
-    public override void _PhysicsProcess(float delta)
+    public override void _PhysicsProcess(double delta)
     {
         // ...
         var pivot = GetNode<Node3D>("Pivot");
-        pivot.Rotation = new Vector3(Mathf.Pi / 6f * _velocity.y / JumpImpulse, pivot.Rotation.y, pivot.Rotation.z);
+        pivot.Rotation = new Vector3(Mathf.Pi / 6.0f * Velocity.Y / JumpImpulse, pivot.Rotation.Y, pivot.Rotation.Z);
     }
 
 Animating the mobs
@@ -293,15 +293,16 @@ Here's the *Player* script.
 
 .. tabs::
  .. code-tab:: gdscript GDScript
-    
+
     extends CharacterBody3D
 
     signal hit
 
-    # How fast the player moves in meters per second
+    # How fast the player moves in meters per second.
     @export var speed = 14
     # The downward acceleration while in the air, in meters per second squared.
     @export var fall_acceleration = 75
+    # Vertical impulse applied to the character upon jumping in meters per second.
     @export var jump_impulse = 20
     # Vertical impulse applied to the character upon bouncing over a mob
     # in meters per second.
@@ -330,9 +331,9 @@ Here's the *Player* script.
         if direction != Vector3.ZERO:
             direction = direction.normalized()
             $Pivot.look_at(position + direction,Vector3.UP)
-            $AnimationPlayer.playback_speed = 4
+            $AnimationPlayer.speed_scale = 4
         else:
-            $AnimationPlayer.playback_speed = 1
+            $AnimationPlayer.speed_scale = 1
 
         # Ground Velocity
         target_velocity.x = direction.x * speed
@@ -378,6 +379,7 @@ Here's the *Player* script.
 
     func _on_mob_detector_body_entered(body):
         die()
+
  .. code-tab:: csharp
 
     using Godot;
@@ -390,44 +392,49 @@ Here's the *Player* script.
 
         // How fast the player moves in meters per second.
         [Export]
-        public int Speed = 14;
+        public int Speed { get; set; } = 14;
         // The downward acceleration when in the air, in meters per second squared.
         [Export]
-        public int FallAcceleration = 75;
+        public int FallAcceleration { get; set; } = 75;
         // Vertical impulse applied to the character upon jumping in meters per second.
         [Export]
-        public int JumpImpulse = 20;
+        public int JumpImpulse { get; set; } = 20;
         // Vertical impulse applied to the character upon bouncing over a mob in meters per second.
         [Export]
-        public int BounceImpulse = 16;
+        public int BounceImpulse { get; set; } = 16;
 
-        private Vector3 _velocity = Vector3.Zero;
+        private Vector3 _targetVelocity = Vector3.Zero;
 
-        public override void _PhysicsProcess(float delta)
+        public override void _PhysicsProcess(double delta)
         {
+            // We create a local variable to store the input direction.
             var direction = Vector3.Zero;
 
+            // We check for each move input and update the direction accordingly.
             if (Input.IsActionPressed("move_right"))
             {
-                direction.x += 1f;
+                direction.X += 1.0f;
             }
             if (Input.IsActionPressed("move_left"))
             {
-                direction.x -= 1f;
+                direction.X -= 1.0f;
             }
             if (Input.IsActionPressed("move_back"))
             {
-                direction.z += 1f;
+                // Notice how we are working with the vector's X and Z axes.
+                // In 3D, the XZ plane is the ground plane.
+                direction.Z += 1.0f;
             }
             if (Input.IsActionPressed("move_forward"))
             {
-                direction.z -= 1f;
+                direction.Z -= 1.0f;
             }
 
+            // Prevent diagonal movement being very fast.
             if (direction != Vector3.Zero)
             {
                 direction = direction.Normalized();
-                GetNode<Node3D>("Pivot").LookAt(Translation + direction, Vector3.Up);
+                GetNode<Node3D>("Pivot").LookAt(Position + direction, Vector3.Up);
                 GetNode<AnimationPlayer>("AnimationPlayer").PlaybackSpeed = 4;
             }
             else
@@ -435,42 +442,56 @@ Here's the *Player* script.
                 GetNode<AnimationPlayer>("AnimationPlayer").PlaybackSpeed = 1;
             }
 
-            _velocity.x = direction.x * Speed;
-            _velocity.z = direction.z * Speed;
+            // Ground velocity
+            _targetVelocity.X = direction.X * Speed;
+            _targetVelocity.Z = direction.Z * Speed;
+
+            // Vertical velocity
+            if (!IsOnFloor())
+            {
+                _targetVelocity.Y -= FallAcceleration * (float)delta;
+            }
 
             // Jumping.
             if (IsOnFloor() && Input.IsActionJustPressed("jump"))
             {
-                _velocity.y += JumpImpulse;
+                _targetVelocity.y += JumpImpulse;
             }
 
-            _velocity.y -= FallAcceleration * delta;
-            _velocity = MoveAndSlide(_velocity, Vector3.Up);
-
-            for (int index = 0; index < GetSlideCount(); index++)
+            // Iterate through all collisions that occurred this frame.
+            for (int index = 0; index < GetSlideCollisionCount(); index++)
             {
+                // We get one of the collisions with the player.
                 KinematicCollision3D collision = GetSlideCollision(index);
-                if (collision.Collider is Mob mob && mob.IsInGroup("mob"))
+
+                // If the collision is with a mob.
+                if (collision.GetCollider() is Mob mob)
                 {
-                    if (Vector3.Up.Dot(collision.Normal) > 0.1f)
+                    // We check that we are hitting it from above.
+                    if (Vector3.Up.Dot(collision.GetNormal()) > 0.1f)
                     {
+                        // If so, we squash it and bounce.
                         mob.Squash();
-                        _velocity.y = BounceImpulse;
+                        _targetVelocity.Y = BounceImpulse;
                     }
                 }
             }
 
+            // Moving the character
+            Velocity = _targetVelocity;
+            MoveAndSlide();
+
             var pivot = GetNode<Node3D>("Pivot");
-            pivot.Rotation = new Vector3(Mathf.Pi / 6f * _velocity.y / JumpImpulse, pivot.Rotation.y, pivot.Rotation.z);
+            pivot.Rotation = new Vector3(Mathf.Pi / 6.0f * Velocity.Y / JumpImpulse, pivot.Rotation.Y, pivot.Rotation.Z);
         }
 
         private void Die()
         {
-            EmitSignal(nameof(Hit));
+            EmitSignal(SignalName.Hit);
             QueueFree();
         }
 
-        public void OnMobDetectorBodyEntered(Node body)
+        private void OnMobDetectorBodyEntered(Node body)
         {
             Die();
         }
@@ -500,8 +521,8 @@ And the *Mob*'s script.
         # We position the mob by placing it at start_position
         # and rotate it towards player_position, so it looks at the player.
         look_at_from_position(start_position, player_position, Vector3.UP)
-        # In this rotation^, the mob will move directly towards the player
-        # so we rotate it randomly within range of -90 and +90 degrees.
+        # Rotate this mob randomly within range of -90 and +90 degrees,
+        # so that it doesn't move directly towards the player.
         rotate_y(randf_range(-PI / 4, PI / 4))
 
         # We calculate a random speed (integer)
@@ -512,7 +533,7 @@ And the *Mob*'s script.
         # in order to move in the direction the mob is looking.
         velocity = velocity.rotated(Vector3.UP, rotation.y)
 
-        $AnimationPlayer.playback_speed = random_speed / min_speed
+        $AnimationPlayer.speed_scale = random_speed / min_speed
 
     func _on_visible_on_screen_notifier_3d_screen_exited():
         queue_free()
@@ -520,6 +541,7 @@ And the *Mob*'s script.
     func squash():
         squashed.emit()
         queue_free() # Destroy this node
+
  .. code-tab:: csharp
 
     using Godot;
@@ -532,37 +554,44 @@ And the *Mob*'s script.
 
         // Minimum speed of the mob in meters per second
         [Export]
-        public int MinSpeed = 10;
+        public int MinSpeed { get; set; } = 10;
         // Maximum speed of the mob in meters per second
         [Export]
-        public int MaxSpeed = 18;
+        public int MaxSpeed { get; set; } = 18;
 
-        private Vector3 _velocity = Vector3.Zero;
-
-        public override void _PhysicsProcess(float delta)
+        public override void _PhysicsProcess(double delta)
         {
-            MoveAndSlide(_velocity);
+            MoveAndSlide();
         }
 
+        // This function will be called from the Main scene.
         public void Initialize(Vector3 startPosition, Vector3 playerPosition)
         {
+            // We position the mob by placing it at startPosition
+            // and rotate it towards playerPosition, so it looks at the player.
             LookAtFromPosition(startPosition, playerPosition, Vector3.Up);
+            // Rotate this mob randomly within range of -90 and +90 degrees,
+            // so that it doesn't move directly towards the player.
             RotateY((float)GD.RandRange(-Mathf.Pi / 4.0, Mathf.Pi / 4.0));
 
-            float randomSpeed = (float)GD.RandRange(MinSpeed, MaxSpeed);
-            _velocity = Vector3.Forward * randomSpeed;
-            _velocity = _velocity.Rotated(Vector3.Up, Rotation.y);
+            // We calculate a random speed (integer).
+            int randomSpeed = GD.RandRange(MinSpeed, MaxSpeed);
+            // We calculate a forward velocity that represents the speed.
+            Velocity = Vector3.Forward * randomSpeed;
+            // We then rotate the velocity vector based on the mob's Y rotation
+            // in order to move in the direction the mob is looking.
+            Velocity = Velocity.Rotated(Vector3.Up, Rotation.Y);
 
-            GetNode<AnimationPlayer>("AnimationPlayer").PlaybackSpeed = randomSpeed / MinSpeed;
+            GetNode<AnimationPlayer>("AnimationPlayer").SpeedScale = randomSpeed / MinSpeed;
         }
 
         public void Squash()
         {
-            EmitSignal(nameof(Squashed));
-            QueueFree();
+            EmitSignal(SignalName.Squashed);
+            QueueFree(); // Destroy this node
         }
 
-        public void OnVisibilityNotifierScreenExited()
+        private void OnVisibilityNotifierScreenExited()
         {
             QueueFree();
         }

+ 6 - 6
getting_started/introduction/first_look_at_the_editor.rst

@@ -1,8 +1,8 @@
 .. This page is only here to introduce the interface to the user broadly. To
    cover individual areas in greater detail, write the corresponding pages in
    the most appropriate section, and link them. E.g. the animation editor goes
-   to the animation section. General pages, for instance, about the project
-   manager, should go in the editor manual.
+   to the animation section. General pages, for instance, about the Project
+   Manager, should go in the editor manual.
 
 .. _doc_intro_to_the_editor_interface:
 
@@ -15,7 +15,7 @@ look at the different main screens and docks to help you situate yourself.
 .. seealso:: For a comprehensive breakdown of the editor's interface and how to
              use it, see the :ref:`Editor manual <toc-learn-editor>`.
 
-The Project manager
+The Project Manager
 -------------------
 
 When you launch Godot, the first window you see is the Project Manager. In the
@@ -24,11 +24,11 @@ ones, and more.
 
 .. image:: img/editor_intro_project_manager.webp
 
-At the top of the window, there is another tab named "Templates". You can search
+At the top of the window, there is another tab named "Asset Library Projects". You can search
 for demo projects in the open source asset library, which includes many projects
 developed by the community.
 
-.. seealso:: To learn the project manager's ins and outs, read
+.. seealso:: To learn the Project Manager's ins and outs, read
              :ref:`doc_project_manager`.
 
 .. image:: img/editor_intro_project_templates.webp
@@ -68,7 +68,7 @@ Below is the 3D one.
 
 .. image:: img/editor_intro_toolbar_3d.webp
 
-Let's look at the docks. The **FileSystem** dock lists your project files, be it
+Let's look at the docks. The **FileSystem** dock lists your project files, including
 scripts, images, audio samples, and more.
 
 .. image:: img/editor_intro_filesystem_dock.webp

+ 3 - 3
getting_started/introduction/godot_design_philosophy.rst

@@ -81,9 +81,9 @@ user experience. You can still work with external programs as long as
 there is an import plugin for it. Or you can create one, like the `Tiled
 Map Importer <https://github.com/vnen/godot-tiled-importer>`__.
 
-That is also partly why Godot offers its own programming languages
-GDScript and, along with C#. They're designed for the needs
-of game developers and game designers, and they're tightly integrated in
+That is also partly why Godot offers its own programming language
+GDScript along with C#. GDScript is designed for the needs
+of game developers and game designers, and is tightly integrated in
 the engine and the editor.
 
 GDScript lets you write code using an indentation-based syntax,

+ 1 - 1
getting_started/introduction/key_concepts_overview.rst

@@ -46,7 +46,7 @@ It is made of a ``CharacterBody2D`` node named "Character", a ``Sprite2D``, a
 ``Camera2D``, and a ``CollisionShape2D``.
 
 .. note:: The node names end with "2D" because this is a 2D scene. Their 3D
-          counterpart have names that end with "3D".
+          counterparts have names that end with "3D".
 
 Notice how nodes and scenes look the same in the editor. When you save a tree of
 nodes as a scene, it then shows as a single node, with its internal structure

+ 4 - 4
getting_started/introduction/learning_new_features.rst

@@ -30,7 +30,7 @@ available functions and properties when programming. While the manual covers
 general features, concepts, and how to use the editor, the reference is all
 about using Godot's scripting API (Application Programming Interface). You can
 access it both online and offline. We recommend browsing the reference offline,
-from within the Godot editor. To do so, go to Help -> Search or press
+from within the Godot editor. To do so, go to Help -> Search Help or press
 :kbd:`F1`.
 
 .. image:: img/manual_class_reference_search.png
@@ -86,10 +86,10 @@ help to better understand how to achieve something, you can ask other users for
 help on one of the many `active
 communities <https://godotengine.org/community>`_.
 
-The best place to ask for questions and find already answered ones is the
+The best place to ask questions and find already answered ones is the
 official `Questions & Answers <https://godotengine.org/qa/>`_ site. These
 responses show up in search engine results and get saved, allowing other users
-to benefit from discussions on the platform. Once you asked a question there,
+to benefit from discussions on the platform. Once you have asked a question there,
 you can share its link on other social platforms. Before asking a question, be
 sure to look for existing answers that might solve your problem on this website
 or using your preferred search engine.
@@ -141,7 +141,7 @@ information:
    interface evolve rapidly.
 
 Following these guidelines will maximize your chances of getting the answer
-you're looking for. They will save time both to you and the persons helping you.
+you're looking for. They will save time both for you and the persons helping you.
 
 Community tutorials
 -------------------

二进制
getting_started/step_by_step/img/scripting_first_script_add_sprite_node.png


二进制
getting_started/step_by_step/img/scripting_first_script_add_sprite_node.webp


二进制
getting_started/step_by_step/img/scripting_first_script_attach_node_script.png


二进制
getting_started/step_by_step/img/scripting_first_script_attach_node_script.webp


二进制
getting_started/step_by_step/img/scripting_first_script_attach_script.png


二进制
getting_started/step_by_step/img/scripting_first_script_attach_script.webp


二进制
getting_started/step_by_step/img/scripting_first_script_scene_tree.png


二进制
getting_started/step_by_step/img/scripting_first_script_scene_tree.webp


二进制
getting_started/step_by_step/img/scripting_first_script_setting_texture.png


二进制
getting_started/step_by_step/img/scripting_first_script_setting_texture.webp


+ 3 - 3
getting_started/step_by_step/instancing.rst

@@ -44,10 +44,10 @@ Let's use instancing in practice to see how it works in Godot. We invite
 you to download the ball's sample project we prepared for you:
 :download:`instancing.zip <files/instancing.zip>`.
 
-Extract the archive on your computer. To import it, you need the project manager.
-The project manager is accessed by opening Godot, or if you already have Godot opened, click on *Project -> Quit to Project List* (:kbd:`Ctrl + Shift + Q`)
+Extract the archive on your computer. To import it, you need the Project Manager.
+The Project Manager is accessed by opening Godot, or if you already have Godot opened, click on *Project -> Quit to Project List* (:kbd:`Ctrl + Shift + Q`)
 
-In the project manager, click the *Import* button to import the project.
+In the Project Manager, click the *Import* button to import the project.
 
 .. image:: img/instancing_import_button.png
 

+ 13 - 13
getting_started/step_by_step/scripting_first_script.rst

@@ -49,18 +49,18 @@ click the Other Node button.
 Type "Sprite2D" in the search bar to filter nodes and double-click on Sprite2D
 to create the node.
 
-.. image:: img/scripting_first_script_add_sprite_node.png
+.. image:: img/scripting_first_script_add_sprite_node.webp
 
 Your Scene tab should now only have a Sprite2D node.
 
-.. image:: img/scripting_first_script_scene_tree.png
+.. image:: img/scripting_first_script_scene_tree.webp
 
 A Sprite2D node needs a texture to display. In the Inspector on the right, you
 can see that the Texture property says "[empty]". To display the Godot icon,
-click and drag the file ``icon.png`` from the FileSystem dock onto the Texture
+click and drag the file ``icon.svg`` from the FileSystem dock onto the Texture
 slot.
 
-.. image:: img/scripting_first_script_setting_texture.png
+.. image:: img/scripting_first_script_setting_texture.webp
 
 .. note::
 
@@ -79,15 +79,15 @@ Creating a new script
 To create and attach a new script to our node, right-click on Sprite2D in the
 scene dock and select "Attach Script".
 
-.. image:: img/scripting_first_script_attach_script.png
+.. image:: img/scripting_first_script_attach_script.webp
 
 The Attach Node Script window appears. It allows you to select the script's
 language and file path, among other options.
 
-Change the Template from Default to Empty to start with a clean file. Leave the
+Change the Template field from "Node: Default" to "Object: Empty" to start with a clean file. Leave the
 other options by default and click the Create button to create the script.
 
-.. image:: img/scripting_first_script_attach_node_script.png
+.. image:: img/scripting_first_script_attach_node_script.webp
 
 The Script workspace should appear with your new ``Sprite2D.gd`` file open and
 the following line of code:
@@ -159,7 +159,7 @@ this function.
           it or don't indent a line correctly, the editor will highlight it in
           red and display the following error message: "Indented block expected".
 
-Save the scene if you haven't already, then press :kbd:`F6` (:kbd:`Cmd + R` on macOS)
+Save the scene as ``sprite_2d.tscn`` if you haven't already, then press :kbd:`F6` (:kbd:`Cmd + R` on macOS)
 to run it. Look at the **Output** bottom panel that expands.
 It should display "Hello, world!".
 
@@ -173,7 +173,7 @@ Turning around
 
 It's time to make our node move and rotate. To do so, we're going to add two
 member variables to our script: the movement speed in pixels per second and the
-angular speed in radians per second.
+angular speed in radians per second.  Add the following after the ``extends Sprite2D`` line.
 
 .. tabs::
  .. code-tab:: gdscript GDScript
@@ -259,8 +259,8 @@ Run the scene to see the Godot icon turn in-place.
 Moving forward
 ~~~~~~~~~~~~~~
 
-Let's now make the node move. Add the following two lines to the ``_process()``
-function, ensuring the new lines are indented the same way as the one before
+Let's now make the node move. Add the following two lines inside of the ``_process()``
+function, ensuring the new lines are indented the same way as the ``rotation += angular * delta`` line before
 them.
 
 .. tabs::
@@ -282,8 +282,8 @@ defines a local variable: it only exists within the function's scope.
 
 We define a local variable named ``velocity``, a 2D vector representing both a
 direction and a speed. To make the node move forward, we start from the Vector2
-class's constant Vector2.UP, a vector pointing up, and rotate it by calling the
-``Vector2.rotated()`` method. This expression, ``Vector2.UP.rotated(rotation)``,
+class's constant ``Vector2.UP``, a vector pointing up, and rotate it by calling the
+``rotated()`` method on any ``Vector2``. This expression, ``Vector2.UP.rotated(rotation)``,
 is a vector pointing forward relative to our icon. Multiplied by our ``speed``
 property, it gives us a velocity we can use to move the node forward.
 

+ 2 - 2
getting_started/step_by_step/scripting_languages.rst

@@ -130,7 +130,7 @@ C++ via GDExtension
 ~~~~~~~~~~~~~~~~~~~
 
 GDExtension allows you to write game code in C++ without needing to recompile
-or even restart Godot.
+Godot.
 
 .. image:: img/scripting_cpp.png
 
@@ -149,7 +149,7 @@ Summary
 Scripts are files containing code that you attach to a node to extend its
 functionality.
 
-Godot supports five official scripting languages, offering you flexibility
+Godot supports four official scripting languages, offering you flexibility
 between performance and ease of use.
 
 You can mix languages, for instance, to implement demanding algorithms with C or

+ 26 - 26
getting_started/step_by_step/signals.rst

@@ -157,7 +157,7 @@ the ``not`` keyword to invert the value.
 
  .. code-tab:: csharp C#
 
-    public void OnButtonPressed()
+    private void OnButtonPressed()
     {
         SetProcess(!IsProcessing());
     }
@@ -181,8 +181,8 @@ following code, which we saw two lessons ago:
 
     public override void _Process(double delta)
     {
-        Rotation += AngularSpeed * (float)delta;
-        var velocity = Vector2.Up.Rotated(Rotation) * Speed;
+        Rotation += _angularSpeed * (float)delta;
+        var velocity = Vector2.Up.Rotated(Rotation) * _speed;
         Position += velocity * (float)delta;
     }
 
@@ -210,19 +210,19 @@ Your complete ``Sprite2D.gd`` code should look like the following.
 
     using Godot;
 
-    public partial class Sprite : Sprite2D
+    public partial class MySprite2D : Sprite2D
     {
-        private float Speed = 400;
-        private float AngularSpeed = Mathf.Pi;
+        private float _speed = 400;
+        private float _angularSpeed = Mathf.Pi;
 
         public override void _Process(double delta)
         {
-            Rotation += AngularSpeed * (float)delta;
-            var velocity = Vector2.Up.Rotated(Rotation) * Speed;
+            Rotation += _angularSpeed * (float)delta;
+            var velocity = Vector2.Up.Rotated(Rotation) * _speed;
             Position += velocity * (float)delta;
         }
 
-        public void OnButtonPressed()
+        private void OnButtonPressed()
         {
             SetProcess(!IsProcessing());
         }
@@ -323,7 +323,7 @@ bottom of our script and use it to toggle our sprite's visibility.
 
  .. code-tab:: csharp C#
 
-    public void OnTimerTimeout()
+    private void OnTimerTimeout()
     {
         Visible = !Visible;
     }
@@ -372,10 +372,10 @@ Here is the complete ``Sprite2D.gd`` file for reference.
 
     using Godot;
 
-    public partial class Sprite : Sprite2D
+    public partial class MySprite2D : Sprite2D
     {
-        private float Speed = 400;
-        private float AngularSpeed = Mathf.Pi;
+        private float _speed = 400;
+        private float _angularSpeed = Mathf.Pi;
 
         public override void _Ready()
         {
@@ -385,17 +385,17 @@ Here is the complete ``Sprite2D.gd`` file for reference.
 
         public override void _Process(double delta)
         {
-            Rotation += AngularSpeed * (float)delta;
-            var velocity = Vector2.Up.Rotated(Rotation) * Speed;
+            Rotation += _angularSpeed * (float)delta;
+            var velocity = Vector2.Up.Rotated(Rotation) * _speed;
             Position += velocity * (float)delta;
         }
 
-        public void OnButtonPressed()
+        private void OnButtonPressed()
         {
             SetProcess(!IsProcessing());
         }
 
-        public void OnTimerTimeout()
+        private void OnTimerTimeout()
         {
             Visible = !Visible;
         }
@@ -425,12 +425,12 @@ reaches 0.
 
     using Godot;
 
-    public partial class CustomSignal : Node2D
+    public partial class MyNode2D : Node2D
     {
         [Signal]
         public delegate void HealthDepletedEventHandler();
 
-        private int Health = 10;
+        private int _health = 10;
     }
 
 .. note:: As signals represent events that just occurred, we generally use an
@@ -455,9 +455,9 @@ To emit a signal in your scripts, call ``emit()`` on the signal.
 
     public void TakeDamage(int amount)
     {
-        Health -= amount;
+        _health -= amount;
 
-        if (Health < 0)
+        if (_health <= 0)
         {
             EmitSignal(SignalName.HealthDepleted);
         }
@@ -479,12 +479,12 @@ names between parentheses:
 
     using Godot;
 
-    public partial class CustomSignal : Node
+    public partial class MyNode : Node
     {
         [Signal]
         public delegate void HealthChangedEventHandler(int oldValue, int newValue);
 
-        private int Health = 10;
+        private int _health = 10;
     }
 
 .. note::
@@ -509,9 +509,9 @@ To emit values along with the signal, add them as extra arguments to the
 
     public void TakeDamage(int amount)
     {
-        var oldHealth = Health;
-        Health -= amount;
-        EmitSignal(SignalName.HealthChanged, oldHealth, Health);
+        int oldHealth = _health;
+        _health -= amount;
+        EmitSignal(SignalName.HealthChanged, oldHealth, _health);
     }
 
 Summary

二进制
img/control_gallery.webp


+ 1 - 1
tutorials/2d/2d_movement.rst

@@ -261,7 +261,7 @@ on the screen will cause the player to move to the target location.
 
         public override void _PhysicsProcess(double delta)
         {
-            velocity = Position.DirectionTo(_target) * Speed;
+            Velocity = Position.DirectionTo(_target) * Speed;
             // LookAt(target);
             if (Position.DistanceTo(_target) > 10)
             {

+ 4 - 4
tutorials/2d/2d_sprite_animation.rst

@@ -33,7 +33,7 @@ You can download the images here:
 Unzip the images and place them in your project folder. Set up your scene tree
 with the following nodes:
 
-.. image:: img/2d_animation_tree1.png
+.. image:: img/2d_animation_tree1.webp
 
 .. note:: The root node could also be :ref:`Area2D <class_Area2D>` or
           :ref:`RigidBody2D <class_RigidBody2D>`. The animation will still be
@@ -78,7 +78,7 @@ released.
 
     extends CharacterBody2D
 
-    onready var _animated_sprite = $AnimatedSprite2D
+    @onready var _animated_sprite = $AnimatedSprite2D
 
     func _process(_delta):
         if Input.is_action_pressed("ui_right"):
@@ -165,7 +165,7 @@ image into your project folder.
 Our goal is to display these images one after another in a loop. Start by
 setting up your scene tree:
 
-.. image:: img/2d_animation_tree2.png
+.. image:: img/2d_animation_tree2.webp
 
 .. note:: The root node could also be :ref:`Area2D <class_Area2D>` or
           :ref:`RigidBody2D <class_RigidBody2D>`. The animation will still be
@@ -219,7 +219,7 @@ released.
 
     extends CharacterBody2D
 
-    onready var _animation_player = $AnimationPlayer
+    @onready var _animation_player = $AnimationPlayer
 
     func _process(_delta):
         if Input.is_action_pressed("ui_right"):

+ 1 - 1
tutorials/2d/2d_transforms.rst

@@ -99,7 +99,7 @@ way:
 
     var local_pos = Vector2(10, 20) # local to Control/Node2D
     var ie = InputEventMouseButton.new()
-    ie.button_index = BUTTON_LEFT
+    ie.button_index = MOUSE_BUTTON_LEFT
     ie.position = get_viewport_transform() * (get_global_transform() * local_pos)
     get_tree().input_event(ie)
 

二进制
tutorials/2d/img/2d_animation_tree1.png


部分文件因为文件数量过多而无法显示