Using one scene for infinite levels - unity3d

I am trying to make a game where there is a single scene, which will be used for an infinite number of levels until the player loses. All of my code is currently in a GameController script, and I have it so that when the level is completed, the player will press a key and integer for the level will be incremented, and the same scene will be loaded.
void Start()
{
gamePlaying = false;
currLevel = 0;
BeginGame();
}
void Update()
{
if (Input.GetKeyUp(KeyCode.Return))
{
currLevel++;
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
I have this script and a DontDestroyOnLoad script attached to the GameController gameObject.
This currLevel variable is staying at 0 when printing to the console; however, it is updating in the inspector. What am I doing incorrectly, and is this a good way of setting up this project? Thank you!

There are some ways to implement this but I would recommend to not reload the scene but have a list or container with the objects you want to destroy and when loading the next scene you destroy these and create new. You can easly make a loading screen in this time and even better pre buffer the new scene when you notice the old one is comming to an end.
So instead of reloading the scene, destroy unnecessary objects and create the onse you need. Depending on your needs you may even reuse some as the floor for example and just change the color for your level. As said that all depents on your usecase.

Related

Instantiating object with physics on Canvas

I've been trying to instantiate simple object on my canvas that would show added score value with some small visual and then fall down with gravity for a while before disappearing.
I Cant in any way make it visible as UI element.
It is spawning at ridicolous position where canvas objects are physically. and even if i instantiate it as a child of my Ui element it has RectTransform but is not visible by camera as Ui element.
in my script "scoreValue" is ui element under which i'd want it to be instantiated,scoreVisualisationSpawnPoint is normal object with trasnform position i used earlier.
How to instantiate object on canvas at certain position in canvas for it to be visible?
Here is my not-working code:
public void CreateAddScoreVisualisation(int addedScore)
{
GameObject effect;
effect = Instantiate(addScoreVisialisation, scoreVisualisationSpawnPoint, scoreValue.transform.rotation,scoreValue.transform);
effect.GetComponent<RectTransform>().position = scoreValue.rectTransform.position;
effect.GetComponent<ScoreVisualisation>().scoreText.text = addedScore.ToString();
}
That can be tricky at times, but are you sure this is the right approach at all?
I'd suggest have your object permanently there so you can set it up as you wish with the inspector and then in the start function, call gameObject.SetActive(false) to disable it.
Then instead of instantiating, activate it.
This will also be more performant by the way because small, inactive objects don't cost much but instantiating and destroying is relatively expensive.

GameObject isn't in the hieararchy, but its script's Update is called?

Now I am facing a ghost object.
There was a script attached to an object which I deleted. But for some reason, the script's update function is always being called.
I added this line to the Update: Debug.Log(name), and its name is Flamestrike, but when I search it in the hierarchy, there are no results.
And if I set its position to 0,1,0 (so it should be visible), it is not visible in the game either.
So please help me because it drives me crazy :(
Edit:
Debug.Log("a");
if(transform.parent == null) {
transform.SetParent(GameObject.Find("Canvas").transform);
Debug.Log("Canvas");
}
I also tried this, and it prints Canvas, so it sets its parent to Canvas, but I can't see any Flamestrike objects under Canvas.
When Instantiating a prefab GameObject, for some reason it was being created with Hidden Flags. In order to solve this, we added the code: this.gameObject.hideFlag = HideFlags.None; which allowed the object to show up in the hiearchy finally.
The only other source I could find on this was this answer, which had basically no explanation as to why it occured. http://answers.unity3d.com/questions/921819/instantiated-prefabs-not-showing-up-in-hierarchy.html (quoted below)
Found the issue, not sure why but: These two ways are working (prefab
is a GameObject defined elsewhere).
Player1 = Instantiate(prefab) as GameObject;
Instantiate(prefab) as GameObject;
For some reason the prototype:
Instantiate(prefabName, position, rotation);
Was not working.
(Sorry if this is not the correct way to write this, but the comments are too short, and can't be formatted)
This not fully true, I think.
This hidden gameObject wasn't created via script. I dragged the prefab to the scene, then somehow I didn't delete the prefab fully. (or didn't even delete, just made it hidden)
It disappeared in the hieararchy, but it wasn't deleted fully.
After we made the object visible via script, now it is visible.
(but only in play mode, so I can't delete it, because it is not visible in scene view)
And it got some interesting components/attributes.
The original story:
FlameStrike - a Container for scaling purposes (empty gameObject)
-FlameStrike - a gameobject with animation, FlameStrike.cs script etc.
--Particle System - a part. system with this exact name.
But after we found the remaining hidden object it was like this:
So I don't understand what I did. It deleted some parts of the prefab, but also mixed some parts,
(like adding the Particle System object's Particle System component to this FlameStrike object)
then made it hidden. Is there a hotkey for this? :D Because it is not script related issue, I did this in the editor.

How to programmatically assign a random sprite to game object?

I have a function that generates a game object on screen every 100 frames:
var trash : Transform ;
function Update()
{
if(count == 1)
{
Instantiate(trash,new Vector3(UnityEngine.Random.Range(-3f,3f),UnityEngine.Random.Range(-3f,3f),UnityEngine.Random.Range(-3f,3f)), Quaternion.identity);
}
else if(count == 100)
{
count = 0;
}
}
Now, I want each of those generated objects to pick a random sprite from my assets. I thought about making a sprite array and picking from that, but I'm not sure how to go about doing so or how to assign the sprite to the object.
Anu help would be much appreciated!
I know it's late, but I just did it for myself, so I'm sharing.
Basically - put your assets in a folder and choose randomly from them to assign to the object you're duplicating.
Create a Resources folder under Assets.
Create another sub-folder for your relevant sprite assets, under Resources, lets call it CookiesImages.
Create your prefab object, and locate it under Assets/Prefabs/Resources (this is the object that you want to duplicate multiple times with different assets).
Create a script for this prefab object.
Create a static Object array (will hold the sprites).
In your Awake() method, init this Object array by loading all the resources from your assets folder:
if (objectsArray == null)
{
objectsArray= Resources.LoadAll("CookiesImages", typeof(Sprite));
}
In the Start() method, get a random index 0 --> objectsArray.Length and call Instantiate to create a sprite to assign to your prefab object.
this.GetComponent<SpriteRenderer>().sprite = Instantiate(objectsArray[index]) as Sprite;
At the beginning, I tried assigning them to an array variable from the unity UI, but I realized that in the way I described it's much more flexible.
Well, you can generate an array of sprites of the length of your choosing with:
Sprite[] _sprites = new Sprite[quantity desired]
Then using the resources folder and the Resources.Load method (found here: http://docs.unity3d.com/ScriptReference/Resources.Load.html), you could load all your sprites into the array one after the other. Then using your random number generator, you can access sprites at random from it.
Still probably not the best way of doing it, but I would imagine it is considerably better and easier to maintain than the prefab method, but different situations call for different approaches.

unity jumping collisions - how enemy is damaged

I am making a platformer in Unity using unityscript.
I have a Player parent object with a character controller and various child objects. I have a similar enemy with a box collider. I'm struggling to differentiate between the collision happening when the player walks into the enemy and when the the player jumps and collides with it from above.
I've tried tagging the child objects but they don't have colliders. If I add colliders to the child objects, it messes up my character movement. I've also tried to test the position of the player:
if(col.transform.position.y >= transform.position.y){ killThyself(); }
But this doesn't work either - should I add the height of the enemy? If so how do I do that?
Any suggestions happily received.
Mmmm, I would use a boolean variable. Make it true when you press the jump button, and false once the jump has finished (when the player touches the floor). Declare the boolean as a public variable.
After that, in the OnCollision method, check the variable value.
I recommend you to read this to understand how to do that:
http://docs.unity3d.com/Documentation/ScriptReference/index.Accessing_Other_Game_Objects.html
Well, in your case I would assign the "otherScript" (the player script) doing this in the enemy control script:
var player : GameObject;
var playerScript: PlayerScript;
//I'm assuming "PlayerScript" is the name of the control script of your player,
//where you defined the "jump" variable.
function Start()
{
player = GameObject.FindGameObjectWithTag("Player");
//You also can use GameObject.Find("PlayerName")
playerScript = player.GetComponent(PlayerScript);
//Get the script from the player
}
function OnCollisionEnter(col : Collision)
{
if (playerScript.jump == true)
{
killThyself();
}
}
I'm finding the player on the function Start, to find it only ONCE, in the level load. Now, I assign the player script into a variable, so, when the player hit the enemy, this enemy will check if the player is jumping using his script. Remember to declare this variable as a public variable or this won't work.
Please comment if you have any problem using this method =)
I would use a second collider at the upper part of the enemy let's called it headCollider. Set isTrigger = true and maybe use a special physics material. If this headCollider is the first one to get triggered you know that the player chararacter is jumping on the enemy or is falling on it from above.
In OnTriggerEnter (Collider other) you can prepare some status variables (and maybe a timer for resetting the status). Also the current jump status like in V_Programmer's answer suggested should be useful for evaluation.
As Unity does not allow you to attach 2 colliders of the same kind, you have to use box and sphere or create an empty child and use that one.

unity moving to another scene with current scene being paused

I'm making a turn-based battle game in Unity3D and I have 2 scenes (a town scene and a battle scene). Whenever the character meets a monster, the game jumps to the battle scene where the character does battle and go back to the town scene after defeating or losing.
The problem is how to return to the town scene with the same state as when the character enters the battle scene (character position, statuses, etc.)
if I use
Application.LoadLevel('battlescene');
then
Application.loadLevel('townScene');
then the townscene will start from the first time. How to make the townscene continue from where we left off?
There are two ways that I think you can accomplish this. It all depends on your target platform and how important resources are but here we go:
1) If resources aren't an issue
You could put all your normal scene and battle scene objects in one scene.
Create two empty game objects (One for Town Scene objects and the other for Battle Scene Objects). You can then either have two versions
of your game character(s) or one. Then write a script that simply
switches the camera(s) from the town scene to the battle scene when
a battle is triggered and back to the town scene when the battle is
over.
If you have one version of each character you could simply add a script that changes the behaviour of your game character controller
to/from battle mode and normal/town mode.
If you have two versions of each character then you would simply need to write the appropriate character controller scripts and
activate/deactivate the game characters according to which one you are
using. This is how games like Final Fantasy 7,8,9 achieved the same
effect. There were two versions of the game characters: one for battle mode and the other for normal mode.
2) If resources ARE an issue
(and I think a more efficient way)
You could use the Application.LoadLevelAdditive function. This function allows you to load a different scene and rather than destroy everything in the current scene, it takes the new scene and all it's objects and adds them to the current scene.
So basically you can use it something like this:
Create a separate battlescene and within your scene, create an empty game object to hold every object in your scene.
In your noraml scene do the same.
When you need to go to battle mode use:
Application.LoadLevelAdditive ('battlescene');
And when/if you want to unload your battlescene after that you can do so by simply writing code to destroy the battlescene game object
since it contains everything from your battle scene.
As with the first method you can decide whether you want to have two different versions of your characters or not. One of the pros of having two versions is that if you want to save time by not going into detail with you game models (especially if your game is really big) you can have save processing power by using scaled down models for the town scene and using polished more detailed models for the battle scene, assuming your battle scene is a small stage representing the place where your characters are fighting. Think final fantasy VII. Just something to consider.
I hope that helps. I've written it all in a rush but lemme know if anything needs clearing up.
You can do it by script in c#
void onYourFunction()
{
Time.timeScale = 0; //pauses the current scene
Application.LoadLevelAdditive("YourNextScene"); //loads your desired other scene
}
And when you want to activate your game back you can use Time.timeScale = 1;
I know this is an old post, but there is one more method that can be used. This would be to save the state of the scene. This comes in handy when you don't expect users to have the resources for loading 2 scenes with the Application.LoadLevelAdditive. That method potentially can use twice the resources.
When you save the state (save all information that can change to a file or DB) you can then load the level at a later time and not have it sitting in memory. You could also use this to save your game.
I know it is on old post. But I have found another, very easy solution for my case. Just deactivating all GameObjects from one scene while the other is active and then reactivate it, as soon I go back to the root scene:
[Button]
public void UnPauseScene()
{
EndlessSceneCamera.gameObject.SetActive(true);
Time.timeScale = 1;
levelStatus = LevelStatus.Running;
foreach (var go in activeGameObjectsBeforeScenePaused)
{
go.SetActive(true);
}
}
[Button]
public void PauseScene()
{
//EndlessSceneCamera.gameObject.SetActive(false);
levelStatus = LevelStatus.Pause;
Time.timeScale = 0;
var allGameObjects = FindObjectsOfType<GameObject>().ToList();
activeGameObjectsBeforeScenePaused = allGameObjects.Where(x => isActiveAndEnabled).ToList();
foreach (var go in activeGameObjectsBeforeScenePaused)
{
go.SetActive(false);
}
}