spMaax
spMaax

Reputation: 395

Godot C# setScript() with derived class

I have a scene that is a Paddle (like the one in PONG game). But my paddles can be either horizontal either vertical.

So I made one parent abstract class "Paddle" that contains the common logic, and two derived classes that extends Paddle "PaddleHorizontal" and "PaddleVertical" where the movements are different (one go up and down, the other go left and right).

At the beginning, I want to create my paddles and attach correct script to each of them but I got this error

" Script inherits from native type 'KinematicBody2D', so it can't be instanced in object of type: 'PackedScene' "

My Main.cs is like so :

using Godot;

public class Main : Node2D
{

    private PackedScene _paddleScene;
    
    public override void _Ready()
    {
        base._Ready();
        _paddleScene = GD.Load<PackedScene>("res://src/scenes/entities/paddle/Paddle.tscn");
        var script = GD.Load<Reference>("res://src/scenes/entities/paddle/PaddleHorizontal.cs");
        _paddleScene.SetScript(script);
        this.InitPaddles();
    }


    private void InitPaddles()
    {
        this.AddPaddle(new Vector2(PaddlePositions.Top.x, PaddlePositions.Top.y));
        this.AddPaddle(new Vector2(PaddlePositions.Bottom.x, PaddlePositions.Bottom.y));
    }

    private void AddPaddle(Vector2 paddlePosition)
    {
        KinematicBody2D paddleInstance = (KinematicBody2D)_paddleScene.Instance();
        paddleInstance.Position = paddlePosition;
        AddChild(paddleInstance);
    }
}
// -- Paddle.cs --
using Godot;

public abstract class Paddle : KinematicBody2D
{
    // common methods & properties

    // the one method that is different and should be override
    public abstract Vector2 GetMovement();
}

// -- PaddleHorizontal.cs --
using Godot;

public class PaddleHorizontal : Paddle
{
    public override Vector2 GetMovement()
    {
        // different from PaddleVertical
    }

}

I guess the error come from the fact that PaddleHorizontal don't extends KinematicBody2D directly but there is a lot of logic that will be in common between the 2 types of Paddle... .. If you guys have a solution or a workaround...

EDIT: A workaround has beed found by mxmissile in comments. Instead of setting the script of PackedScene, he proposed to set it on the Instance. And it works. Check https://github.com/godotengine/godot/issues/31994 for more details and DO READ the first comment in order to avoid another issue.

Upvotes: 2

Views: 1719

Answers (2)

spMaax
spMaax

Reputation: 395

The solution suggested by @mxmissile looks like:

private void AddPaddle(Vector2 paddlePosition)
    {
        KinematicBody2D paddleInstance = (KinematicBody2D)_paddleScene.Instance();
        ulong paddleInstanceId = paddleInstance.GetInstanceId();

        Resource script = GD.Load("res://src/scenes/entities/paddle/PaddleHorizontal.cs");
        paddleInstance.SetScript(script);

        paddleInstance = (KinematicBody2D)GD.InstanceFromId(paddleInstanceId);

        paddleInstance.Position = paddlePosition;
        AddChild(paddleInstance);
    }

Upvotes: 0

hola
hola

Reputation: 3500

The Error

Script inherits from native type 'KinematicBody2D', so it can't be instanced in object of type: 'PackedScene'

This error is caused by setting the script of an Object to a script of a different object hierarchy.

The same error will occur if you, for example, set the script of a Control node to a script that inherits from Node2D.

The Solution

Instead of set_script() of the _paddleScene you should set_script() of the paddleInstance which is the instance of KinematicBody2D.

KinematicBody2D paddleInstance = (KinematicBody2D)_paddleScene.Instance();
paddleInstance.SetScript(thePaddleScript);

Upvotes: -1

Related Questions