|
|
|
|
Reply From: |
avencherus |
One method would be to add each new instance as reference into an array.
Inside the scene that you’re instancing, you would write some functions that manipulate their data, like their position, stats, whatever.
Then from the point you wish to send a command to all of them you would loop through the array and call that function.
for unit in units:
unit.retreat()
If you want specific commands to specific things, you’ll have to create the logic you desire for making selections and such. But algorithms like that are not specific to Godot.
Another option you could employ is grouping: http://docs.godotengine.org/en/stable/tutorials/step_by_step/scripting_continued.html#groups
Selecting units, grouping and giving orders to the groups in godot could be just add_to_group (selected units) and get_tree.call_group to give orders as avencherus said.
Using groups means you will have to be careful and organized with adding, removing and naming groups.
But that depends on the design, you can have something more complex.
Apart ffrom grouping, to control armies for a RTS I can recommend you to design states and behaviors, units may need to avoid themselves, get better paths, avoid obstacles and react (alone or in group) without direct intervention from the player (a simple AI).
This worked great (array method) and everything seem to work as what I wanted. I just prototype your idea out and that now I can control each individually object via hard coded - just to check if it will work or not. Soon I will turn this prototype into a more dynamic program. Below is the snippet that is working.
Autoload global.gd
extends Node
var arrayBlue = Array();
func _ready():
print("Global ready!");
func arrayBlue_add(addName):
arrayBlue.push_back(addName);
func arrayBlue_size():
return arrayBlue.size();
Main scene
extends Node
var continueAdd = false;
func _ready():
set_process_input(true)
func _input(event):
# if user left clicks
if(event.type == InputEvent.MOUSE_BUTTON):
if(event.button_index == 1):
if (continueAdd == true):
global.arrayBlue_add(global.arrayBlue_size() + 1);
var player = preload( "res://scenes/spawns.tscn" ).instance()
get_node(".").add_child(player)
print(str("Getting player #", global.arrayBlue_size(), "!"));
print(global.arrayBlue);
continueAdd = false;
func _on_ContinueAdd_Timer_timeout():
continueAdd = true;
Spawns
extends KinematicBody2D
var blueInstanceId = global.arrayBlue_size();
var x_pos = 200;
var y_pos = 200;
func _ready():
set_pos(Vector2(x_pos, y_pos));
print("#", blueInstanceId, " - ", "X: ", x_pos, " | Y: ", y_pos);
set_process(true);
func _process(delta):
if(Input.is_action_pressed("ui_left")):
if (blueInstanceId == 3):
set_pos(Vector2(get_pos().x - 100 * delta, get_pos().y));
Now whenever I press ‘left’ button, only the third instance will be moved away. I will be checking out the grouping method and see if it will be a better alternative for my simple test game.
By the way, is there any disadvantages of using one over another or is it just a matter of preference - array and grouping.
inTech | 2016-10-25 15:44
More preference/design, also groups are like arrays managed by the tree.
You can design groups to have many functions (a single node in groups “player”,“infantry”,“current selection”,“stand ground”).
Direct references to an array may feel more “normal” than using groups, for programmers in particular.
What I don’t know is if adding&removing from an array is optimized like the built in group system.
Like individual unit add and remove from selection.
ps: Other methods that can be used are node reparenting to a “selection” node but not sure if is clean for a RTS because you can select&deselect all the time.
Seems like a fine start to me.
I’m not sure about what groups do on the back end, and I haven’t had any need yet to use them for my projects. So I can’t comment on it.
When it comes to performance, you’ll have to measure that case by case. A lot of it is going to be mainly reliant on Godot’s implementations. You’re not going to be doing your own memory management and such from GDScript.
So what I can say about arrays, is that when they’re used in certain ways where the memory is aligned, they can out perform many types of traditional algorithms, even though it is brute force. It’s because of things like a cache prefetchers in the hardware.
The slowest thing these days are the connections between the cache and the RAM. A prefetch can look at an array and make an assumption that you’re going to want what’s next, and start predicatively caching it. So you’re a lot less likely to get what’s called a cache miss, where it has to go the long journey back to RAM to get the data.
When an array gets used and handled this way, it’s almost as if it’s all hanging out in the level 2 cache. Since it’s constantly loading in new data before it’s requested.
Whereas something like a very fast linked list algorithm will be a list of pointers to objects scattered through memory. There is no way for the prefetcher to predict ahead of time where the next data element is going to come from. Even though on paper it touches waaaaaay less items in memory to find the data, it loses out because of the vast amount of time the CPU and cache may have to wait for it’s data to arrive.
Maybe that’s a bit off topic, but hopefully that helps, because it’s a very deep topic, and one can only touch on it from here.
The only responsible prescription one can give for performance is to never assume, and always measure.
avencherus | 2016-10-25 19:53