1
votes

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.

2
I know nothing about godot, but to me it looks like you are trying to "set" the script of the PackedScene, which must be derived of PackedScene. I'm guessing here, but does paddleInstance have a SetScript method? - mxmissile
@mxmissile You may not know Godot but thanks to you I change my idea and... found a workaround! :P I've google setScript on an Instance instead of a PackedScene and found this: github.com/godotengine/godot/issues/31994 He set his scripts on his instances but he also have an issue that can be fixed by the first comment. (The issue is open since 14 days so...) - spMaax
@mxmissile In my opinion, it is a workaround instead of a solution. Atleast it works but I'll prefer to have explainations why it was not working so I'll keep this thread open. - spMaax
I agree, hopefully some godot experts will chime in. - mxmissile
@mxmissile still thanks a lot to you, I mentioned your name when I edited my post - spMaax

2 Answers

0
votes

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);
    }
-1
votes

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);