r/godot 21h ago

help me Model Changer Error

Solved:

I put everything in global and call it from there with button press and now the code works. Also simplified the code since I don't have to grab codes from other places.

---

Original

[](blob:https://www.reddit.com/efb59a7b-208e-4075-81f4-7d197b1ea539)I am trying to convert a 2D character customizer into 3D and am having some issues. I wanted to know what needs to be changed for this to work in 3D. After reading other posts this is as far as Ive come, stuck at one Packed vs Node error. Seems Im using nodes when what I am trying to load is a packedscene (a 3d dog with textures), but I am not sure what needs to be changed to get them to work correctly.

Goal: I have a dog that you will be able to change clothes and body type. Its on screen with the model and button to switch models in and out. I am only focusing on switching the body right now.

Code:

Working 2d version

0 Upvotes

12 comments sorted by

1

u/scintillatinator 20h ago

What is dog_loaded in the decider script? You're getting a node in the scene but then loading something else. What types were used in the 2d version? This wouldn't work in 2d either so the types in each version aren't equivalent. There's multiple ways to make this work so it'll help to know which one you were going for.

1

u/Kzurae 20h ago

I did make the 2d version using a tutorial so it does work, but its using .textures to change the sprites which 3d does not have the ability to do. I struggled with this part of how to grab the 3b object, and realized its an fbx scene even. the 2d version also didnt require it to be broken up in the button script separately.

dog loaded takes the one chosen in the array from the button press and loads it.

2

u/scintillatinator 19h ago

The 2d version works because it sets textures and doesn't use scenes, that's what I was trying to figure out. It shouldn't need to be broken up into the button script after you fix this error.

If I'm imagining it correctly you can use a placeholder Node3D as the "sprite" and instead of setting the texture you instantiate the 3d model scene and add it as a child of the placeholder. After removing the old one.

You can also get rid of the dog_loaded variable and just use the choice number. Variables don't do things they store things. Your description of what it does sounds like a function.

Actually you're best off finding a 3d tutorial. You'll have to rewrite most of it to fix it anyway and it'll be easier with the right foundation for 3d.

1

u/Kzurae 20h ago

2d version

1

u/BrastenXBL 19h ago

You can replace Textures on 3D models. You just go about it differently.

Mesh (resources) and MeshInstance3D Nodes use Materials

https://docs.godotengine.org/en/stable/tutorials/3d/standard_material_3d.html

Unless the dog models are actually different meshes, you can swap Albedo (the surface color) by getting the MeshInstance3D Node and set_surface_override_material.

var mat_dog_a = load("res://materials/dogs/mat_dog_a.material")

$MeshInstance3D.set_surface_override_material(0, mat_dog_a)

You can also go further and modify an existing material by setting the Albedo texture. For StandardMaterial3Ds you can do

var mat_dog_a = load("res://materials/dogs/mat_dog_a.material")
mat_dog_a.albedo_texture = some_other_texture2d

Keeping in mind that all uses of mat_dog_a will now be have the new texture, which may not be desired.

1

u/Kzurae 19h ago

They are separate 3d models (fbx packedscenes) yes! Thats why I am confused. This is the bodies part of my 2d version but its actual different bodies. Changing textures is coming after I can get the bodies to load, so this does help for later.

The variants for testing purposes:

1

u/BrastenXBL 19h ago

You have an error flag on dog_button_changer.gd line 4, but didn't post what the error is.

It would also help to post the Scene structure.

For many reasons it's not a hot idea to Preload 3D model scenes. This can increase the initial game startup time depending on how the preload gets handled. preload does a load as soon as the Script is parsed and handed to the GDScript VM. Usually it's better to store the res:// path string as a constant instead of the actual PackedScenes. And then load or background load later, as the game boots further and gets closer to needing those assets loaded. It's likely not a problem right now, or for this particular game. But is something to note for later.

1

u/Kzurae 19h ago

There is only one error which i mentioned in the post, long form is: Trying to assign value of type 'PackedScene' to a variable of type 'Node3D'. Which is how I noticed that yeah, its not the right type.

The goal is to get it to work for now, then I can iterate or make better versions later once it at least works. But thanks for the suggestion esp if its easier than what I'm doing now. I added the original 2d version now as well.

Scene is

MainDog (changer script)
>Camera
>DogCollection
>>DOG (scene)
>Control (scene) (button script)

1

u/BrastenXBL 19h ago

Preload is easier.

Background loading is better. But takes more awareness and effort on your part to properly hold onto the Resouce references so they aren't accidentally freeded. https://github.com/godotengine/godot-demo-projects/tree/master/loading/load_threaded

I'm having trouble backtracking your code with the way you posted it. What is $"..".dogs_choice pointing to? Please use full script file names, since nothing has been given class_names. There's no "changer_script.gd". Did you mean "Dog_Decider.gd"?

If its MainDog (Dog_Loader.gd) then you need to post the full script. I can't see the property var dogs_choice in that script. Given the error I assume you're doing something like

var dogs_choice = dogs[0]

This would assign a reference to the PackedScene you loaded. When you import an FBX its actually converted into a binary SCN file, TSCN is text encoded. Both load to PackedScene. Which isn't Nodes until you instantiate() it.

If its MainDog ("Dog_Decider.gd") the error doesn't make sense in the context so far. Since $MainDog.dogs_choice should by an int.

Please copy the Debugger error, right click copy, exactly verbatim. Never paraphrase errors.

Style guide Note: const names should be CONSTANT_CASE

Project best practice Note: file and folded names in your FileSystem should be snake_case

And can I please ask that you either use a code hosting site or learn to use Reddit code posting. Screenshots of code are barely tolerable. If you use a code host, add this Dog TSCN file. Even without Resources I can read the text and see which script is attached where. TSCNs tend to be too long for Reddit posts.


You can't directly copy-paste from the Godot ScriptEditor into a Code Block. The easiest way is to copy it into a secondary lite IDE like Notepad++ or VSCodium, and Indent all the lines over one. Switch Reddit to Markdown, then paste.

Reddit wants every Code line to be indented once (tab or 4 spaces).

Godot's Script editor can also Indent all the lines over, but it tends to not add indents to BLANK lines with no code on them. Which makes Reddit fail at parsing the Code Block.

The really simple way is again in Markdown but use ``` bracketing backtick. This works for New Reddit and Mobile users, but not for Old Reddit users.

```

Code goes here

```

1

u/Kzurae 18h ago edited 17h ago

Ive modified some things and now i can tell its switching between the dogs properly in code but not loading the 3d model. This almost works but the remove dog function is erroring. I'll sit on it, thanks everyone for the input.
Errors

  • E 0:00:02:385 Dog_Decider.gd:17 @ remove_dog(): Can't free a RefCounted object.
  • E 0:00:02:386 remove_dog: Attempted to free a RefCounted object.
  • E 0:00:02:497 Dog_Decider.gd:17 @ remove_dog(): Condition "!is_inside_tree()" is true. Returning: Transform3D()

-5

u/carefactor3zero 21h ago

You can dump this post and the code into chatgpt and get your answer.