I am having an issue with the zPosition undesirably changing when a node is touched.
I can't give a simple code example because currently my scene and rendering is quite complex. Everything is drawn correctly when the scene is presented and for the most part besides as described below it works.
So the issue explained - we have a base image node correctly rendered below a tower node (tower defence game). The tower is circular and the base image is square, so the corners stick out. If you manage to touch the corners, for some reason beyond my knowledge, the zPosition changes to above the tower.
There is no particular code on touches to change any zPositions of anything in the game.
I know this is a shot in the dark, but any insight would be great and much appreciated.
If your view's ignoreSiblingOrder property is set, you should set the zPosition of each node, appropriately, to ensure that they are drawn in the correct order.
From Apple's documentation...
The default value (of SKView's ignoreSiblingOrder property) is NO,
which means that when multiple nodes share the same z position, those
nodes are sorted and rendered in a deterministic order. Parents are
rendered before their children, and siblings are rendered from eldest
to youngest. When this property is set to YES, the position of the
nodes in the tree is ignored when determining the rendering order.
The rendering order of nodes at the same z position is arbitrary and may change every time a new frame is rendered [emphasis added].
Related
I think I understand how Hierarchy (lowest sibling rendered last, appears on top), Layers (can assign to layers - which have their own order), Sort (sort of a sub-layer), Child (rendered in front of parent), and z-axis (higher numbers go in front) control how each object appears in front or behind other objects. But -consistently - I have a TextMeshPro object that ends up behind its parent sprite (a square). Adjusting all of the 4 parameters mentioned here has no effect on the render - the text remains behind the sprite. Moreover, the sprite seems to NOT follow sorting rules (placing it high in the hierarchy makes it appear in front, whereas lower in the hierarchy makes it behind even the parent). What am I missing?
I've tried manipulating all the parameters but the text simply will not go in front of the sprite.
I am trying to understand how Unity decides what to draw first in a 2D game. I could just give everything an order in layer, but I have so many objects that it would be so much easier if it was just drawing in the order of the hierarchy. I could write a script that gives every object its index, but I also want to see it in editor.
So the question is, is there an option that I can check so that it uses the order in the hierarchy window as the default sorting order?
From your last screenshot I could see you are using SpriteRenderer.
The short answer to the question "is there an option that I can check so that it uses the order in the hierarchy window as the default sorting order?" would be no, there isn't by default*.
Sprite renderers calculates which object is in front of others in one of two ways:
By using the distance to the camera, this will draw the objects closest to the camera on top of the rest of the objects in that same order in layer, as per the docs:
Sprite Sort Point
This property is only available when the Sprite Renderer’s Draw Mode is set to Simple.
In a 2D project, the Main Camera is set to Orthographic Projection mode by default. In this mode, Unity renders Sprites in the order of their their distance to the camera, along the direction of the Camera’s view.
If you want to keep everything on the same sorting layer/order in layer you can change the order in which the objects appear by moving one of the two objects further away from the camera (this is probably further down the z axis). For example if your Cashew is on z = 0, and you place the walnut on z = 1 then the cashew will be drawn on top of the walnut. If Cashew is on z=0 and the walnut is on z = -1 then the walnut will be draw on top (Since negative is closer to the camera). If both of the objects are on z - 0 they are both equally as far away from the camera, so it becomes a coin toss for which object gets drawn in front, as it does not take into account the hierarchy.
The second way the order can be changed is by creating different sorting layers, and adjusting the order in layer in the sprite renderer component. But you already figured that out.
*However, that doesn't mean it cannot be done, technically...
If you feel adventurous there is nothing stopping you from making an editor script that automates setting the order in layer for you based on the position in the hierarchy. This script would loop through all the objects in your hierarchy, grab the index of the object in the hierarchy, and assign the index to the Order in Layer.
I don't think Unity has such feature (https://docs.unity3d.com/Manual/2DSorting.html).
Usually you shall define some Sorting Layers:
far background
background
foreground
and assign Sprite Renderer of each sprite to one of Sorting Layers
I am working on a basic racing game using Apple's SceneKit and am running into issues simulating a car. Using the SCNPhysicsVehicle behavior, I am able to properly set up the car and drive it using the documented methods.
However, I am unable to get the car's position. It seems logical that the SCNPhysicsVehicle would move the SCNNodes that contain the chassis and the wheels as the car moves but the SCNNodes remain at their original position and orientation. Strangely enough, the chassis' SCNPhysicsBody's velocity remains accurate throughout the simulation so I can assume that the car's position is based off of the SCNPhysicsBody and not the SCNNode. Unfortunately, there is no documented method that I have found to get an SCNPhysicsBody's position.
Getting a car's position should be trivial and is essential to create a racing game but I can't seem to find any way of getting it. Any thoughts or suggestions would be appreciated.
Scene Kit automatically updates the position of the node that owns an SCNPhysicsBody based on the physics simulation, so SCNNode.position is the right property to look for.
The catch is that there are actually two versions of that node in play. The one you typically access is called the "model" node. It reflects the target values for properties you set, even if you set those properties through an animation. The presentationNode reflects the state of the node currently being rendered — if an animation is in progress, the node's properties have intermediate values, not the target values of the animation.
Actions, physics, constraints, and any scene graph changes you make inside update/render loop methods directly target the "presentation" version of your scene graph. So, to read node properties that have been set by the physics simulation, get the presentationNode for the node you're interested in (the node that owns the vehicle's chassisBody physics body), then read the presentation node's position (or other properties).
I have the same problem with my player node.
I move it with applyForce (to manage collision detection).
But when i check node position after some movement, the node position has not move (presentation node is the actual position as rickster write in his answer)
I manage to update the scnNode.position with renderer loop
You have to set position of your node with the presentationNode position.
node.position = node.presentationNode.position
Set this into renderer(_: updateAtTime) and your node position will sync with any animation you made to the physicsBody
I've started implementing an iOS game with swift and SpriteKit.
I have an object called "bubble" which basically is an SKSpriteNode (with zPosition=0, with image) that have a child (which is an SKCropNode of a person image cropped to a circle, with zPozition=1).
That's ok if one bubble covers another bubble as a whole, but somehow it seems like the bubbles are partially covered with the person images.
a demo picture is provided: (my final output should be that bubble1 will be on top of child-of-bubble-2)
Maybe the problem is that SpriteKit ignores child ordering and just set any node with a zPozition to be in it's correct place? That is - all the bubbles are drawn first because they have zPosition=0 and then all the bubble-children are drawn, as they all have zPosition=1?
If this is the case, what can I do to make sure all bubble parts are drawn together (and other bubbles can cover that bubble, I don't care) knowing that I have a dynamic amount of bubbles?
well according to this SO answer, indeed all the zPosition values are calculated before drawing.
I ended up creating a counter for bubbles, adding 1 every time a bubble has been added, and assinging the counter value as its zPosition.
And inside the bubbles, I made sure every child has a zPosition in the range (0, 1)
If you need to draw things in a precise order, then I suggest you to read section Understanding the Drawing Order for a Node Tree of SKNode Apple's documentation. Everything is correctly describe in details.
Hi im pretty new to programming and I have encountered a small issue. I am creating a simple game which has a score label. However, the score label is covered whenever a downward scrolling obstacle passes. I would like for the score label to not be covered by the obstacles.Is there a way i can change the sprite hierarchy in spritekit? Thanks
I would recommend creating a node for the static stuff that should be fixed on screen (like a game HUD). Then you set this node's zPosition to be higher then the game play node (where all game objects are placed and manipulated).
This makes it also easier implementing a camera or moving the game play node if needed without the score label or any other fixed hud element moving as well.
So you will have something like this :
SKNode *hudNode = [SKNode node];
hudNode.zPosition = 1000;
[hudNode addChild:scoreLabel];
SKNode *gamePlayNode = [SKNode node];
gamePlayNode.zPosition = 0; // Not mandatory as it defaults to 0 but I put this here for clarification
[self addChild:hudNode]; // self is your scene instance
[self addChild:gamePlayNode];
You can change the zPosition property of your label node, by making it 100 it will be above all other nodes (default value is 0.0):
labelNode.zPosition = 100;
Nodes are drawn in the order they are added to the scene (or parent node). You can change the order in which nodes are drawn by setting their zPosition property.
From Apple's documentation...
...The z position is the node’s height relative to its parent node, much as a node’s position
property represents its x and y position relative to parent’s
position. So you use the z position to place a node above or below the
parent’s position.
When you take z positions into account, here is how the node tree is
rendered:
Each node’s global z position is calculated.
Nodes are drawn in order from smallest z value to largest z value.
If two nodes share the same z value, ancestors are rendered first, and siblings are rendered in child order.
You can also use zPosition to optimize rendering performance...
...it might be better if Sprite Kit could gather all of the nodes that share the same texture and drawing mode and and draw them with a single drawing pass. To enable these sorts of optimizations, you set the view’s ignoresSiblingOrder property to YES.