How to remove all nodes with a specific name spritekit - swift

Is there a simple way to remove all spritekit nodes with a given name. I am making a project that has waves of spaceships and at a certain score, I want the old spaceships to dissappear so that new, harder spaceships replace them. I gave all of the level one spaceships the same name and was wondering if there was a way that I could remove them all based on this factor.

It depends on how you created the spaceships. If you made them all with the same name maybe you can try:
self.enumerateChildNodesWithName("spaceShip"){
spaceShip.removeFromParent()
}
//or try
for child in self.children{
if child.name == "spaceShip"{
child.removeFromParent
}
}

Related

Unity scaling an object when duplicating (not wanted)

I'm making a mining game, where you have a rest area, and a mine area (all of this stuff works well) but when I "hire a new worker" the main miner clones, and is put in the starting area. When I clone the main miner, the cloned miner's size goes to 6k something something.
public void moreMiners(){
if (gm.Diamonds >= gm.mmcost){
gm.Diamonds -= gm.mmcost;
GameObject newplr = GameObject.Instantiate(plr);
newplr.gameObject.transform.localPosition = plr.transform.position;
}
}
duplicating code ^
help is appreciated
Make sure that "plr" reference is the original Prefab from your assets folder and not from your scene, then what you can do is to check your original prefab inside your assets folder and see if the scale is the one that you want to have.
Also when you Instantiate an object you can parse the position too as a parameter like this:
GameObject.Instantiate(plr,position);

Unity: Trying to load and run an fbx animation

I am trying to load an animation from an fbx file and have it play on a GameObject:
TestObject.AddComponent<Animation>();
animation_handler = TestObject.GetComponent<Animation>();
walking_anim = Resources.Load("fbx_anims/walking_anim_test", typeof(AnimationClip)) as AnimationClip;
if(walking_anim == null)
{
Debug.Log("walking anim not found");
}
walking_anim.legacy = true;
animation_handler.AddClip(walking_anim, "walking");
animation_handler.wrapMode = WrapMode.Loop;
In the game loop, I tried using this:
if (Input.GetKeyDown(KeyCode.W))
{
if (!(animation_handler.IsPlaying("walking")))
{
animation_handler.clip = walking_anim;
animation_handler.Play("walking");
}
}
It doesnt give any errors, yet it doesn't work either. Anything I'm missing?
EDIT: For clarification: The model stays in the default T-Pose, after pressing 'W'. After inserting Debug.Logs at different points, I can confirm that the Play function is getting called only once, after which IsPlaying always returns true. Yet the "playing" animation causes no visual changes in the model (yes, the bone names are the same).
You don't want to use the Animation component, it is an old legacy component that has been replaced by the much improved Animator component. There are a lot of good posts on the Internet on how to use it - no need to repeat it here. The important steps are:
Add the Animator (not Animation) component to the model.
Create an "Animator Controller" in your project and add the clips (like the "walking_anim"). Here you can have a lot of different clips and tell Unity how to interpolate between them by using different parameters.
Add the "Animator Controller" to your "Animator" component.
Add an "avatar" of your model (usually created when the model is imported).
By code alter the parameters of the Animator Controller to tell it which animation clips to play.
It may look like a lot of steps, but it is not so hard and you will quickly have a walking, running, jumping creature on your screen. Good luck!

High CPU usage SceneKit

When I display a node from a COLLADA file, the CPU usage goes up to 100%+.
Link to pic
I am not using the simulator, I am using my actual phone. The model consists of about 80k vertices.
Here is how I load the model:
// Add Character
func addModel(name:String)
{
// Load COLLADA Model
if let myScene = SCNScene(named: "Assets.scnassets/"+name+"/"+name+".dae")
{
// Recurse through all the child nodes in the model and add to modelNode
for node in myScene.rootNode.childNodes as [SCNNode]
{
modelNode.addChildNode(node)
}
// Add modelNode to scene
self.rootNode.addChildNode(modelNode)
}
else
{
print("Error loading model: "+name)
}
}
The model is 122MB and can be found here:
Link to zip
I have tried with different models, but CPU goes nuts on each one of them. They are all about 122MB (which sounds large) and about 80k vertices.
Update
Tried to lower the poly count in SceneKit. In blender i lowered vertices from 20k to 5k (see here). But when I load the model in SceneKit the poly count is still the same (68k). I also tried converting the model and the animations to .SCN instead. This resulted in much lower file size, however the same poly count and CPU usage.
Pictures of showStatistics
I think what I need to do is lower the poly count, not so much the file size (don't think that would harm though).
Update 2
Now I actually managed to lower the poly count to about 48k. Still lagging. If I remove the texture, the CPU is much lower.
I'm not positive this is your usage issue but your method of loading your file could be streamlined.
You don't need to add each individual node from your DAE file to your modelNode. Ideally, your Collada model will have its own root node with a unique name. Just add that node to modelNode and all its children will be included. In the sample below, lyso_ribbons is the name of the root node in the DAE as well as the name of the DAE file itself.
guard let lysoRibbons = SCNScene(named: "lyso_ribbons")
else { print("Couldn't find molecule in dictionary (lysoRibbons)")
return }
let modelNode = lysoRibbons.rootNode.childNodeWithName("lyso_ribbons", recursively: false)!
All the child nodes that tagged along with the root are still accessible by name via childNodeWithName. You can inspect your DAE's scene graph in the editor window, just click on it in the navigator panel and, within the editor, click on the small square far lower left of the editor window. If, for some reason, your DAE model is lacking a root node you can create one here and move all other nodes into it. Also see: Transform and Rotate in Scenekit
You can create nodes in the left-hand panel of the editor window displaying your DAE file. Click on the + sign, far lower left of the panel. Drag that <untitled> object to the top, just under "Scene graph". Then group-select all other nodes and drag them into this new object. Give the new object a unique name. You'll notice the new node has a grayed icon meaning it has no geometry of its own.
A better way to do this is to plan ahead when creating your Collada model using nulls, with unique names, to organize your geometry nodes into meaningful sub-groups. The nulls will then be imported as parent nodes of those sub-groups. Place all nodes into one master null that will become the root for your model.

Adding videos to Unity3d

We are developing a game about driving awareness.
The problem is we need to show videos to the user if he makes any mistakes after completing driving. For example, if he makes two mistakes we need to show two videos at the end of the game.
Can you help with this. I don't have any idea.
#solus already gave you an answer, regarding "how to play a (pre-registered) video from your application". However, from what I've understood, you are asking about saving (and visualize) a kind of replay for the "wrong" actions, performed by the player. This is not an easy task, and I don't think that you can receive an exaustive answer, but only some advices. I will try to give you my own ones.
First of all, you should "capture" the position of the player's car, in various time periods.
As an example, you could read player's car position every 0.2 seconds, and save it into a structure (example: a List).
Then, you would implement some logic to detect the "wrong" actions (crashes, speeding...They obviously depend on your game) and save a reference to the pair ["mistake", "relevant portion of the list containg car's positions for that event"].
Now, you have all what you need to recreate a replay of the action: that is, making the car "driving alone", by reading the previously saved positions (that will act as waypoints for generating the route).
Obviously, you also have to deal with the camera's position and rotation: just leave it attached to the car (as the normal "in-game" action), or modify it during time to catch the more interesting angulations, as the AAA racing games do (this will make the overall task more difficult, of course).
Unity will import a video as a MovieTexture. It will be converted to the native Theora/Vorbis (Ogg) format. (Use ffmpeg2theora if import fails.)
Simply apply it as you would any texture. You could use a plane or a flat cube. You should adjust its localScale to the aspect ratio of your video (movie.width/(float)movie.height).
Put the attached audioclip in an AudioSource. Then call movie.Play() and audio.Play().
You could also load the video from a local file path or the web (in the correct format).
var movie = new WWW(#"file://C:\videos\myvideo.ogv").movie;
...
if(movie.isReadyToPlay)
{
renderer.material.mainTexture = movie;
audio.clip = movie.audioClip;
movie.Play();
audio.clip.Play();
}
Use MovieTexture, but do not forget to install QuickTime, you need it to import movie clip (.mov file for example).

Remove part of Gameobject name

Is it possible to remove a part of a name given to a GameObject? For instance:
Im instantiating gameobjects for the use of bullets. I give them the name of the player shooting the bullet. So if a player's name is "Ben", his bullets are called Ben's bullet.
gameObject.name = playerName + "'s bullet";
Now I'm trying to use this name to know wich person gives the finishing blow to an other player. And to do this I want find the player object with the same name as the bullet, and update his kill count. So I want to remove the "'s bullet" part from the bullets name.
So long story short: Is it possible to remove a part of a name given to a GameObject?
Hope that this is clear enough en help is really appreciated. Thanks in advance!
Edit: This is the part where the name has to change:
if(other.gameObject.tag == "bullet"){
var colBullet = other.transform.name;
playerHealth = playerHealth - 5;
if(playerHealth <= 0){
onDie();
//colBullet = colBullet - "'s bullet";
GameObject.Find(colBullet);
} }
The name of the collided object is put in the colBullet variable. I printed it and it says: Playername's bullet. This works but now the only thing it needs is the 's bullet being removed
int suffixLength = "'s bullet".Length;
string player = gameObject.name.Substring(0, gameObject.name.Length - suffixLength);
But maybe it would be better to have a property that doesn't need manipulating to find the player name?
Long story short: keep a reference to the player in your GameObject, instead of its name. This way you save on look ups for the player if you want to, for example, increase the experience or gold the shooter has for each kill. For stray bullets, or recycled ones, just set Player to null.