I am quite new to SpriteKit, coming from about 4 months playing around with HTML5. Using Mark Wihlberg's HTML5 youtube game tutorials, my programs always constantly updated a player or object's position.
Example if it helps:
function run() {
var loop = function() {
window.requestAnimationFrame(loop, canvas);
update(); //here I would add maybe 3 to a player's x pos and redraw in draw()
draw();
}
window.requestAnimationFrame(loop, canvas);
}
But looking at various SpriteKit tutorials online, many use SKAction to move nodes across the screen.
My question is whether constantly updating a node's position in SpriteKit is unorthodox, or frowned upon, and I should get used to using actions, and why?
No it isn't frowned upon, and it's good to know how to do these things manually. If it's fairly straightforward, regular movement, then SKAction is fine. For more complicated stuff (and SKActions can actually get complicated, with sprites following paths and bezier curves etc), use the Update() function, iterate over your sprites (using enumerateChildNodesWithName or similar) and move them as necessary.
You can combine the 2 - move the sprites in Update() and animate them with an SKAction, or vice-versa.
Bear in mind that you don't call Update(); it is called automatically by the game engine 60 times a second. It gets passed a time, so you can work out exactly how long it has been since Update() was last called (not always 1/60s)
Related
I am building a 3d Billiard game in VR using Unity3d.
I try to display a miniature copy of the billiard "table" (actually a cube), like it is at any given moment.
I tried instantiating the root of the billiard hierarchy, just to find out it will instantiate the original gameObject (runnings its Start() methods) which totally makes sense, just not what i am trying to do.
In practice I have a billiard root, which has all the geometry of the table, and all balls as children, those balls can interact physically.
On button press I try to create a hologram of the table, with all its balls at their position at any given time.
So If a player hits a ball and it moves in the original, it should display the same in the miniature.
I thought it might be possible to translate the ball positions (and table rotation etc) every frame to the miniature. but that seams very un optimal.
var midPoint = (leftHand.transform.position + rightHand.transform.position) / 2;
var miniature = Instantiate(gameObject, midPoint, transform.rotation);
miniature.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f);
this obviously does not work as i described above. It creates a completely new instance of the billiard cube. (this code was run from a script inside the billiard root)
The board itself probably doesn't move, so you can just make holograms and simulate the balls.
Since Unity 2018.2, you can create physics scenes and simulate them manually.
For that problem you would need to:
Stop physics simulations.
Physics.autoSimulation = false;
Create a new scene for independent physics simulation.
var physicsPreviewScene = SceneManager.CreateScene("Physics Preview Scene", sceneParams);
Copy the physics-relevant objects and components to the preview scene.
Many ways to do it, but basically colliders, rigidbodies, and for objects you need visuals for, renderers.
You can use caching to avoid creating these every time.
You can also, in theory, have the simulation on the main scene, but then you need to make kinematic all the stuff you don't want simulated, and there are some gotchas.
Then simulate manually.
Get the PhysicsScene from the preview scene: var physicsScene = physicsPreviewScene.GetPhysicsScene();
Simulate: physicsScene.Simulate();
So yea, short of avoiding the components unrelated to physics in the copies, you can't avoid the duplicates; only mitigate their impact with pooling and/or caching.
Another technique is to use casting (spherecasting, in this case) to make a mockup physics simulation, stepping multiple casts with velocity, acceleration (gravity for example) and Time.fixedDeltaTime, and reacting to intercepts/hits as collisions, with Vector3.Reflector something similar. But this will only give you an approximation of how physics would react, and is not going to be an actual (accurate) physics simulation like having multiple PhysicsScenes will.
I'm trying to use the EventManager and according Events to calculate the distance between objects, and to do something when enough objects are close to the target.
I watched video's on YouTube and searched for examples on Google, but I couldn't find something that looks like what I want. Of course I also watched the explanation videos of Events in general, but I just don't get it. They are all English, which is not my native language, this makes it difficult to understand. So, also sorry for any grammar mistakes. They often talk so fast. So please don't think I'm lazy, I have searched for hours but I just don't get it.
I have one target object, and several enemy objects. This enemy objects have the tag 'Enemy'. The target object can move. I made a coroutine, so when the target moves, the enemies follow, until a distance of 0.5. But from the moment that they reached the distance of 0.5, the enemies won't move anymore. Instead they should also follow the target when they already reached their target position. So to prevent this, I changed the while(Vector3.Distance(transform.position, target.position) > 0.5f) in while 1 > 0, (so just always) and I deleted the part of the code that was about 'after the while loop'. But this is probably not the right way.
So, in short, I want to make an Event that keeps track of when enemies reaches or loses their target position. When three enemies are on their target position, I want to make them blue.
Could anyone show me how I can do this? I don't get it now, but when I see how it works I can use this for more events in the game.
I think You can use trigger collider, just make it bigger then your target object, then do all you want about enemies in methods OnTriggetEnter, OnTriggerStay
As an another technique you can use raycasts. Raycasts will provide you more performance than colliders.
You can locate your raycasts in your target position, in case your raycast hit the enemy then make them blue. For Example;
public LayerMask enemyLayer;
bool isTouch = false;
public bool isTouched(){
if (Physics.Raycast(transform.position,-Vector3.up,1f,enemyLayer)) {
isTouch = true;
return isTouch ;
}
return !isTouch ;
}
In my game I want to call a function every few seconds that creates random objects from an array. Currently I'm moving this objects by SKAction like this:
func createRandmoObject() {
let random = arc4random_uniform(4)
randomObject = randomObjects[random]
randomObject.runAction(SKAction.moveTo(CGPoint(x: randomObject.position.x, y: 0 - randomObject.size.height), duration: 3))
addChild(randomObject)
}
and when the object hits the player it gets removed, then the function gets called again. The problem with this method is I found that the motion of the object isn't always smooth, when the framerate drops for some reason, stutterness occurs. Now I know how to calculate delta time in the update method, but I'm not sure how to apply it to an object when that object keeps changing and not always on the screen, and there are some other objects like it(let's think of them as enemies, and there are another function that creates another enemy) So how can I make those random objects move according to deltatime instead of SKAction?
While you can use SKAction in spritekit projects, if your game is based on physics, you should utilize the update method for all of your sprites movements. SKactions are ok for simple games but if your game involves collisions and random movements, update method is the choice to go for.
There is a remake of the Snake game. The snake's head is a trigger, and the apple uses only a collider. Now OnTriggerEnter() does not work every time - the snake's trigger have to enter several times into apple's body to get it.
There is code used for eating:
void Head.OnTriggerEnter(Collider col)
{
if(col.CompareTag("Food"))
{
gameController.FoodEated();
}
}
public void GameController FoodEated()
{
Destroy(currentFood);
InitializeMeal();
head.GrowUp();
}
void GameController.InitializeMeal()
{
currentFood = (GameObject)Instantiate(foodPrefab, FindFreeSpace(), Quaternion.identity);
}
And there is some kind of magic: The first apple could be eaten normally, but the snake can walk through the second apple a few times before the apple will be activated.
I tried every trigger functions and none of them are working. http://www.youtube.com/watch?v=z_UQi7SGOLw - video of a bug. The snake is going through the apple for 3-4 frame updates. I have another idea for realizing an apple, but a trigger is more appropriate, I think.
If your snake moves too fast and the apple collider is too small than I guess that Unity's engine can sometimes miss collisions.
If on the snake you have a Rigidbody component than you can increase collision detection quality by changing "Collision Detection" from "Discrete" to "Continues" or "Continues Dynamic".
As you can see on the video above, my snake is growing by creating a tailelement at the current transform.position. TailElement starts moving when the distance between last two tail elements is more or equals 1.
I just tried to decrease the radius of the head's collider by 10% and now the tail element is not collider during the movement of snake. Now it works fine.
I am new to Objective-C. I am currently working on a game using Cocos2D and Box2D. My problem is that when 3 objects collide together, the game crashes. Now let me describe my game in details:
In my game I have a main character standing on top of a building. Below the building there's this the road. Enemies pass by the road at various random speeds entering the screen from right and exiting from the left. I have created the enemies as b2_kinematicBodies and set a random velocity for each of them using SetLinearVelocity(). The main character shoots the enemies. The projectile (the object being shot) is a b2_dynamicBody. When the projectile hits the enemies, both the projectile and the enemy are destroyed. During gameplay sometimes an enemy moving at a slow speed is crossed by one which is moving at a higher speed. If a projectile hits the two enemies just at the point when they are overlapping and one is about to pass the other one, the game crashes! Please help me with this.
I have detected collision using b2contactListener class.
One thing I didn't mention before is that I am not creating the enemies as individual distinct bodies. Instead, I am creating it once and making it move and I am calling this method (which creates the enemies and makes them move) inside init as below:
[self schedule:#selector(addRightTarget) interval:2.0];
I believe the issue is that the collisions are calculated before your handler gets any calls. Meaning that when your handler gets called, the bullet has hit 2 objects. So you get 2 call-backs as shown below.
Collision Detected: Bullet + Enemy1
Destroy Enemy1
Destroy Bullet
Collision Detected: Bullet + Enemy2
Destroy Enemy2
Destroy Bullet [CRAAAASH!!! You just tried to delete a non-existent object]
1st: You should not be removing anything except in your step function (as someone mentioned in another answer)
2nd: Pick one of these:
Make your list/array of objects-to-delete be a 'set' or implemented in such a way that duplicates are avoided.
Check for existence of your object in the world
The collision only happens between 2 objects in Box2D. So in your mentioned scenario your will get multiple collision events which could be,
Enemy-1 and Enemy-2
Enemy-1 and Bullet
Enemy-2 and Bullet
So one possible reason of crash could be that you are not expecting (Enemy-1 and Enemy-2) collision and you are handling it like you have collision between (Enemy-1 and Bullet) so you might be casting it into wrong class. Make sure you are checking the kind of class "isKindOf" before casting it.
Also you may want to use Contact Filtering and or assign category masks to your enemies so that they don't collide with each other and only collide with bullet.
But it will be more help full if you tell something about how and where you destroy your bodies (I hope its not inside your Collision Detection Functions) and also if you can share the exception text when your application crash, that will be helpful.
I used a rather cheap workaround. I alternately created enemy fixtures of different sizes(differing by few pixels). So now if i shoot them even when they overlap, the app doesn't crash(because only the bigger object collides and gets destroyed). This serves my purpose. Thanx a llot for your help. I really appreciate it! :)