c_sharp_features.rst 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. .. _doc_c_sharp_features:
  2. C# features
  3. ===========
  4. This page provides an overview of the commonly used features of both C# and Godot
  5. and how they are used together.
  6. .. _doc_c_sharp_features_type_conversion_and_casting:
  7. Type conversion and casting
  8. ---------------------------
  9. C# is a statically typed language. Therefore, you can't do the following:
  10. .. code-block:: csharp
  11. var mySprite = GetNode("MySprite");
  12. mySprite.SetFrame(0);
  13. The method ``GetNode()`` returns a ``Node`` instance.
  14. You must explicitly convert it to the desired derived type, ``Sprite2D`` in this case.
  15. For this, you have various options in C#.
  16. **Casting and Type Checking**
  17. Throws ``InvalidCastException`` if the returned node cannot be cast to Sprite2D.
  18. You would use it instead of the ``as`` operator if you are pretty sure it won't fail.
  19. .. code-block:: csharp
  20. Sprite2D mySprite = (Sprite2D)GetNode("MySprite");
  21. mySprite.SetFrame(0);
  22. **Using the AS operator**
  23. The ``as`` operator returns ``null`` if the node cannot be cast to Sprite2D,
  24. and for that reason, it cannot be used with value types.
  25. .. code-block:: csharp
  26. Sprite2D mySprite = GetNode("MySprite") as Sprite2D;
  27. // Only call SetFrame() if mySprite is not null
  28. mySprite?.SetFrame(0);
  29. **Using the generic methods**
  30. Generic methods are also provided to make this type conversion transparent.
  31. ``GetNode<T>()`` casts the node before returning it. It will throw an ``InvalidCastException`` if the node cannot be cast to the desired type.
  32. .. code-block:: csharp
  33. Sprite2D mySprite = GetNode<Sprite2D>("MySprite");
  34. mySprite.SetFrame(0);
  35. ``GetNodeOrNull<T>()`` uses the ``as`` operator and will return ``null`` if the node cannot be cast to the desired type.
  36. .. code-block:: csharp
  37. Sprite2D mySprite = GetNodeOrNull<Sprite2D>("MySprite");
  38. // Only call SetFrame() if mySprite is not null
  39. mySprite?.SetFrame(0);
  40. **Type checking using the IS operator**
  41. To check if the node can be cast to Sprite2D, you can use the ``is`` operator.
  42. The ``is`` operator returns false if the node cannot be cast to Sprite2D,
  43. otherwise it returns true. Note that when the ``is`` operator is used against ``null``
  44. the result is always going to be ``false``.
  45. .. code-block:: csharp
  46. if (GetNode("MySprite") is Sprite2D)
  47. {
  48. // Yup, it's a Sprite2D!
  49. }
  50. if (null is Sprite2D)
  51. {
  52. // This block can never happen.
  53. }
  54. For more advanced type checking, you can look into `Pattern Matching <https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching>`_.
  55. Preprocessor defines
  56. --------------------
  57. Godot has a set of defines that allow you to change your C# code
  58. depending on the environment you are compiling to.
  59. .. note:: If you created your project before Godot 3.2, you have to modify
  60. or regenerate your `csproj` file to use this feature
  61. (compare ``<DefineConstants>`` with a new 3.2+ project).
  62. Examples
  63. ~~~~~~~~
  64. For example, you can change code based on the platform:
  65. .. code-block:: csharp
  66. public override void _Ready()
  67. {
  68. #if GODOT_SERVER
  69. // Don't try to load meshes or anything, this is a server!
  70. LaunchServer();
  71. #elif GODOT_32 || GODOT_MOBILE || GODOT_WEB
  72. // Use simple objects when running on less powerful systems.
  73. SpawnSimpleObjects();
  74. #else
  75. SpawnComplexObjects();
  76. #endif
  77. }
  78. Or you can detect which engine your code is in, useful for making cross-engine libraries:
  79. .. code-block:: csharp
  80. public void MyPlatformPrinter()
  81. {
  82. #if GODOT
  83. GD.Print("This is Godot.");
  84. #elif UNITY_5_3_OR_NEWER
  85. print("This is Unity.");
  86. #else
  87. throw new NotSupportedException("Only Godot and Unity are supported.");
  88. #endif
  89. }
  90. Full list of defines
  91. ~~~~~~~~~~~~~~~~~~~~
  92. * ``GODOT`` is always defined for Godot projects.
  93. * ``TOOLS`` is defined when building with the Debug configuration (editor and editor player).
  94. * ``GODOT_REAL_T_IS_DOUBLE`` is defined when the ``GodotFloat64`` property is set to ``true``.
  95. * One of ``GODOT_64`` or ``GODOT_32`` is defined depending on if the architecture is 64-bit or 32-bit.
  96. * One of ``GODOT_LINUXBSD``, ``GODOT_WINDOWS``, ``GODOT_OSX``,
  97. ``GODOT_ANDROID``, ``GODOT_IOS``, ``GODOT_HTML5``, or ``GODOT_SERVER``
  98. depending on the OS. These names may change in the future.
  99. These are created from the ``get_name()`` method of the
  100. :ref:`OS <class_OS>` singleton, but not every possible OS
  101. the method returns is an OS that Godot with .NET runs on.
  102. When **exporting**, the following may also be defined depending on the export features:
  103. * One of ``GODOT_PC``, ``GODOT_MOBILE``, or ``GODOT_WEB`` depending on the platform type.
  104. * One of ``GODOT_ARM64_V8A`` or ``GODOT_ARMEABI_V7A`` on Android only depending on the architecture.
  105. * One of ``GODOT_ARM64`` or ``GODOT_ARMV7`` on iOS only depending on the architecture.
  106. * Any of ``GODOT_S3TC``, ``GODOT_ETC``, and ``GODOT_ETC2`` depending on the texture compression type.
  107. To see an example project, see the OS testing demo:
  108. https://github.com/godotengine/godot-demo-projects/tree/master/misc/os_test