ywmaa / Advanced-Movement-System-Godot

This project is a template for creating advanced Third/First Person movement in GODOT
MIT License
432 stars 37 forks source link

Lock system #33

Closed TheFunnyBrain closed 1 year ago

TheFunnyBrain commented 1 year ago

For the company I work for, we make use of a lock system, to restrict player movement whilst using UI, or in a cutscene.

The way we found best, is a privately settable Dictionary of strings.

Locks.AddLock("TalkingToCompanionA")

Locks.RemoveLock("TalkingToCompanionA")

Input can then check locks.count/locks.length etc with a property or method, e.g.

if(!Locks.IsLocked)
{
    //accept input
}

This one is something I'd be happy to work on, but only if it's useful. :)

ywmaa commented 1 year ago

Yeah that is a very useful feature, if you do it, please do it as a Node, and name it something like

LockComponent Or TargetingSystem

I advise adding additional stuff for it like : Object Targeting (useful for games with Pickup system) Enemy Targeting. Allies Targeting.

And then export a variable in this TargetingComponent

@export var TargetingRaycast :Raycast3D

Use this variable or something similar for detecting the above stuff. So by this, we should have an advanced targeting system, while being optional and customizable.

What do you think ?

ywmaa commented 1 year ago

Another ideas that could help :

The Targeting/Locking system can be made as follows so we can apply it to the examples above.

First Node :

TargetingComponent, will be added to the player, handles all targeting functions, and has a Placeholder functions aka "Virtual Functions" That can be used to do specific actions in other components.

And this component also got 5 signals, I will just write example code :

extends Node
class_name TargetingComponent

@export var detection_raycast : RayCast3D

@export var detectable_object_group : String = "detectable_object" # we can use the node group feature in Godot
@export var detectable_player_group : String = "player" # I am calling any Enemy/AI/Ally a player 

var detected_object : Node3D
var detected_player : Node3D

signal object_detected(object: Node3D)
signal enemy_detected(object: Node3D)
signal ally_detected(object: Node3D)
signal player_detected(object: Node3D)
signal detected(object: Node3D) #this activates for all

func _process(delta):
    if detection_raycast.is_colliding():
        if detected_player == detection_raycast.get_collider() or detected_object == detection_raycast.get_collider():
            return
        if detection_raycast.get_collider().is_in_group(detectable_object_group):
            detected_object = detection_raycast.get_collider()
            detected.emit(detected_object)
            object_detected.emit(detected_object)
            return
        if detection_raycast.get_collider().is_in_group(detectable_player_group):
            detected_player = detection_raycast.get_collider()
            detected.emit(detected_player)
            player_detected.emit(detected_player)
            if false: #Needs a Specific check to know if this player is enemy or not
                enemy_detected.emit(detected_player)
            if false: #Needs a Specific check to know if this player is ally or not
                ally_detected.emit(detected_player)
            return

And so on in the process functions, we make if conditions to emit specific signals.

In Godot Signals can be connected to any function, so you can connect signal from this node to a function in another code that handles what the player will do when there is a lockable/intractable object/player.

Edit : I wrote all of the code from my memory, and on my mobile, so expect it to need fixes in Godot Engine.

Edit 2 : I just realized that I never did a check in the code to not emit the signal unless the interactable object changes, now this code will keep emitting the signal every frame when the player is looking to the object.

Edit 3 : I noticed some typos in the code, so some adjustmenst, still it may need testing.

Edit 4 : expanded the code

ywmaa commented 1 year ago

Perhaps we need also to have a Team System, Not an actual Team System but I mean something to classify objects and players, useful for most games.

something like :

enum {NATURAL_OBJECT=0}
var team_id : int = 0

so we can assign a number for the team_id to seperate players/AI in teams.

and leave at 0 for natural object that can be picked up, or non-violent AI.

For now I am not sure if the team system should be in the TargetingComponent, or have a seperate Component.

ywmaa commented 1 year ago

Just Pushed a new commit

it contains a CombatComponent, so we can use this one for Damaging the Player Health, and Assigning Teams

also the damage function can be used with Natural Objects to register a physics hit or something

so the CombatComponent is made for a lot not only players.

I will work on the Firearms example to also showcase the usage of CombatComponent.

for now you can look at its code.

ywmaa commented 1 year ago

@TheFunnyBrain

Lol, I JUST REALIZED I UNDERSTOOD Lock system wrong, resulting me working on another features, LOL.

but now I understand your game LOCK System.

still it will help.

in my game the lock system was using one Variable called in_game, your idea is much better.

Please add this system, as it will help a lot of games that will use this Template, plus, it may help turn this Template into a whole Demo, because it will make Menus work flawlessly with this template.

ywmaa commented 1 year ago

@TheFunnyBrain

I made this PlayerController Script : https://github.com/ywmaa/Advanced-Movement-System-Godot/commit/c3ef313d57a67dd08ff472ef30bd0424fce5fb75#diff-2642a77dfb50662044ce692d38d2067a604e56aafbe6372b1dce31a50d6c576f

So you can add the system you meant here.

TheFunnyBrain commented 1 year ago

Awesome! :) Thank you :)

I have added the feature to PlayerGamePlayComponent in a local branch, but it's no trouble to throw it over :)

I'm just trying to work out how best to get the locks connected to the player, but as an optional component. Initially it's as a preloaded .gd script, so I'm going to try and turn it into a proper node that can be there or not. :)

It's strange migrating from Unity, where I'd do something like a null check or even trygetcomponent at launch. :) That said, I am really getting a kick out of the friendliness of GDScripts - is so simple with handling things like dictionaries!

I am also looking to try and make it support signals, so that we could for example have debug UI.

TheFunnyBrain commented 1 year ago

I've rewritten it in nodes, added a nullcheck etc, so hopefully it'll do the trick. :)

Would I be okay to add a pause key (e.g. the 'p' key) to test the system works? :) It's doing absolutely nothing presently, which is exactly as intended - so I guess the next test is to add a lock, see what happens.

ywmaa commented 1 year ago

Would I be okay to add a pause key (e.g. the 'p' key) to test the system works?

Yes, no problem, actually you should consider adding a way so the users of the template know that this feature exists.

for me the Pause Key "p" is good enough, and I may add a simple Pause screen for it in the future.

TheFunnyBrain commented 1 year ago

That sounds perfect! :) I've added the 'p' key in for now, and hopefully I can add a small UI element to tell the user what's happening. :)

I did notice an amusing side effect of my implementation - the player walks, or runs indefinitely whilst locked! I'll resolve that now, I think it might be that I need to switch the character to an idle state. :)

I'm guessing physics might also be a consideration, but I won't get ahead of myself for now. Quite frankly, I'm astonished any of my GDScript is working on day 2, it is a nice feeling.

ywmaa commented 1 year ago

I saw your scripts, and you are a good user of GD script.

Keep going 👍

TheFunnyBrain commented 1 year ago

Thank you :) That's really encouraging to hear, it's a nice jump, and I'm having fun. I have a perpetual fear of wading into someone's project, and busting things through lack of knowledge.

I've made a pull request now, and I can fix any issues, add anything, change things etc. :)