SpriteKit: Hashing a Recycled SKShapeNode - ios

I'm trying to detect collisions between nodes that have not collided before in my SpriteKit game by calling node.hash and storing new nodes in a set. I'm seeing that after some time, new nodes have the same hash as nodes that I had previously called node.removeFromParent() on.
I'm guessing that because I am removing from parent and recreating very similar nodes over and over, SK is automatically recycling some nodes.
How can I get a truly unique hash from nodes in SpriteKit?
Please let me know if further clarification is needed. I feel like posting my code wouldn't be too relevant to this post.
Furthermore, I am not able to reproduce this issue when I'm debugging with my phone attached to xcode but I have added logging that shows node.hash not being unique for newly created nodes. Anyone know why recycling behavior would be different with my phone connected to Xcode?

I think you may be misunderstanding what a hash is and does.
A hash is not necessarily a unique value. It is a one way function of some kind (not necessarily cryptographic) that takes arbitrary data and produces a value. If the same data is hashed more than one time, it will produce the same hash value, not a different value.
Working against you, however, is the fact that the .hash value is not a cryptographic hash (which is somewhat computationally intensive). The quality of a hash function, cryptographic or not, is based on how frequently there are hash collisions. A hash collision occurs when two different values produce the same hash.
Cryptographic hashing functions are selected, amongst other things, based on a low hash collision rate. The .hash function may have a high collision rate, even if your data is different, depending on your particular data.
A far better solution is to add a property to your nodes that can be easily checked:
class MyNodeClass: SkShapeNode {
var hasCollided = false // Publicly accessible property
}
I do notice that in other comments you say, "I am interesting in finding the proper hash." I'd strongly recommend against this approach since, again, hash functions will definitely carry a computational load. The better the function, the higher that load.
If what you are really looking for is a unique identifier for each node (rather than a collision tracker) then why not implement an internal property that is initialized from the initializer based on a class value that simply produces a unique, incrementing ID?

SKNode is using NSObject's default implementation of hash which just returns a memory address
import Foundation
import SpriteKit
let node = SKNode()
let hex = String(node.hash, radix:16)
let addr = unsafeAddressOf(node)
print(hex) // 7f9a21d080a0
print(addr) // 0x00007f9a21d080a0
So basically, once a memory location is reused, the hash value is not going to be unique. Likely the difference between behaviour in debugging is due to compiler optimisations.
To get a unique hash you'll need to override the hash method of your SKNode and have it return something that is actually unique. A simple strategy would be to assign each node an id property at creation something like
class MyNode : SKNode {
var uid:Int
init(uid:Int) {
self.uid = uid
super.init()
}
override var hash:Int { get {
return self.uid
}}
required init(coder aDecoder: NSCoder) {
fatalError("not implemented, required to compile")
}
}
If you start a counter off at Int.min and increment it towards Int.max you'll have to create 18,446,744,073,709,551,613 nodes before you run out of uniqueness.

If I understand you correctly, you seem to be trying to determine if you’re colliding with new objects. What you could do is simply create a custom SKShapeNode object with the boolean property. This would remove the need to deal with colliding hashes, and instead provide a foolproof method of checking if the node has been dealt with.
class CustomShapeNode: SKShapeNode {
var hasAlreadyCollided = false
// Any required overidden methods
}

Related

PyDrake CollisionFilterManager Not Applying Filter

I have a system that consists of a robotic manipulator and an object. I want to evaluate signed distances between all collision geometries in the system while excluding collisions between the fingertips of the end-effector and the convex geometries that make up the collision geometry of the object. However, when I use the CollisionFilterManager to try to apply the relevant exclusions, my code still computes signed distances between fingertips and object geometries when calling ComputeSignedDistancePairClosestPoints() much later on downstream.
I have a container class that has the plant and its SceneGraph as attributes. When initializing this class, I try to filter the collisions. Here are the relevant parts of the code:
class SimplifiedClass:
def __init__(self, ...):
# initializing plant, contexts, and query object port
self.diagram = function_generating_diagram_with_plant(...)
self.plant = self.diagram.GetSubsystemByName("plant")
self.scene_graph = self.diagram.GetSubsystemByName("scene_graph")
_diag_context = self.diagram.CreateDefaultContext()
self.plant_context = self.plant.GetMyMutableContextFromRoot(_diag_context)
self.sg_context = self.scene_graph.GetMyMutableContextFromRoot(_diag_context)
self.qo_port = self.scene_graph.get_query_output_port()
# applying filters
cfm = self.scene_graph.collision_filter_manager()
inspector = self.query_object.inspector()
fingertip_geoms = []
obj_collision_geoms = []
gids = inspector.GetAllGeometryIds()
for g in gids:
name = inspector.GetName(g)
# if name.endswith("ds_collision") or name.endswith("collision_1"):
if name.endswith("tip_collision_1") and "algr" in name:
fingertip_geoms.append(g)
elif name.startswith("obj_collision"):
obj_collision_geoms.append(g)
ftip_set = GeometrySet(fingertip_geoms)
obj_set = GeometrySet(obj_collision_geoms)
cfm.Apply(
CollisionFilterDeclaration()
.ExcludeBetween(ftip_set, obj_set)
.ExcludeWithin(obj_set)
)
#property
def query_object(self):
return self.qo_port.Eval(self.sg_context)
def function_that_computes_signed_distances(self, ...):
# this function calls ComputeSignedDistancePairClosestPoints(), which
# computes signed distances even between filtered geometry pairs
I've confirmed that the correct geometry IDs are being retrieved during initialization (at least the names are correct), but if I do a simple test where I see how many SignedDistancePairs are returned from calling ComputeSignedDistancePairClosestPoints() before and after the attempt to apply the filter, the same number of signed distance pairs are returned, which implies the filter had no effect even immediately after declaring it. I also confirm the geometries that should be filtered are not by examining the names associated with signed distance pairs during my downstream function call.
Is there an obvious bug in my code? If not, where else could the bug be located besides here?
The problem is an age-old problem: model vs context.
In short, SceneGraph stores an interior model so you can construct as you go. When you create a context a copy of that model is placed in the context. That copy is independent. If you continue to modify SceneGraph's model, you'll only observe a change in future contexts you allocate.
In your code above, you've already allocated a context. You acquire a collision filter manager using cfm = self.scene_graph.collision_filter_manager(). This is the SceneGraph model version. You want the other one where you get the manager from the context: self.scene_graph.collision_filter_manager(self.sg_context) as documented here.
Alternatively, you can modify the collision filters before you allocate a context. Or throw out the old context and reallocate. All are viable choices.

What is the best way of generating a lot of instances of a class in Dart performance-wise?

All in the title. I'm looking for the best performance possible when creating a lot of instances (~100 000).
It all depends on details. This is an optimization question, and optimizations always depend on the details, because those details determine which changes can be done without affecting the final result.
Top of the list: Don't do it. Takes zero extra space! If you can represent the information in some other way than an object instance (a single integer would be awesome!) then consider doing that. (Such an integer could be a pointer into a large string or byte array which holds the actual data in a shared and optimized way. Whether that makes sense depends on what the data are.)
Second: Don't do all of them if you don't need to. If any of the objects are equivalent, reuse those instead of creating new objects. That's effectively caching, which means it can keep those objects alive longer than necessary if you don't actively try to avoid it, and if the majority of objects are actually new, the cache might take up more space than the rest of the objects would. That depends on the next item...
Third: Make the class small, which means as few fields as possible. Avoid anything that isn't necessary, or which can be computed when needed (unless it's definitely going to be needed and is expensive to compute, the usual trade-offs).
Fourth: Share any substructure which can (and likely will) be shared among multiple objects. That's a variant of items 2 and 3 applied to sub-components.
Don't do:
class MyClass {
int left;
int top;
int right;
int bottom;
}
if
class MyClass {
Point _topLeft;
Point _bottomRight;
int get left => _topLeft.x;
int get top => _topLeft.y;
int get right => _bottomRight.x;
int get bottom => _bottomRight.y;
}
would allow you to share the same topLeft point or bottomRight among multiple instances, even if all the MyClass instances have unique combinations. Again, depends on the sharing percentage, size of the extra objects, and the cost of caching, which depends on the underlying data.
Other than that, just do it. Creating 100K objects doesn't sound that bad if the objects themselves are simple. If each contains, say, a large JSON object and a 1K string, you may want to consider other options.

How to handle Lua memory/references if my userdata is used as a key elsewhere?

I am indexing some table with my userdata (lets call it Turret) - to store some associated variables like bullets and armor.
I need to manage Turret's lifecycle by being able to set it to nil, subsequently allowing Lua to GC it. I'm worried that I lose all control over the object's memory when I use it as a key elsewhere.
Sample Code:
local turretStorage = {}
-- Bunch of turrets are created and added, lets look at the one below
local turret = load.newTurret(15) -- Create a Turret userdata
turretStorage[turret] = {}
turretStorage[turret].bullets = 100
turretStorage[turret].decal = "skulls.png"
-- Some time passes, we're done with the turret object
turretStorage[turret] = nil
turret = nil
My concern is the indexing of turretStorage by turret userdata. Does turret userdata ever get GC'd? If setting the turretStorage[..] to nil removes the key references - could you please show me supporting documents?
Should I somehow nil the key in the turretStorage table? If so, how would I do it?
If the key is used as a reference of the original variable and can't be removed, then I am stuck and need help, or refactoring.
If the key in this example is just userdata's memory location used as a unique index - then I'm completely in the clear; but - the answered question would have references to support this ;)
An object in Lua is only considered garbage and marked for collection when there are no references to it inside Lua. Using a value as a key in a table counts as a reference.
Consider also using weak tables if they fit your design.

How to identify SpriteKit node by id or number?

In my scene world I have "blocks" with category ("blockCategory") and an object colliding with these blocks. I wish to identify which specific block (using block index) the object has touched.
The only way I found is giving a name to the blocks, but I already use :
block.name = blockOfType ..
In order to identify the block types. I also found I could use node.userData to place custom data, but it seems to be with a large overhead to use dictionary. Is there a simpler way?

How best to decouple objects in, for example, a 'snake' game

I am creating a snake game in C#/XNA for fun but it's a good opportunity to practice some good object design.
Snake Object
There's a snake object which is essentially a linked list, each node being a vector with X & Y co-ordinates which relate to the map.
Also a few properties such as whether the snake has just eaten (in which case, the last body node is not removed for this update), direction that the snake is moving in etc.
Map Object
The map (game area) holds its contents inside 2D array of integers - using an array of primitives to store the map should keep down memory consumption and be quicker (and easier) to iterate over than an array of vectors.
Contents are defined inside an enum {Empty, Wall, Snake, Food} which are then stored inside the array at the relevant co-ordinates.
A reference is also kept to the snake object within the map so that every call to render, loops through the nodes that make up the snake and render it into the correct position on the map.
Question!!
My question is... is this coupling too tight, in which case are there any suggestions (i.e. observer pattern) or is it okay for this situation...
I've tried to think of a way to decouple the snake from needing to know the co-ordinate system being used by the map, but can't think of a way to make it work and keep the positions each nodes relative to each-other.
Any answers appreciated, cheers!
"is this coupling too tight?" No, it isn't.
In this case, the code required to decouple it is bigger, more complicated, and harder to maintain than the code required to simply implement it with the coupling.
Furthermore, there is always going to be some level of coupling required. Coupling to "a coordinate system" is usually one of them in game development. You could, in fact, rigorously decouple your map and snake objects (again, not worth the effort), but they still need to share a common coordinate system in order to communicate.
I think you are already hinted the answer yourself. The current design of making the Snake referenced in the map is tight coupling between the two.
You might want to consider creating another Interface such as MapListener that the Snake will implement. The Snake will listen to the event that maps will publish and react to it, effectively making the Snake the subscriber for the event that the Map is publishing (such as rendering in the correct position as you say). You could even have ArrayList of Listeners so you have the flexibility of adding new Object in the map that would react to the event in the maps as your game becoming more complex.
For reference on creating the Listener, see this SO question How can I code a custom listener. While this example is listening for finishing download, you should be able to see the pattern in the accepted answer for creating custom listener for your game. Let me know if you need any clarification and I will adapt the code to fit your case.
Here is simple first thought structure:
create an interface called MapContainable
//marker interface
interface MapContainable {
}
interface MapMovable extends MapContainable {
///map movement specific contract methods here
}
class Snake implements MapMovable {
.....
}
This way, your map need not know if there are concrete objects called snake, food etc. You snake object need not know the existence of a Map. A snake just moves!

Resources