Skip to content

coinbump/UnityToGodot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 

Repository files navigation

UnityToGodot

This repository is meant to keep track of what needs to be done to port a Unity codebase to Godot. It is a WORK IN PROGRESS, and will include my findings and any tools/scripts that are useful in the process.

Porting Steps

Unity Concept Godot Replacement Notes
.meta files Remove all .meta files On MacOS, search for .meta and delete. TODO: create a script for this
[SerializeField] [Export]
Auto serialized public fields [Export] Unity auto-synthesizes public fields. Godot does not. Add [Export] to fields you want to serialize.
[SerializeField] List<Vector3> vectors = new(); [Export] public Vector3[] vectors; Export list for serialization
void Awake() public override void _Ready() Unity calls Awake with random order. Godot calls _Ready in order from child to parent to root.
void Start() No exact equivalent Requires custom solution
void Update() using Time.deltaTime for time step public override void _Process(double delta) using delta parameter for time step
void FixedUpdate() using Time.fixedDeltaTime for time step public override void _PhysicsProcess(double delta) using delta parameter for time step
.zero .Zero
implicit conversion between Vector3 and Vector2 Not supported
[Range(0, 20)] [Export(PropertyHint.Range, "0,20,")]
radians = degrees * Mathf.Deg2Rad radians = Mathf.DegToRad(degrees)
degrees = radians * Mathf.Rad2Deg degrees = Mathf.RadToDeg(radians)
Mathf.PI Mathf.Pi Pi (π) constant
Random.InitState(seed) GD.Seed(seed) Initialize random number generator seed
Random.Range(min, max) GD.Randi() % valueRangeSize + minValue Generate random integer
Random.value GD.Randf() Generate random float between 0-1.0f (inclusive)
Color.red Colors.Red Color constants
gameObject.name node.Name In Godot, the names of sibling nodes must be unique from each other. If you change the node name to an existing name it will be automatically renamed (From in-code documentation).
rigidbody.isKinematic physicsBody2D is CharacterBody2D Test: Is kinematic
new Vector2(spriteRenderer.size.x, spriteRenderer.size.y) sprite2D.Texture.GetSize() Get sprite size in pixels
spriteRenderer.color sprite2D.Modulate Get sprite modulate color
spriteRenderer.flipX = true sprite2D.FlipH = true Flip sprite horizontally
spriteRenderer.flipY = true sprite2D.FlipV = true Flip sprite vertically
[Tooltip("tooltip")] No equivalent Not available in C# for Godot. Documentation ("Currently only @GDScript has annotations")
.x .X Vector types
.y .Y Vector types
.up .Up Vector types
.down .Down Vector types
.z .Z Vector3
.forward .Forward Vector3
.normalized .Normalized() Vector types
.magnitude .Length() Vector types
GameObject Node See Porting Problems section for more information
Vector2Int Vector2I
Vector3Int Vector3I
DestroyObject(gameObject) QueueFree() Destroy node in scene
transform.childCount GetChildCount() Get count of children for MonoBehaviour (Unity) vs Node (Godot)
transform.localEulerAngles = new Vector3(0, 0, -newAngle.Degrees) RotationDegrees = newAngle.Degrees 2D rotation
transform.parent GetParent() Get node parent
foreach (Transform childTransform in transform) foreach (var child in GetChildren()) Iterate through children for MonoBehaviour (Unity) vs Node (Godot)
OnTriggerEnter2D Code Sample
OnCollisionEnter2D Code Sample
AudioListener AudioListener2D, AudioListener3D Audio
AudioSource AudioStreamPlayer, AudioStreamPlayer2D, AudioStreamPlayer3D Audio
GlobalLight2D, Light2D CanvasModulate, DirectionalLight2D, PointLight2D, LightOccluder2D 2D Lighting
using UnityEditor; Remove all
using UnityEngine.XXX; Remove all
using UnityEngine; using Godot;
Debug.Log GD.Print
Input Actions InputEvent/InputMap Godot Documentation: InputEvent
Rigidbody2D as child component RigidBody2D as parent node or CharacterBody2D as parent node In Godot, the roles of ownership between a node and its rigidbody are reversed
Unity packages Remove all Remove installed Unity packages from the Assets/plugins folder
n/a partial class requirement Because of the way Godot builds C# code, you'll get a build error for classes that subclass a built-in Godot class and don't use partial. Documentation: Godot Interop With Source Generators
n/a Godot type name conflicts If you have any types in your code that conflict with built in Godot types, use namespace to wrap them.
Prefab Scene Godot Documentation: Where Are My Prefabs

Godot Limitations

Summary Problem Statement Solution
No visual scene while running In Unity, you can view a scene visually in the editor. In Godot, you can see the list of nodes in the Scene tree while running in the Remote tab, but you can't view the objects visually in the scene editor.

Porting Problems

Summary Problem Statement Solution
Components vs Nodes In Unity, each GameObject can have multiple Components (via MonoBehaviour). In Godot, each Node is the component. Create a separate node for each behavior, instead of a separate component. This requires rethinking logic around finding the target for a particular behavior. Instead of using gameObject directly, in Godot you might operate on the parent node, for example.
No transform in Node In Unity, every GameObject has a transform. In Godot, Node doesn't have a transform, so you're forced to choose if your code subclasses Node2D or Node3D. Duplicated code for Node2D vs Node3D or utility structs that can operate on either a Node2D or Node3D. Example: Transform tool that can set the position of either node type.
2D Physics Sprite2D not working After adding RigidBody2D, sprite doesn't move or interact with physics. Sprite must be child node of RigidBody2D. This is different than Unity, where the RigidBody component is attached to the GameObject along with the sprite renderer.
Strange scaling for physics sprite When adding RigidBody2D to a Sprite2D you might see strange scaling when the game is running. Check all Node2D transforms in parent nodes of the sprite and make sure they are (1, 1). Documentation: https://stackoverflow.com/questions/77590667/godot-physics-resizing-my-sprites-at-runtime
C# 10 support Godot supports C# 10, Unity does not. This means writing code that works for both engines is more difficult if you want to use the newest language features. No solution

Code Samples

Godot Code Samples

Detect 2D Collisions

var collision = characterBody2D.MoveAndCollide(velocity);

or

characterBody2D.Velocity = velocity;
characterBody2D.MoveAndSlide();
for (int i = 0; i < characterBody2D.GetSlideCollisionCount(); i++)
{
    var slideCollision = characterBody2D.GetSlideCollision(i);
    GD.Print("Collided with: ", (slideCollision.GetCollider() as Node).Name);
}

Detect Mouse Click on Node

  • Set the Pickable property to true on your CharacterBody2D
  • Make sure your CharacterBody2D has a child collision node
  • In the Signals panel for your character body node, connect the input_event to your script
public void _on_character_body_2d_input_event(Node viewport, InputEvent @event, int shape_idx)
{
    if (@event is Godot.InputEventMouseButton)
    {
        if (@event.IsPressed())
        {
            GD.Print("Mouse Press");
        }
        else
        {
            GD.Print("Mouse Release");
        }
    }
}

Troubleshooting

Problem Possible Solutions Notes
Trouble with VSCode and Intellisense ?Reinstall .NET SDK? Unverified. Still Investigating

TODO: Will add more notes as I port more code

Releases

No releases published

Packages

No packages published