mirror of
https://github.com/godotengine/godot-docs.git
synced 2025-12-31 17:49:03 +03:00
Update some C# examples for 4.0 (#6693)
* Update some C# examples - Rename members that have been renamed in Godot's C# API for 4.0. - Change `delta` parameter type to `double`. - Ensure parameters match base declaration. - Other minor code fixes. --------- Co-authored-by: Paul Joannon <437025+paulloz@users.noreply.github.com>
This commit is contained in:
@@ -104,7 +104,9 @@ way:
|
||||
.. code-tab:: csharp
|
||||
|
||||
var localPos = new Vector2(10,20); // local to Control/Node2D
|
||||
var ie = new InputEventMouseButton();
|
||||
ie.ButtonIndex = (int)ButtonList.Left;
|
||||
ie.Position = (GetViewportTransform() * GetGlobalTransform()).Xform(localPos);
|
||||
var ie = new InputEventMouseButton()
|
||||
{
|
||||
ButtonIndex = MouseButton.Left,
|
||||
Position = GetViewportTransform() * (GetGlobalTransform() * localPos),
|
||||
};
|
||||
GetTree().InputEvent(ie);
|
||||
|
||||
@@ -84,7 +84,7 @@ redrawn if modified:
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class CustomNode2D : Node2D
|
||||
public partial class MyNode2D : Node2D
|
||||
{
|
||||
private Texture _texture;
|
||||
public Texture Texture
|
||||
@@ -133,7 +133,7 @@ call ``queue_redraw()`` from the ``_process()`` callback, like this:
|
||||
// Your draw commands here
|
||||
}
|
||||
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
QueueRedraw();
|
||||
}
|
||||
@@ -387,7 +387,7 @@ using ``get_node()``.
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class CustomNode2D : Node2D
|
||||
public partial class MyNode2D : Node2D
|
||||
{
|
||||
private float _rotationAngle = 50;
|
||||
private float _angleFrom = 75;
|
||||
@@ -421,7 +421,7 @@ calls ``_draw()``. This way, you can control when you want to refresh the frame.
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
_angleFrom += _rotationAngle;
|
||||
_angleTo += _rotationAngle;
|
||||
@@ -490,10 +490,10 @@ smaller value, which directly depends on the rendering speed.
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
_angleFrom += _rotationAngle * delta;
|
||||
_angleTo += _rotationAngle * delta;
|
||||
_angleFrom += _rotationAngle * (float)delta;
|
||||
_angleTo += _rotationAngle * (float)delta;
|
||||
|
||||
// We only wrap angles when both of them are bigger than 360.
|
||||
if (_angleFrom > 360 && _angleTo > 360)
|
||||
|
||||
@@ -112,9 +112,9 @@ A default basis (unmodified) is akin to:
|
||||
|
||||
// Instead we can use the Identity property.
|
||||
var identityBasis = Basis.Identity;
|
||||
GD.Print(identityBasis.x); // prints: (1, 0, 0)
|
||||
GD.Print(identityBasis.y); // prints: (0, 1, 0)
|
||||
GD.Print(identityBasis.z); // prints: (0, 0, 1)
|
||||
GD.Print(identityBasis.X); // prints: (1, 0, 0)
|
||||
GD.Print(identityBasis.Y); // prints: (0, 1, 0)
|
||||
GD.Print(identityBasis.Z); // prints: (0, 0, 1)
|
||||
|
||||
// The Identity basis is equivalent to:
|
||||
var basis = new Basis(Vector3.Right, Vector3.Up, Vector3.Back);
|
||||
@@ -161,9 +161,9 @@ It is possible to rotate a transform, either by multiplying its basis by another
|
||||
Vector3 axis = new Vector3(1, 0, 0); // Or Vector3.Right
|
||||
float rotationAmount = 0.1f;
|
||||
// Rotate the transform around the X axis by 0.1 radians.
|
||||
transform.basis = new Basis(axis, rotationAmount) * transform.basis;
|
||||
transform.Basis = new Basis(axis, rotationAmount) * transform.Basis;
|
||||
// shortened
|
||||
transform.basis = transform.basis.Rotated(axis, rotationAmount);
|
||||
transform.Basis = transform.Basis.Rotated(axis, rotationAmount);
|
||||
|
||||
A method in Node3D simplifies this:
|
||||
|
||||
@@ -246,7 +246,7 @@ Imagine you need to shoot a bullet in the direction your player is facing. Just
|
||||
.. code-tab:: csharp
|
||||
|
||||
bullet.Transform = transform;
|
||||
bullet.LinearVelocity = transform.basis.z * BulletSpeed;
|
||||
bullet.LinearVelocity = transform.Basis.Z * BulletSpeed;
|
||||
|
||||
Is the enemy looking at the player? Use the dot product for this (see the :ref:`doc_vector_math` tutorial for an explanation of the dot product):
|
||||
|
||||
@@ -261,8 +261,8 @@ Is the enemy looking at the player? Use the dot product for this (see the :ref:`
|
||||
.. code-tab:: csharp
|
||||
|
||||
// Get the direction vector from player to enemy
|
||||
Vector3 direction = enemy.Transform.origin - player.Transform.origin;
|
||||
if (direction.Dot(enemy.Transform.basis.z) > 0)
|
||||
Vector3 direction = enemy.Transform.Origin - player.Transform.Origin;
|
||||
if (direction.Dot(enemy.Transform.Basis.Z) > 0)
|
||||
{
|
||||
enemy.ImWatchingYou(player);
|
||||
}
|
||||
@@ -281,7 +281,7 @@ Strafe left:
|
||||
// Remember that +X is right
|
||||
if (Input.IsActionPressed("strafe_left"))
|
||||
{
|
||||
TranslateObjectLocal(-Transform.basis.x);
|
||||
TranslateObjectLocal(-Transform.Basis.X);
|
||||
}
|
||||
|
||||
Jump:
|
||||
@@ -299,7 +299,7 @@ Jump:
|
||||
|
||||
// Keep in mind Y is up-axis
|
||||
if (Input.IsActionJustPressed("jump"))
|
||||
velocity.y = JumpSpeed;
|
||||
velocity.Y = JumpSpeed;
|
||||
|
||||
velocity = MoveAndSlide(velocity);
|
||||
|
||||
@@ -341,12 +341,12 @@ Example of looking around, FPS style:
|
||||
if (@event is InputEventMouseMotion mouseMotion)
|
||||
{
|
||||
// modify accumulated mouse rotation
|
||||
_rotationX += mouseMotion.Relative.x * LookAroundSpeed;
|
||||
_rotationY += mouseMotion.Relative.y * LookAroundSpeed;
|
||||
_rotationX += mouseMotion.Relative.X * LookAroundSpeed;
|
||||
_rotationY += mouseMotion.Relative.Y * LookAroundSpeed;
|
||||
|
||||
// reset rotation
|
||||
Transform3D transform = Transform;
|
||||
transform.basis = Basis.Identity;
|
||||
transform.Basis = Basis.Identity;
|
||||
Transform = transform;
|
||||
|
||||
RotateObjectLocal(Vector3.Up, _rotationX); // first rotate about Y
|
||||
@@ -377,12 +377,12 @@ Converting a rotation to quaternion is straightforward.
|
||||
.. code-tab:: csharp
|
||||
|
||||
// Convert basis to quaternion, keep in mind scale is lost
|
||||
var a = transform.basis.Quaternion();
|
||||
var b = transform2.basis.Quaternion();
|
||||
var a = transform.Basis.GetQuaternion();
|
||||
var b = transform2.Basis.GetQuaternion();
|
||||
// Interpolate using spherical-linear interpolation (SLERP).
|
||||
var c = a.Slerp(b, 0.5f); // find halfway point between a and b
|
||||
// Apply back
|
||||
transform.basis = new Basis(c);
|
||||
transform.Basis = new Basis(c);
|
||||
|
||||
The :ref:`class_Quaternion` type reference has more information on the datatype (it
|
||||
can also do transform accumulation, transform points, etc., though this is used
|
||||
|
||||
@@ -249,28 +249,25 @@ tree structures.
|
||||
.. code-tab:: csharp
|
||||
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
// Can decide whether to expose getters/setters for properties later
|
||||
public partial class TreeNode : Object
|
||||
public partial class TreeNode : GodotObject
|
||||
{
|
||||
private TreeNode _parent = null;
|
||||
|
||||
private object[] _children = new object[0];
|
||||
private List<TreeNode> _children = new();
|
||||
|
||||
public override void Notification(int what)
|
||||
public override void _Notification(int what)
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case NotificationPredelete:
|
||||
foreach (object child in _children)
|
||||
foreach (TreeNode child in _children)
|
||||
{
|
||||
TreeNode node = child as TreeNode;
|
||||
if (node != null)
|
||||
node.Free();
|
||||
node.Free();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ is to get a reference to an existing object from another acquired instance.
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
Object obj = node.Object; // Property access.
|
||||
Object obj = node.GetObject(); // Method access.
|
||||
GodotObject obj = node.Object; // Property access.
|
||||
GodotObject obj = node.GetObject(); // Method access.
|
||||
|
||||
The same principle applies for :ref:`RefCounted <class_RefCounted>` objects.
|
||||
While users often access :ref:`Node <class_Node>` and
|
||||
@@ -181,31 +181,35 @@ Nodes likewise have an alternative access point: the SceneTree.
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public class MyNode
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
public class MyNode : Node
|
||||
{
|
||||
// Slow
|
||||
public void DynamicLookupWithDynamicNodePath()
|
||||
{
|
||||
GD.Print(GetNode(NodePath("Child")));
|
||||
GD.Print(GetNode("Child"));
|
||||
}
|
||||
|
||||
// Fastest. Lookup node and cache for future access.
|
||||
// Doesn't break if node moves later.
|
||||
public Node Child;
|
||||
private Node _child;
|
||||
public void _Ready()
|
||||
{
|
||||
Child = GetNode(NodePath("Child"));
|
||||
_child = GetNode("Child");
|
||||
}
|
||||
public void LookupAndCacheForFutureAccess()
|
||||
{
|
||||
GD.Print(Child);
|
||||
GD.Print(_child);
|
||||
}
|
||||
|
||||
// Delegate reference assignment to an external source.
|
||||
// Con: need to perform a validation check.
|
||||
// Pro: node makes no requirements of its external structure.
|
||||
// 'prop' can come from anywhere.
|
||||
public object Prop;
|
||||
public object Prop { get; set; }
|
||||
public void CallMeAfterPropIsInitializedByParent()
|
||||
{
|
||||
// Validate prop in one of three ways.
|
||||
@@ -223,7 +227,15 @@ Nodes likewise have an alternative access point: the SceneTree.
|
||||
return;
|
||||
}
|
||||
|
||||
// Fail with an exception.
|
||||
if (prop == null)
|
||||
{
|
||||
throw new InvalidOperationException("'Prop' wasn't initialized.");
|
||||
}
|
||||
|
||||
// Fail and terminate.
|
||||
// Note: Scripts run from a release export template don't
|
||||
// run `Debug.Assert` statements.
|
||||
Debug.Assert(Prop, "'Prop' wasn't initialized");
|
||||
}
|
||||
|
||||
@@ -232,10 +244,10 @@ Nodes likewise have an alternative access point: the SceneTree.
|
||||
// that manage their own data and don't interfere with other objects.
|
||||
public void ReferenceAGlobalAutoloadedVariable()
|
||||
{
|
||||
Node globals = GetNode(NodePath("/root/Globals"));
|
||||
MyNode globals = GetNode<MyNode>("/root/Globals");
|
||||
GD.Print(globals);
|
||||
GD.Print(globals.prop);
|
||||
GD.Print(globals.my_getter());
|
||||
GD.Print(globals.Prop);
|
||||
GD.Print(globals.MyGetter());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ deltatime methods as needed.
|
||||
{
|
||||
|
||||
// Called every frame, even when the engine detects no input.
|
||||
public void _Process(float delta)
|
||||
public void _Process(double delta)
|
||||
{
|
||||
if (Input.IsActionJustPressed("ui_select"))
|
||||
GD.Print(delta);
|
||||
@@ -130,12 +130,10 @@ deltatime methods as needed.
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case InputEventKey keyEvent:
|
||||
case InputEventKey:
|
||||
if (Input.IsActionJustPressed("ui_accept"))
|
||||
GD.Print(GetProcessDeltaTime());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +185,7 @@ instantiation:
|
||||
set
|
||||
{
|
||||
_test = value;
|
||||
GD.Print("Setting: " + _test);
|
||||
GD.Print($"Setting: {_test}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ program termination, you should send the notification yourself:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
GetTree().Root.PropagateNotification((int)NotificationWmCloseRequest)
|
||||
GetTree().Root.PropagateNotification((int)NotificationWmCloseRequest);
|
||||
|
||||
Sending this notification will inform all nodes about the program termination,
|
||||
but will not terminate the program itself *unlike in 3.X*. In order to achieve
|
||||
|
||||
@@ -43,20 +43,20 @@ Examples:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Input(InputEvent inputEvent)
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
if (inputEvent.IsActionPressed("jump"))
|
||||
if (@event.IsActionPressed("jump"))
|
||||
{
|
||||
Jump();
|
||||
}
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
if (Input.IsActionPressed("move_right"))
|
||||
{
|
||||
// Move as long as the key/button is pressed.
|
||||
position.x += speed * delta;
|
||||
position.X += speed * (float)delta;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,9 +89,9 @@ attach the following script:
|
||||
|
||||
public partial class Node : Godot.Node
|
||||
{
|
||||
public override void _Input(InputEvent inputEvent)
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
GD.Print(inputEvent.AsText());
|
||||
GD.Print(@event.AsText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,9 +136,9 @@ avoid this, make sure to test the event type first:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Input(InputEvent inputEvent)
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
if (inputEvent is InputEventMouseButton mouseEvent)
|
||||
if (@event is InputEventMouseButton mouseEvent)
|
||||
{
|
||||
GD.Print("mouse button event at ", mouseEvent.Position);
|
||||
}
|
||||
@@ -172,9 +172,9 @@ the action you're looking for:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Input(InputEvent inputEvent)
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
if (inputEvent.IsActionPressed("my_action"))
|
||||
if (@event.IsActionPressed("my_action"))
|
||||
{
|
||||
GD.Print("my_action occurred!");
|
||||
}
|
||||
@@ -198,11 +198,11 @@ the :kbd:`T`:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Input(InputEvent inputEvent)
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
if (inputEvent is InputEventKey keyEvent && keyEvent.Pressed)
|
||||
if (@event is InputEventKey keyEvent && keyEvent.Pressed)
|
||||
{
|
||||
if ((KeyList)keyEvent.Keycode == KeyList.T)
|
||||
if (keyEvent.Keycode == Key.T)
|
||||
{
|
||||
GD.Print("T was pressed");
|
||||
}
|
||||
@@ -247,13 +247,13 @@ different when it's :kbd:`Shift + T`:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Input(InputEvent inputEvent)
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
if (inputEvent is InputEventKey keyEvent && keyEvent.Pressed)
|
||||
if (@event is InputEventKey keyEvent && keyEvent.Pressed)
|
||||
{
|
||||
switch ((KeyList)keyEvent.Keycode)
|
||||
switch (keyEvent.Keycode)
|
||||
{
|
||||
case KeyList.T:
|
||||
case Key.T:
|
||||
GD.Print(keyEvent.Shift ? "Shift+T was pressed" : "T was pressed");
|
||||
break;
|
||||
}
|
||||
@@ -292,9 +292,9 @@ also counts as a button - two buttons, to be precise, with both
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Input(InputEvent inputEvent)
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
if (inputEvent is InputEventMouseButton mouseEvent && mouseEvent.Pressed)
|
||||
if (@event is InputEventMouseButton mouseEvent && mouseEvent.Pressed)
|
||||
{
|
||||
switch (mouseEvent.ButtonIndex)
|
||||
{
|
||||
@@ -346,12 +346,12 @@ node:
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class Node2D : Godot.Node2D
|
||||
public partial class MyNode2D : Node2D
|
||||
{
|
||||
private bool dragging = false;
|
||||
private int clickRadius = 32; // Size of the sprite.
|
||||
private bool _dragging = false;
|
||||
private int _clickRadius = 32; // Size of the sprite.
|
||||
|
||||
public override void _Input(InputEvent inputEvent)
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
Sprite2D sprite = GetNodeOrNull<Sprite2D>("Sprite2D");
|
||||
if (sprite == null)
|
||||
@@ -359,25 +359,25 @@ node:
|
||||
return; // No suitable node was found.
|
||||
}
|
||||
|
||||
if (inputEvent is InputEventMouseButton mouseEvent && (ButtonList)mouseEvent.ButtonIndex == ButtonList.Left)
|
||||
if (@event is InputEventMouseButton mouseEvent && mouseEvent.ButtonIndex == MouseButton.Left)
|
||||
{
|
||||
if ((mouseEvent.Position - sprite.Position).Length() < clickRadius)
|
||||
if ((mouseEvent.Position - sprite.Position).Length() < _clickRadius)
|
||||
{
|
||||
// Start dragging if the click is on the sprite.
|
||||
if (!dragging && mouseEvent.Pressed)
|
||||
if (!_dragging && mouseEvent.Pressed)
|
||||
{
|
||||
dragging = true;
|
||||
_dragging = true;
|
||||
}
|
||||
}
|
||||
// Stop dragging if the button is released.
|
||||
if (dragging && !mouseEvent.Pressed)
|
||||
if (_dragging && !mouseEvent.Pressed)
|
||||
{
|
||||
dragging = false;
|
||||
_dragging = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inputEvent is InputEventMouseMotion motionEvent && dragging)
|
||||
if (@event is InputEventMouseMotion motionEvent && _dragging)
|
||||
{
|
||||
// While dragging, move the sprite with the mouse.
|
||||
sprite.Position = motionEvent.Position;
|
||||
|
||||
@@ -27,7 +27,7 @@ Here is a quick example, closing your game if the escape key is hit:
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
{
|
||||
if (@event is InputEventKey eventKey)
|
||||
if (eventKey.Pressed && eventKey.Keycode == (int)KeyList.Escape)
|
||||
if (eventKey.Pressed && eventKey.Keycode == Key.Escape)
|
||||
GetTree().Quit();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ You can set up your InputMap under **Project > Project Settings > Input Map** an
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (Input.IsActionPressed("ui_right"))
|
||||
{
|
||||
|
||||
@@ -94,8 +94,8 @@ The save function will look like this:
|
||||
{
|
||||
{ "Filename", SceneFilePath },
|
||||
{ "Parent", GetParent().GetPath() },
|
||||
{ "PosX", Position.x }, // Vector2 is not supported by JSON
|
||||
{ "PosY", Position.y },
|
||||
{ "PosX", Position.X }, // Vector2 is not supported by JSON
|
||||
{ "PosY", Position.Y },
|
||||
{ "Attack", Attack },
|
||||
{ "Defense", Defense },
|
||||
{ "CurrentHealth", CurrentHealth },
|
||||
@@ -152,7 +152,7 @@ way to pull the data out of the file as well.
|
||||
# Call the node's save function.
|
||||
var node_data = node.call("save")
|
||||
|
||||
# JSON provides a static method to serialized JSON string
|
||||
# JSON provides a static method to serialized JSON string.
|
||||
var json_string = JSON.stringify(node_data)
|
||||
|
||||
# Store the save dictionary as a new line in the save file.
|
||||
@@ -188,8 +188,8 @@ way to pull the data out of the file as well.
|
||||
// Call the node's save function.
|
||||
var nodeData = saveNode.Call("Save");
|
||||
|
||||
// JSON provides a static method to serialized JSON string
|
||||
var jsonString = JSON.Stringify(nodeData);
|
||||
// Json provides a static method to serialized JSON string.
|
||||
var jsonString = Json.Stringify(nodeData);
|
||||
|
||||
// Store the save dictionary as a new line in the save file.
|
||||
saveGame.StoreLine(jsonString);
|
||||
@@ -257,7 +257,9 @@ load function:
|
||||
public void LoadGame()
|
||||
{
|
||||
if (!FileAccess.FileExists("user://savegame.save"))
|
||||
{
|
||||
return; // Error! We don't have a save to load.
|
||||
}
|
||||
|
||||
// We need to revert the game state so we're not cloning objects during loading.
|
||||
// This will vary wildly depending on the needs of a project, so take care with
|
||||
@@ -265,7 +267,9 @@ load function:
|
||||
// For our example, we will accomplish this by deleting saveable objects.
|
||||
var saveNodes = GetTree().GetNodesInGroup("Persist");
|
||||
foreach (Node saveNode in saveNodes)
|
||||
{
|
||||
saveNode.QueueFree();
|
||||
}
|
||||
|
||||
// Load the file line by line and process that dictionary to restore the object
|
||||
// it represents.
|
||||
@@ -276,7 +280,7 @@ load function:
|
||||
var jsonString = saveGame.GetLine();
|
||||
|
||||
// Creates the helper class to interact with JSON
|
||||
var json = new JSON();
|
||||
var json = new Json();
|
||||
var parseResult = json.Parse(jsonString);
|
||||
if (parseResult != Error.Ok)
|
||||
{
|
||||
@@ -288,18 +292,19 @@ load function:
|
||||
var nodeData = new Godot.Collections.Dictionary<string, Variant>((Godot.Collections.Dictionary)json.Data);
|
||||
|
||||
// Firstly, we need to create the object and add it to the tree and set its position.
|
||||
var newObjectScene = (PackedScene)ResourceLoader.Load(nodeData["Filename"].ToString());
|
||||
var newObject = (Node)newObjectScene.Instantiate();
|
||||
var newObjectScene = GD.Load<PackedScene>(nodeData["Filename"].ToString());
|
||||
var newObject = newObjectScene.Instantiate<Node>();
|
||||
GetNode(nodeData["Parent"].ToString()).AddChild(newObject);
|
||||
newObject.Set("position", new Vector2((float)nodeData["PosX"], (float)nodeData["PosY"]));
|
||||
newObject.Set(Node2D.PropertyName.Position, new Vector2((float)nodeData["PosX"], (float)nodeData["PosY"]));
|
||||
|
||||
// Now we set the remaining variables.
|
||||
foreach (KeyValuePair<string, Variant> entry in nodeData)
|
||||
foreach (var (key, value) in nodeData)
|
||||
{
|
||||
string key = entry.Key;
|
||||
if (key == "Filename" || key == "Parent" || key == "PosX" || key == "PosY")
|
||||
{
|
||||
continue;
|
||||
newObject.Set(key, entry.Value);
|
||||
}
|
||||
newObject.Set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,9 +219,9 @@ Let's do an example with the following pseudocode:
|
||||
|
||||
private float _t = 0.0f;
|
||||
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
_t += delta;
|
||||
_t += (float)delta;
|
||||
Position = CubicBezier(p0, p1, p2, p3, _t);
|
||||
}
|
||||
|
||||
@@ -268,9 +268,9 @@ Traversal at constant speed, then, can be done with the following pseudo-code:
|
||||
|
||||
private float _t = 0.0f;
|
||||
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
_t += delta;
|
||||
_t += (float)delta;
|
||||
Position = curve.InterpolateBaked(_t * curve.GetBakedLength(), true);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ Here is example pseudo-code for going from point A to B using interpolation:
|
||||
|
||||
private float _t = 0.0f;
|
||||
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
_t += delta * 0.4f;
|
||||
_t += (float)delta * 0.4f;
|
||||
|
||||
Marker2D a = GetNode<Marker2D>("A");
|
||||
Marker2D b = GetNode<Marker2D>("B");
|
||||
@@ -90,9 +90,9 @@ Using the following pseudocode:
|
||||
|
||||
private float _t = 0.0f;
|
||||
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
_t += delta;
|
||||
_t += (float)delta;
|
||||
|
||||
Marker3D p1 = GetNode<Marker3D>("Position1");
|
||||
Marker3D p2 = GetNode<Marker3D>("Position2");
|
||||
@@ -125,13 +125,13 @@ Interpolation can be used to smooth movement, rotation, etc. Here is an example
|
||||
|
||||
private const float FollowSpeed = 4.0f;
|
||||
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
Vector2 mousePos = GetLocalMousePosition();
|
||||
|
||||
Sprite2D sprite = GetNode<Sprite2D>("Sprite2D");
|
||||
|
||||
sprite.Position = sprite.Position.Lerp(mousePos, delta * FollowSpeed);
|
||||
sprite.Position = sprite.Position.Lerp(mousePos, (float)delta * FollowSpeed);
|
||||
}
|
||||
|
||||
Here is how it looks:
|
||||
|
||||
@@ -170,9 +170,9 @@ Here's how that would be done in code (place the script on a Node2D):
|
||||
|
||||
float rot = 0.5f; // The rotation to apply.
|
||||
Transform2D t = Transform2D.Identity;
|
||||
t.x.x = t.y.y = Mathf.Cos(rot);
|
||||
t.x.y = t.y.x = Mathf.Sin(rot);
|
||||
t.y.x *= -1;
|
||||
t.X.X = t.Y.Y = Mathf.Cos(rot);
|
||||
t.X.Y = t.Y.X = Mathf.Sin(rot);
|
||||
t.Y.X *= -1;
|
||||
Transform = t; // Change the node's transform to what we calculated.
|
||||
|
||||
To calculate the object's rotation from an existing transformation
|
||||
@@ -265,15 +265,15 @@ you to try and reproduce the screenshot without looking at the code!
|
||||
|
||||
Transform2D t = Transform2D.Identity;
|
||||
// Translation
|
||||
t.origin = new Vector2(350, 150);
|
||||
t.Origin = new Vector2(350, 150);
|
||||
// Rotation
|
||||
float rot = -0.5f; // The rotation to apply.
|
||||
t.x.x = t.y.y = Mathf.Cos(rot);
|
||||
t.x.y = t.y.x = Mathf.Sin(rot);
|
||||
t.y.x *= -1;
|
||||
t.X.X = t.Y.Y = Mathf.Cos(rot);
|
||||
t.X.Y = t.Y.X = Mathf.Sin(rot);
|
||||
t.Y.X *= -1;
|
||||
// Scale
|
||||
t.x *= 3;
|
||||
t.y *= 3;
|
||||
t.X *= 3;
|
||||
t.Y *= 3;
|
||||
Transform = t; // Change the node's transform to what we calculated.
|
||||
|
||||
Shearing the transformation matrix (advanced)
|
||||
@@ -435,7 +435,7 @@ This code moves an object 100 units to its own right:
|
||||
.. code-tab:: csharp
|
||||
|
||||
Transform2D t = Transform;
|
||||
t.origin += t.x * 100;
|
||||
t.Origin += t.X * 100;
|
||||
Transform = t;
|
||||
|
||||
For moving in 3D, you would need to replace "x" with "basis.x".
|
||||
@@ -500,11 +500,11 @@ the code we would use:
|
||||
|
||||
// Calculate the child's world space transform
|
||||
// origin = (2, 0) * 100 + (0, 1) * 100 + (100, 200)
|
||||
Vector2 origin = parent.x * child.origin.x + parent.y * child.origin.y + parent.origin;
|
||||
Vector2 origin = parent.X * child.Origin.X + parent.Y * child.Origin.Y + parent.Origin;
|
||||
// basisX = (2, 0) * 0.5 + (0, 1) * 0 = (0.5, 0)
|
||||
Vector2 basisX = parent.x * child.x.x + parent.y * child.x.y;
|
||||
Vector2 basisX = parent.X * child.X.X + parent.Y * child.X.Y;
|
||||
// basisY = (2, 0) * 0 + (0, 1) * 0.5 = (0.5, 0)
|
||||
Vector2 basisY = parent.x * child.y.x + parent.y * child.y.y;
|
||||
Vector2 basisY = parent.X * child.Y.X + parent.Y * child.Y.Y;
|
||||
|
||||
// Change the node's transform to what we calculated.
|
||||
Transform = new Transform2D(basisX, basisY, origin);
|
||||
|
||||
@@ -468,6 +468,6 @@ terrain. Godot provides :ref:`class_fastnoiselite` for this, which supports
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
GD.Print(_noise.GetNoise1d(i));
|
||||
GD.Print(_noise.GetNoise1D(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,8 +97,8 @@ The individual components of the vector can be accessed directly by name.
|
||||
var a = new Vector2(2, 5);
|
||||
// create a vector and assign x and y manually
|
||||
var b = new Vector2();
|
||||
b.x = 3;
|
||||
b.y = 1;
|
||||
b.X = 3;
|
||||
b.Y = 1;
|
||||
|
||||
Adding vectors
|
||||
--------------
|
||||
@@ -345,9 +345,9 @@ The cross product is calculated like this:
|
||||
.. code-tab:: csharp
|
||||
|
||||
var c = new Vector3();
|
||||
c.x = (a.y * b.z) - (a.z * b.y);
|
||||
c.y = (a.z * b.x) - (a.x * b.z);
|
||||
c.z = (a.x * b.y) - (a.y * b.x);
|
||||
c.X = (a.Y * b.Z) - (a.Z * b.Y);
|
||||
c.Y = (a.Z * b.X) - (a.X * b.Z);
|
||||
c.Z = (a.X * b.Y) - (a.Y * b.X);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ NavigationServer2D and a NavigationAgent2D for path movement.
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 currentAgentPosition = GlobalTransform.origin;
|
||||
Vector2 currentAgentPosition = GlobalTransform.Origin;
|
||||
Vector2 nextPathPosition = _navigationAgent.GetNextLocation();
|
||||
|
||||
Vector2 newVelocity = (nextPathPosition - currentAgentPosition).Normalized();
|
||||
|
||||
@@ -185,7 +185,7 @@ a NavigationAgent3D for path movement.
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 currentAgentPosition = GlobalTransform.origin;
|
||||
Vector3 currentAgentPosition = GlobalTransform.Origin;
|
||||
Vector3 nextPathPosition = _navigationAgent.GetNextLocation();
|
||||
|
||||
Vector3 newVelocity = (nextPathPosition - currentAgentPosition).Normalized();
|
||||
|
||||
@@ -51,7 +51,7 @@ Below is all the code we need to make it work. The URL points to an online API m
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class HTTPRequestDemo : CanvasLayer
|
||||
public partial class MyCanvasLayer : CanvasLayer
|
||||
{
|
||||
public override void _Ready()
|
||||
{
|
||||
@@ -59,15 +59,15 @@ Below is all the code we need to make it work. The URL points to an online API m
|
||||
GetNode("Button").Pressed += OnButtonPressed;
|
||||
}
|
||||
|
||||
public void OnButtonPressed()
|
||||
private void OnButtonPressed()
|
||||
{
|
||||
HTTPRequest httpRequest = GetNode<HTTPRequest>("HTTPRequest");
|
||||
HttpRequest httpRequest = GetNode<HttpRequest>("HTTPRequest");
|
||||
httpRequest.Request("http://www.mocky.io/v2/5185415ba171ea3a00704eed");
|
||||
}
|
||||
|
||||
public void OnRequestCompleted(int result, int response_code, string[] headers, byte[] body)
|
||||
private void OnRequestCompleted(long result, long responseCode, string[] headers, byte[] body)
|
||||
{
|
||||
JSONParseResult json = JSON.Parse(Encoding.UTF8.GetString(body));
|
||||
JsonParseResult json = Json.Parse(Encoding.UTF8.GetString(body));
|
||||
GD.Print(json.Result);
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ For example, to set a custom user agent (the HTTP ``user-agent`` header) you cou
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
HTTPRequest httpRequest = GetNode<HTTPRequest>("HTTPRequest");
|
||||
HttpRequest httpRequest = GetNode<HttpRequest>("HTTPRequest");
|
||||
httpRequest.Request("http://www.mocky.io/v2/5185415ba171ea3a00704eed", new string[] { "user-agent: YourCustomUserAgent" });
|
||||
|
||||
Please note that, for SSL/TLS encryption and thus HTTPS URLs to work, you may need to take some steps as described :ref:`here <doc_ssl_certificates>`.
|
||||
@@ -108,20 +108,22 @@ Until now, we have limited ourselves to requesting data from a server. But what
|
||||
|
||||
func _make_post_request(url, data_to_send, use_ssl):
|
||||
# Convert data to json string:
|
||||
var query = JSON.print(data_to_send)
|
||||
var query = JSON.stringify(data_to_send)
|
||||
# Add 'Content-Type' header:
|
||||
var headers = ["Content-Type: application/json"]
|
||||
$HTTPRequest.request(url, headers, use_ssl, HTTPClient.METHOD_POST, query)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public void MakePostRequest(string url, object data_to_send, bool use_ssl)
|
||||
{
|
||||
string query = JSON.Print(data_to_send);
|
||||
HTTPRequest httpRequest = GetNode<HTTPRequest>("HTTPRequest");
|
||||
string[] headers = new string[] { "Content-Type: application/json" };
|
||||
httpRequest.Request(url, headers, use_ssl, HTTPClient.Method.Post, query);
|
||||
}
|
||||
public void MakePostRequest(string url, Variant dataToSend, bool useSsl)
|
||||
{
|
||||
// Convert data to json string:
|
||||
string query = Json.Stringify(dataToSend);
|
||||
// Add 'Content-Type' header:
|
||||
string[] headers = new string[] { "Content-Type: application/json" };
|
||||
HttpRequest httpRequest = GetNode<HttpRequest>("HTTPRequest");
|
||||
httpRequest.Request(url, headers, useSsl, HttpClient.Method.Post, query);
|
||||
}
|
||||
|
||||
Keep in mind that you have to wait for a request to finish before sending another one. Making multiple request at once requires you to have one node per request.
|
||||
A common strategy is to create and delete HTTPRequest nodes at runtime as necessary.
|
||||
|
||||
@@ -76,14 +76,14 @@ efficient for millions of objects, but for a few thousands, GDScript should be f
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class YourClassName : MultiMeshInstance3D
|
||||
public partial class MyMultiMeshInstance3D : MultiMeshInstance3D
|
||||
{
|
||||
public override void _Ready()
|
||||
{
|
||||
// Create the multimesh.
|
||||
Multimesh = new MultiMesh();
|
||||
// Set the format first.
|
||||
Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3d;
|
||||
Multimesh.TransformFormat = MultiMesh.TransformFormatEnum.Transform3D;
|
||||
Multimesh.ColorFormat = MultiMesh.ColorFormatEnum.None;
|
||||
Multimesh.CustomDataFormat = MultiMesh.CustomDataFormatEnum.None;
|
||||
// Then resize (otherwise, changing the format is not allowed)
|
||||
|
||||
@@ -60,9 +60,9 @@ Use the following code in 2D:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
var spaceRid = GetWorld2d().Space;
|
||||
var spaceRid = GetWorld2D().Space;
|
||||
var spaceState = Physics2DServer.SpaceGetDirectState(spaceRid);
|
||||
}
|
||||
|
||||
@@ -76,9 +76,9 @@ Or more directly:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
var spaceState = GetWorld2d().DirectSpaceState;
|
||||
var spaceState = GetWorld2D().DirectSpaceState;
|
||||
}
|
||||
|
||||
And in 3D:
|
||||
@@ -91,9 +91,9 @@ And in 3D:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
var spaceState = GetWorld3d().DirectSpaceState;
|
||||
var spaceState = GetWorld3D().DirectSpaceState;
|
||||
}
|
||||
|
||||
Raycast query
|
||||
@@ -114,11 +114,11 @@ may be used. For example:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
var spaceState = GetWorld2d().DirectSpaceState;
|
||||
var spaceState = GetWorld2D().DirectSpaceState;
|
||||
// use global coordinates, not local to node
|
||||
var query = PhysicsRayQueryParameters2D.create(new Vector2(), new Vector2(50, 100));
|
||||
var query = PhysicsRayQueryParameters2D.Create(Vector2.Zero, new Vector2(50, 100));
|
||||
var result = spaceState.IntersectRay(query);
|
||||
}
|
||||
|
||||
@@ -182,13 +182,13 @@ from a CharacterBody2D or any other collision object node:
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class Body : CharacterBody2D
|
||||
public partial class MyCharacterBody2D : CharacterBody2D
|
||||
{
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
var spaceState = GetWorld2d().DirectSpaceState;
|
||||
var query = PhysicsRayQueryParameters2D.create(globalPosition, enemyPosition);
|
||||
query.Exclude = new Godot.Collections.Array { this };
|
||||
var spaceState = GetWorld2D().DirectSpaceState;
|
||||
var query = PhysicsRayQueryParameters2D.Create(globalPosition, enemyPosition);
|
||||
query.Exclude = new Godot.Collections.Array<Rid> { GetRid() };
|
||||
var result = spaceState.IntersectRay(query);
|
||||
}
|
||||
}
|
||||
@@ -221,13 +221,13 @@ member variable. The array of exceptions can be supplied as the last argument as
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class Body : CharacterBody2D
|
||||
public partial class MyCharacterBody2D : CharacterBody2D
|
||||
{
|
||||
public override void _PhysicsProcess(float delta)
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
var spaceState = GetWorld2d().DirectSpaceState;
|
||||
var query = PhysicsRayQueryParameters2D.create(globalPosition, enemyPosition,
|
||||
CollisionMask, new Godot.Collections.Array { this });
|
||||
var spaceState = GetWorld2D().DirectSpaceState;
|
||||
var query = PhysicsRayQueryParameters2D.Create(globalPosition, enemyPosition,
|
||||
CollisionMask, new Godot.Collections.Array<Rid> { GetRid() });
|
||||
var result = spaceState.IntersectRay(query);
|
||||
}
|
||||
}
|
||||
@@ -270,11 +270,11 @@ To obtain it using a camera, the following code can be used:
|
||||
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
if (@event is InputEventMouseButton eventMouseButton && eventMouseButton.Pressed && eventMouseButton.ButtonIndex == 1)
|
||||
if (@event is InputEventMouseButton eventMouseButton && eventMouseButton.Pressed && eventMouseButton.ButtonIndex == MouseButton.Left)
|
||||
{
|
||||
var camera3d = GetNode<Camera3D>("Camera3D");
|
||||
var from = camera3d.ProjectRayOrigin(eventMouseButton.Position);
|
||||
var to = from + camera3d.ProjectRayNormal(eventMouseButton.Position) * RayLength;
|
||||
var camera3D = GetNode<Camera3D>("Camera3D");
|
||||
var from = camera3D.ProjectRayOrigin(eventMouseButton.Position);
|
||||
var to = from + camera3D.ProjectRayNormal(eventMouseButton.Position) * RayLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,21 +52,21 @@ Here is a custom ``look_at()`` method that will work reliably with rigid bodies:
|
||||
|
||||
using Godot;
|
||||
|
||||
public partial class Body : RigidBody3D
|
||||
public partial class MyRigidBody3D : RigidBody3D
|
||||
{
|
||||
private void LookFollow(PhysicsDirectBodyState state, Transform3D currentTransform, Vector3 targetPosition)
|
||||
{
|
||||
var upDir = new Vector3(0, 1, 0);
|
||||
var curDir = currentTransform.basis.Xform(new Vector3(0, 0, 1));
|
||||
var targetDir = (targetPosition - currentTransform.origin).Normalized();
|
||||
var rotationAngle = Mathf.Acos(curDir.x) - Mathf.Acos(targetDir.x);
|
||||
var curDir = currentTransform.Basis * new Vector3(0, 0, 1);
|
||||
var targetDir = (targetPosition - currentTransform.Origin).Normalized();
|
||||
var rotationAngle = Mathf.Acos(curDir.X) - Mathf.Acos(targetDir.X);
|
||||
|
||||
state.SetAngularVelocity(upDir * (rotationAngle / state.GetStep()));
|
||||
}
|
||||
|
||||
public override void _IntegrateForces(PhysicsDirectBodyState state)
|
||||
{
|
||||
var targetPosition = GetNode<Node3D>("my_target_node3d_node").GetGlobalTransform().origin;
|
||||
var targetPosition = GetNode<Node3D>("MyTargetNode3DNode").GetGlobalTransform().Origin;
|
||||
LookFollow(state, GetGlobalTransform(), targetPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,15 +507,15 @@ Here's the code for the player body:
|
||||
Vector2 velocity = Velocity;
|
||||
|
||||
// Add the gravity.
|
||||
velocity.y += Gravity * (float)delta;
|
||||
velocity.Y += Gravity * (float)delta;
|
||||
|
||||
// Handle jump.
|
||||
if (Input.IsActionJustPressed("jump") && IsOnFloor())
|
||||
velocity.y = JumpSpeed;
|
||||
velocity.Y = JumpSpeed;
|
||||
|
||||
// Get the input direction.
|
||||
Vector2 direction = Input.GetAxis("ui_left", "ui_right");
|
||||
velocity.x = direction * Speed;
|
||||
velocity.X = direction * Speed;
|
||||
|
||||
Velocity = velocity;
|
||||
MoveAndSlide();
|
||||
|
||||
@@ -143,13 +143,13 @@ specifically add :ref:`class_EditorProperty`-based controls.
|
||||
|
||||
public partial class MyInspectorPlugin : EditorInspectorPlugin
|
||||
{
|
||||
public override bool CanHandle(Object @object)
|
||||
public override bool _CanHandle(Variant @object)
|
||||
{
|
||||
// We support all objects in this example.
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ParseProperty(Object @object, int type, string path, int hint, string hintText, int usage)
|
||||
public override bool _ParseProperty(GodotObject @object, int type, string name, int hintType, string hintString, int usageFlags, bool wide)
|
||||
{
|
||||
// We handle properties of type integer.
|
||||
if (type == (int)Variant.Type.Int)
|
||||
|
||||
@@ -90,7 +90,7 @@ Here is how a ``_process()`` function might look for you:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (Engine.IsEditorHint())
|
||||
{
|
||||
@@ -133,9 +133,9 @@ and open a script, and change it to this:
|
||||
[Tool]
|
||||
public partial class MySprite : Sprite2D
|
||||
{
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
Rotation += Mathf.Pi * delta;
|
||||
Rotation += Mathf.Pi * (float)delta;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,15 +162,15 @@ look like this:
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
public override void _Process(float delta)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (Engine.IsEditorHint())
|
||||
{
|
||||
Rotation += Mathf.Pi * delta;
|
||||
Rotation += Mathf.Pi * (float)delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
Rotation -= Mathf.Pi * delta;
|
||||
Rotation -= Mathf.Pi * (float)delta;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,24 +208,23 @@ Add and export a variable speed to the script. The function set_speed after
|
||||
[Tool]
|
||||
public partial class MySprite : Sprite2D
|
||||
{
|
||||
private float speed = 1;
|
||||
private float _speed = 1;
|
||||
|
||||
[Export]
|
||||
public float Speed {
|
||||
get => speed;
|
||||
set => SetSpeed(value);
|
||||
public float Speed
|
||||
{
|
||||
get => _speed;
|
||||
set
|
||||
{
|
||||
// Update speed and reset the rotation.
|
||||
_speed = value;
|
||||
Rotation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Update speed and reset the rotation.
|
||||
private void SetSpeed(float newSpeed)
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
speed = newSpeed;
|
||||
Rotation = 0;
|
||||
}
|
||||
|
||||
public override void _Process(float delta)
|
||||
{
|
||||
Rotation += Mathf.Pi * delta * speed;
|
||||
Rotation += Mathf.Pi * (float)delta * speed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -327,7 +327,7 @@ the performance of C# in Godot — while generally in the same order of magnitud
|
||||
a little faster; the specifics are going to vary according to your use case.
|
||||
GDScript is likely fast enough for most general scripting workloads.
|
||||
|
||||
Most properties of Godot C# objects that are based on ``Godot.Object``
|
||||
Most properties of Godot C# objects that are based on ``GodotObject``
|
||||
(e.g. any ``Node`` like ``Control`` or ``Node3D`` like ``Camera3D``) require native (interop) calls as they talk to
|
||||
Godot's C++ core.
|
||||
Consider assigning values of such properties into a local variable if you need to modify or read them multiple times at
|
||||
|
||||
@@ -74,8 +74,8 @@ Exceptions:
|
||||
=========================== =======================================================
|
||||
GDScript C#
|
||||
=========================== =======================================================
|
||||
``weakref(obj)`` ``Object.WeakRef(obj)``
|
||||
``is_instance_valid(obj)`` ``Object.IsInstanceValid(obj)``
|
||||
``weakref(obj)`` ``GodotObject.WeakRef(obj)``
|
||||
``is_instance_valid(obj)`` ``GodotObject.IsInstanceValid(obj)``
|
||||
=========================== =======================================================
|
||||
|
||||
Tips
|
||||
@@ -177,9 +177,9 @@ Example:
|
||||
Input.IsActionPressed("ui_down")
|
||||
|
||||
However, in some very rare cases this is not enough. For example, you may want
|
||||
to access a member from the base class ``Godot.Object``, like ``Connect``.
|
||||
to access a member from the base class ``GodotObject``, like ``Connect``.
|
||||
For such use cases we provide a static property named ``Singleton`` that returns
|
||||
the singleton instance. The type of this instance is ``Godot.Object``.
|
||||
the singleton instance. The type of this instance is ``GodotObject``.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -586,7 +586,7 @@ An expression ``t`` is awaitable if one of the following holds:
|
||||
.. _ValueTask<TResult>: https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.valuetask-1
|
||||
|
||||
An equivalent of awaiting a signal in GDScript can be achieved with the ``await`` keyword and
|
||||
``Godot.Object.ToSignal``.
|
||||
``GodotObject.ToSignal``.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -332,14 +332,14 @@ Export annotations are also provided for the physics and render layers defined i
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
[Export(PropertyHint.Layers2dPhysics)]
|
||||
private int Layers2dPhysics;
|
||||
[Export(PropertyHint.Layers2dRender)]
|
||||
private int Layers2dRender;
|
||||
[Export(PropertyHint.Layers3dPhysics)]
|
||||
private int layers3dPhysics;
|
||||
[Export(PropertyHint.Layers3dRender)]
|
||||
private int layers3dRender;
|
||||
[Export(PropertyHint.Layers2DPhysics)]
|
||||
private int Layers2DPhysics;
|
||||
[Export(PropertyHint.Layers2DRender)]
|
||||
private int Layers2DRender;
|
||||
[Export(PropertyHint.Layers3DPhysics)]
|
||||
private int layers3DPhysics;
|
||||
[Export(PropertyHint.Layers3DRender)]
|
||||
private int layers3DRender;
|
||||
|
||||
Using bit flags requires some understanding of bitwise operations.
|
||||
If in doubt, use boolean variables instead.
|
||||
|
||||
@@ -92,15 +92,17 @@ Signals support arguments of:
|
||||
* All the `built-in value types <https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/built-in-types-table>`_,
|
||||
except ``decimal``, ``nint`` and ``nuint``
|
||||
* ``string``
|
||||
* Classes derived from :ref:`Godot.Object <class_Object>`
|
||||
* Classes derived from :ref:`GodotObject <class_Object>`
|
||||
* Collections types defined in the ``Godot.Collections`` namespace
|
||||
|
||||
Consequently, any ``Node`` or ``Reference`` will be compatible automatically, but custom data objects will need
|
||||
to inherit from ``Godot.Object`` or one of its subclasses.
|
||||
to inherit from ``GodotObject`` or one of its subclasses.
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
public partial class DataObject : Godot.Object
|
||||
using Godot;
|
||||
|
||||
public partial class DataObject : GodotObject
|
||||
{
|
||||
public string MyFirstString { get; set; }
|
||||
public string MySecondString { get; set; }
|
||||
|
||||
@@ -87,7 +87,7 @@ with :ref:`new() <class_CSharpScript_method_new>`.
|
||||
|
||||
For example, MyCoolNode.cs should contain a class named MyCoolNode.
|
||||
|
||||
The C# class needs to derive a Godot class, for example ``Godot.Object``.
|
||||
The C# class needs to derive a Godot class, for example ``GodotObject``.
|
||||
Otherwise, the same error will occur.
|
||||
|
||||
You also need to check your ``.cs`` file is referenced in the project's
|
||||
@@ -101,8 +101,8 @@ be instantiated with :ref:`GDScript.New() <class_GDScript_method_new>`.
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
GDScript MyGDScript = (GDScript) GD.Load("res://path_to_gd_file.gd");
|
||||
Object myGDScriptNode = (Godot.Object) MyGDScript.New(); // This is a Godot.Object
|
||||
GDScript MyGDScript = (GDScript)GD.Load("res://path_to_gd_file.gd");
|
||||
GodotObject myGDScriptNode = (GodotObject)MyGDScript.New(); // This is a GodotObject
|
||||
|
||||
Here we are using an :ref:`class_Object`, but you can use type conversion like
|
||||
explained in :ref:`doc_c_sharp_features_type_conversion_and_casting`.
|
||||
@@ -126,8 +126,8 @@ Accessing GDScript fields from C#
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As C# is statically typed, accessing GDScript from C# is a bit more
|
||||
convoluted, you will have to use :ref:`Object.Get() <class_Object_method_get>`
|
||||
and :ref:`Object.Set() <class_Object_method_set>`. The first argument is the name of the field you want to access.
|
||||
convoluted, you will have to use :ref:`GodotObject.Get() <class_Object_method_get>`
|
||||
and :ref:`GodotObject.Set() <class_Object_method_set>`. The first argument is the name of the field you want to access.
|
||||
|
||||
.. code-block:: csharp
|
||||
|
||||
@@ -164,7 +164,7 @@ Calling GDScript methods from C#
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To call GDScript methods from C# you'll need to use
|
||||
:ref:`Object.Call() <class_Object_method_call>`. The first argument is the
|
||||
:ref:`GodotObject.Call() <class_Object_method_call>`. The first argument is the
|
||||
name of the method you want to call. The following arguments will be passed
|
||||
to said method.
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ Simply override it in your control. No processing needs to be set.
|
||||
|
||||
public override void _GuiInput(InputEvent @event)
|
||||
{
|
||||
if (@event is InputEventMouseButton mbe && mbe.ButtonIndex == (int)ButtonList.Left && mbe.Pressed)
|
||||
if (@event is InputEventMouseButton mbe && mbe.ButtonIndex == MouseButton.Left && mbe.Pressed)
|
||||
{
|
||||
GD.Print("Left mouse button was pressed!");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user