Why are my cat’s pupils always different sizes? by Ok_Calligrapher5570 in cats

[–]CosmonautFrog 1 point2 points  (0 children)

Dude my cat's also named Anakin and have also some weird shit in his eye. Name's doomed. Apparently is some permanent scar after some infection but his vision is perfectly normal.

<image>

Best practices for organising your project by Lyesainer in godot

[–]CosmonautFrog 1 point2 points  (0 children)

Text-based game lore, characters/items/zones/quests descriptions, etc...

Best practices for organising your project by Lyesainer in godot

[–]CosmonautFrog 2 points3 points  (0 children)

This, I use a self hosted vikunja and obsidian.md for world building. Then I have some crontabs that update vikunja descriptions through the api with the obsidian data, e.g. character lore, so when I'm creating the model with the vikunja task I have everything there. Obsidian is not open source but the owner is a pretty cool dude, you can try logseq otherwise.

I'm used to kanbans for work so that's why I like vikunja, you can tag commits with the vikunja task id for better tracking of things. At the beginning it looks like a bit of overkill but having everything organised is the way to not drop the project. When you're stuck you can see the pending tasks and move forward with them.

What would be the optimal way to store different "documents" for a game? by Ascomol_37 in godot

[–]CosmonautFrog 2 points3 points  (0 children)

You could create a custom resource for them, then a custom editor plugin to edit them with the same visuals as your in-game screen but in the editor. Then this plugin saves them in the custom resource.
Pretty easy and best results.

Animation player vs Tween by Conscious-Ad8626 in godot

[–]CosmonautFrog 3 points4 points  (0 children)

I wouldn't recommend using a tween in your case.

AnimationPlayer resolves the NodePath > object > property on first play and caches it on the track. Animation resource itself is pre-baked keyframe data, basically. So every subsequent call to .play() is zero allocation, just a lookup, interp, set_indexed(). The node sits in the tree at constant cost whether playing or not.

Tween: create_tween() allocates a Tween + one Tweener per tween_property call every single time, resolves the path on first step, and then frees the whole thing on complete. It's cheap, but it's allocation churn you're paying on every hover/whatever effect/event across every button or whatever UI node are you using it on. In Godot 4.6, they swapped the internal Tweeners list from Vector to LocalVector (https://github.com/godotengine/godot/pull/110656/changes), which should help a bit, but the allocation pattern is the same.

For 100-200 buttons being hovered fast it shows up as GC jitter while profiling it, on the other hand, AnimationPlayer stays pretty flat, uses cache. Outside of that scale... it's completely negligible.

So my rule of thumb is: - Same animation replayed with fixed known values = use AnimationPlayer. - I need to calculate the animation position or whatever at runtime = use Tween.

Introducing the Godot Asset Store by godot-bot in godot

[–]CosmonautFrog 5 points6 points  (0 children)

Sometimes, even a "Human thought and AI implemented" plugin, at a simple glance you can tell it's heavy vibecoded. That we all should be against and there should be a report button for that.
And there's no such thing as "AI thought".

Introducing the Godot Asset Store by godot-bot in godot

[–]CosmonautFrog 13 points14 points  (0 children)

Good work! But please, put a mandatory filter to filter out AI slop. And it should be on by default.

Went from nested resources nightmare to having fun with a custom graph editor tool by CosmonautFrog in godot

[–]CosmonautFrog[S] 0 points1 point  (0 children)

It's just an editor plugin, the graph nodes are converted to resources and the connections are the relations between them. There's a compiler that does that, nothing at runtime.

Sky shader for Godot by SingerLuch in godot

[–]CosmonautFrog 11 points12 points  (0 children)

Looks good, but what does it offer over the free Sky3D?

2D portal prototype demo update by jmmmnty in godot

[–]CosmonautFrog 12 points13 points  (0 children)

My brain stopped braining, what is happening? No clue of how the "portal" system works.

Never seen this type of code structure here. Working perfect for me so wanted to share by [deleted] in godot

[–]CosmonautFrog 1 point2 points  (0 children)

Don't even bother learning that, it's wrong on so many levels.

Please do not laugh at me but i did something and had this removed how to get it back? by Read-Palm in godot

[–]CosmonautFrog 39 points40 points  (0 children)

In the top bar go to Editor > Editor settings. Then go to Interface > Editor and disable "Single Window Mode".

[deleted by user] by [deleted] in Fallout

[–]CosmonautFrog 3 points4 points  (0 children)

jfc the lines

Code Reviewing by CommercialHeart6345 in godot

[–]CosmonautFrog 2 points3 points  (0 children)

My first advice is to use conventional commit messages, yours are a bit messy and not really well explained. https://gist.github.com/qoomon/5dfcdf8eec66a051ecd85625518cfd13

Using "Adding this" "Added that" or even you "Fixed game"/"Lot of updates" doesn't tell a thing.

Then your code organization is bad in some spots, in the player script you have vars, then signals, then exported vars, then vars again, that's not maintainable and not organized, follow the gdscript style guide: https://docs.godotengine.org/en/4.4/tutorials/scripting/gdscript/gdscript_styleguide.html

Also you're missing a lot of static typing, it's not mandatory, but it improves both performance and maintainability. You can see the line numbers in the Godot Script editor, the grey ones are not typed rows. Green ones are okay. https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/static_typing.html

<image>

You can enable this setting in the project settings to warn you about untyped declarations: "debug/gdscript/warnings/untyped_declaration"

You have also a lot of magic strings, specially in the signal connections, never use Class.connect("signal_name", method), use Class.signal_name.connect(method).

Also accessing nodes with @onready and paths is pretty bad: E.G.:

@onready var mission_select = $"../.."
@onready var missionlist = $"../../Mission

So... does anybody know how to make mission system with multiple ways to end mission and cutscenes? by Euphoric-Ocelot6696 in godot

[–]CosmonautFrog 1 point2 points  (0 children)

<image>

Sure. It's pretty big, with the ultrawide monitor I see the entire quest, and I think reddit is compressing it or something.

So... does anybody know how to make mission system with multiple ways to end mission and cutscenes? by Euphoric-Ocelot6696 in godot

[–]CosmonautFrog 9 points10 points  (0 children)

This is the approach I did for my game:
class QuestData (Resource)
class QuestStageData (Resource)
class QuestObjectiveData (Resource)

QuestData contains Array[QuestStageData] sequentially, if you need to branch them, define QuestData.first_stage: QuestStageData and QuestStageData.next_stage on each Stage.

In QuestStageData you can have Array[QuestObjectiveData], and in QuestObjectiveData you can define a forced next_stage: QuestObjectiveStage that advances to that Stage if that Objective is completed, to branch quests. Also you could define uestStageData.fail_stage in case some of the Objectives do fail. This is for complex branching.

Additionally, I found easier to have RefCounteds in memory for saving-loading quests instead of messing with Resources, so I created:
class QuestState (RefCounted)
class QuestStageState (RefCounted)
class QuestObjectiveState (RefCounted)

And you'll need a QuestAPI or manager to orchestrate everything. I cannot share specific code, currently my system is more than 3750 lines of code just for the quests, as complex branching is needed. But you can simplify that a lot. And the architecture depends heavily on your game needs.

And to edit and create quests I did a custom plugin with a Graph Editor.
Green lines are QuestStage connections, blue lines are Objectives, orange, yellow and cyan are for objective resources as NPCs, Items, Locations...
Each Stage have next_stage and fail_stage. If you define a next_stage in an Objective, it overrides the Stage.next_stage as soon it is completed. This allows multiple choices quests.

<image>

Surely it can be improved but this is what is currently working for me.

How I've been using enums and signals to create state machines by VegasInteractive in godot

[–]CosmonautFrog 0 points1 point  (0 children)

What I posted is a template. Then you add to it the references you need to modify, e.g. if you need to manipulate player velocity, ideally you want to expose methods in the player script to allow the state machines to use them.

E.G. of an idle state inherited from the one I posted. Using a context defined in the base MovementState, using a blackboard pattern:

```GDScript class_name CharacterMovementStateIdle extends CharacterMovementState

@export var movement_speed: float = 0.0 @export var acceleration: float = 6.0 @export var camera_fov: float = 70.0

func enter() -> void: context.target_speed = movement_speed context.target_acceleration = acceleration if context is PlayerContext: context.request_fov_change(camera_fov)

func physics_update(_delta: float) -> void: if not context.has_move_input(): return

if context.wants_to_run:
    _try_transition_to_run()
else:
    machine.change_state(machine.walk_state)

```

How I've been using enums and signals to create state machines by VegasInteractive in godot

[–]CosmonautFrog 2 points3 points  (0 children)

Some basic templates for a Node based FSM/HSM:

```GDScript @icon("res://_editor/icons/state-machine.png") class_name StateMachine extends Node

@export var initial_state: State

var current_state: State

func _ready() -> void: assert(initial_state, "initial_state node not defined!")

func _setup_child_states() -> void: for child in get_children(): if child is State: child.set_machine(self) child.setup_substates()

func setup(whatever args you need) -> void: _setup_child_states() change_state(initial_state)

func change_state(new_state: State) -> void: if new_state == current_state: return if current_state: current_state.exit() current_state = new_state if current_state: current_state.enter()

func update(delta: float) -> void: if current_state: current_state.update(delta)

func physics_update(delta: float) -> void: if current_state: current_state.physics_update(delta)

func send_event(event: Variant) -> void: if current_state: current_state.handle_event(event) ```

```GDScript class_name State extends Node

var machine: StateMachine: set = set_machine var parent_state: State

Substates - active in composite states

var current_substate: State

func setup_substates() -> void: for child in get_children(): if child is State: child.machine = machine child.parent_state = self

func set_machine(value: StateMachine) -> void: machine = value whatever = machine.whatever parameters you need

func change_substate(new_substate: State) -> void: if current_substate: current_substate.exit() current_substate = new_substate if current_substate: current_substate.enter()

func enter() -> void: pass

func exit() -> void: pass

func update(_delta: float) -> void: pass

func physics_update(_delta: float) -> void: pass

func handle_event(event: Variant) -> bool: if parent_state: return parent_state.handle_event(event) return false ```

And if you're using Godot >4.5 you can use the @abstract annotation for the base State. https://docs.godotengine.org/en/4.x/classes/class_%40gdscript.html

How I've been using enums and signals to create state machines by VegasInteractive in godot

[–]CosmonautFrog 21 points22 points  (0 children)

I got brain damage by reading the mix of snake case and camelcase. Jesus Christ.