Hi I'm new to coding games and using Unity, when I switch Scenes in unity the objects 100x and the saturation gets weird
Here is my current script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Game_End : MonoBehaviour
{
int Pins = 0;
void OnCollisionEnter(Collision collision)
{
Pins += 1;
}
// Update is called once per frame
void Update()
{
if (Pins == 4)
{
SceneManager.LoadScene("Level 2", LoadSceneMode.Additive);
}
}
}
Welcome to Unity! There are a few issues I can see, so I will try to explain each one. The main issue you are currently having is you are loading a scene on top of itself using the LoadSceneMode.Additive. It is loading the scene Level 2 on top of itself as long as Pins is equal to 4, which I am guessing is every frame.
I would instead put this check inside of the OnCollisionEnter as it should only be called once. Your other issue is you are not checking what you are colliding with. You might want to check the object you hit by tag. If you are unfamiliar with tags, you can look at the docs. Adding a tag to your game called Pins and adding it to all of your objects that are pins will help resolve what you are colliding with.
Now to solve the near infinite amount of scenes you are spawning. As I mentioned, it is because your conditional check is in Update, which in Unity is called every frame. With the condition you are currently checking for, if pins is not reset, it will keep loading your scene. As you are also using the Scene.Additive, it will load the new scene on your old scene, so the variable pins will not reset unless you collide with something else. I would recommend changing your code to this example:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Game_End : MonoBehaviour
{
int Pins = 0;
void OnCollisionEnter(Collision collision)
{
// we are only checking if the object we hit is tagged as 'Pins' to make sure we hit a pin
if(collision.gameObject.tag == "Pins")
{
// add to the pins
Pins += 1;
// destroy the pin we hit so the player can not hit it twice
Destroy(collision.gameObject);
// check our condition to load the new scene
if(Pins == 4)
{
SceneManager.LoadScene("Level 2");
}
}
}
}
Now that you are only checking if the collision is with an object tagged as Pin, the counter will only go up when you collect a pin. By adding the Destroy, you assure that each pin will only increase the count by 1. And finally, by putting your level check inside of this function, it will only check your condition when it increases the count. My one question is, do you want to use LoadSceneMode.Additive? It loads a scene directly over your current scene. I believe you'd want to load the scene normally so it loads your new scene. Would you mind clarifying how you want to load the new scene a bit more? In my example snippet I removed the additive as I believe you do not want to use it. The docs Unity has for LoadScene use it, so I assume you got it from there.
If you do not understand any of what I said, feel free to ask any questions in the comments. I can tweak the answer as needed to help you understand.
Related
So, i'm trying to make a Multiplayer Game here with various game objects and scripts in c# for every object on the scene.
Thing is, when i spawn the player controlled objects every player shares control over scripts for each spawned gameObject on the scene, that means, when somebody presses "s" for example, every player moves backwards, and that's not how i want game to behave.
--So, the only way i know to solve this, is by spawning 'em with all their scripts (the components) disabled and enable 'em with another script on the gameobject, but i had to make a script to enable every component one by one, and it got really time comsuning to create or edit a new script every time i add a new one to new units n' so on, so i figured out i could do something like this script below.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class PlayerNetControl : NetworkBehaviour {
public MonoBehaviour[] components2enable;
public override void OnStartLocalPlayer()
{
foreach (MonoBehaviour cmp in components2enable)
{
cmp.enabled = true;
}
}
}
after doing this, i expected every "monobehaviour component" i added to the script using unity, to be enabled when for the player who controlled the game object only, but it does nothing, i check the components on the gameobject testing this out, they are all still disabled.
Also, is there any way for me to solve this problem in any other way than the one i know? if so, i would love you to illuminate me teaching me how.
Please help, i've started coding recently and i really need help with C#
Check for islocalplayer.
I think this solves all your problems.
https://docs.unity3d.com/ScriptReference/Networking.NetworkBehaviour-isLocalPlayer.html
I'm a student and I'm doing a 2D platform game as a project but my programming skills are so bad(That's why I'm trying to do the code by myself) but I'm stuck on that and I don't really have an idea about whats going on. Let me explain.
I've got my Player GameObject with his script playerBehaviour actually working and a BoxCollider2D marked as a Trigger
This Player, also tagged as Player, it's inside a Trigger that belongs the the GameObject LiveZone, who has the DeathZone script below.
using UnityEngine;
using System.Collections;
public class DeathZone : MonoBehaviour {
public PlayerBehaviour playerBehaviour;
void OnTriggerExit2D (Collider2D other) {
if (other.tag == "Player") {
playerBehaviour.respawn = true;
Debug.Log ("Respawn");
}
Debug.Log ("Exit Collider");
}
}
I also tried to do it in a most common way, setting the limits of the "LiveZone" with some triggers to delimitate the area with "DeathZoneTriggers"(that's why the script was called DeathZone at first). But I had the same problem with the OnTriggerEnter2D ().
It looks like it doesn't want to detect my Player leaving or entering this area, as you can see I also called some Debugs, but are not working neither.
To organize information you may also need(or not):
2 GameObjects with Triggers
"Player", who has to exit the zone and "AliveZone", who should detect who's leaving.
Player is tagged as "Player", AliveZone has no tag(don't know if that would mean something)
Any idea?
God I found what was wrong, I set a layer that was ignoring the deafault ones, so it wasn't interacting with that deathzone collider ._.
At least I finally found what was wrong with it, thx anyways for those who read it up and tried to think about a solution! :)
I am working through the Unity tutorials, and am currently on a tutorial called "Space Shooter." Something fishy has happened.
I noticed that the Boundary object, and the asteroid object both disappear when the game begins running. Note, both have colliders, and they are not touching. Their is a script called "DestroyByContact", which essentially destroys the game object whenever the player shoots it.
using UnityEngine;
using System.Collections;
public class DestroyByBoundary : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
if (other.tag == "Boundary")
{
return;
}
Destroy(other.gameObject);
Destroy(gameObject);
}
}
I found that when I delete this script off of my Asteroid gameObject, the game functions normally, and the objects are deleted. Their must be something wrong with the script, but I cannot find out what went wrong.
EDIT: I forgot to place the Boundary object to the tag "Boundary" in Unity. This fixes the problem.
Most likely you have not set or misspelled your boundary's tag Boundary1. See This point in the tutorial video.
This is causing your if (other.tag == "Boundary") to be false so it does not go in to the if block to exit the function early.
P.S.: If you are using Unity 5 you should now use if (other.CompareTag("Boundary")), it was not in Unity 4 when the space shooter tutorial was written and it supposedly has better performance than doing a other.tag == "Boundary" compare. You can see a example of it used in the Roll-A-Ball tutorial which is written in Unity 5. The Roll-A-Ball tutorial also has a example of adding a new custom tag in the Unity 5 UI.
1: Ironically I misspelled Boundary when I first posted this answer.
I was following a unity tutorial started on Unity 4 but I am on Unity 5, and when I try to use the script seen (https://youtu.be/vwUahWrY9Jg?t=1337) and I try to use it, it gives an error:
Assets/Scripts/DestroyFinishedParticle.cs(18,17): error CS0246: The type or namespace name `Destroy' could not be found. Are you missing a using directive or an assembly reference?
this is the code:
using UnityEngine;
using System.Collections;
public class DestroyFinishedParticle : MonoBehaviour {
private ParticleSystem thisParticleSystem;
// Use this for initialization
void Start () {
thisParticleSystem = GetComponent<ParticleSystem>();
}
// Update is called once per frame
void Update() {
if (thisParticleSystem.isPlaying)
return;
Destroy (GameObject);
}
}
It can be because C# code for unity changed from 4 to 5? what should I change? The problem seems to be in the Update method.
There are couple of issues with this code.
First, you didn't mention to what exactly is it attached too? I assume it attached to the Particle System.
Secondly, use "gameObject", not "GameObject", since GameObject is the name of the class.
Third, I believe there's a much more efficient way to destroy the gameObject without checking every frame whether the particles system has finished or not, maybe set a small timer? or invoke the function with time?
Depending on how your event is set up would depend on the approach to checking if the particles are running. If you can setup a collider to when you walk in, you can trigger an event to know the particles are on. Upon exiting the collider, the particles will shut off.
I'm not 100% on the syntax of return in C# but seems like it should go after you destroy your game object. I think return works in a similar fashion as the break in that aspect.(Especially since you don't seem to be returning any values anyway why do you need it?)
I'd like some help with the following issue. I'm making a simple game where you have a character running and he has to jump over obstacles coming at him.
And I'm currently stuck when it comes to creating GameObjects and randomly generating them within the game scene at run time.
I've written a class to help accomplish this:
using UnityEngine;
using System.Collections;
public class randomObstacles : MonoBehaviour {
public GameObject myCube;
public Vector3 spawnLocation = new Vector3(0,2,0);
// Use this for initialization
void Start () {
GameObject SpawnLocation = (GameObject)Instantiate(myCube, spawnLocation, Quaternion.identity);
}
// Update is called once per frame
void Update () {
}
}
The above code is what I wrote to simply create Objects, one after the other. But when I run the game, it comes up empty -_- !
Can anyone please tell me where am going wrong, and from the look of it my code doesn't seem to do what I am hoping to achieve :(
I've attached the above script into an empty GameObject as I saw in a tutorial from the Unity Community forum, but that did not help either.
(I've looked around and it seems like no one has come across such an issue - I could bee wrong)
It would seem that your myCube variable is the root of your problems, having tested it in a scene of my own. By subsituting
(GameObject)Instantiate(myCube, ...
with
(GameObject)Instantiate(GameObject.CreatePrimitive(PrimitiveType.Cube), ...
I was able to produce a cube at (0,2,0) with no qualms. Perhaps your myCube GameObject is missing a Mesh Renderer, in which case it would appear in the Hierarchy during runtime even though it would not appear visible in Game View. Perhaps you are not assigning it in the Inspector before you run the game, in which case the myCube variable would refer to null and thus not be created. Additionally, though you may be assigning the GameObject you instantiate to SpawnLocation, it is an unused local variable (something MonoDevelop or your code editor should notify you of). Make sure you either provide a reference to a myCube GameObject in the Inspector before runtime or through script referencing to a loaded prefab/GameObject during runtime. It would also be helpful to provide a fallback (say, to PrimitiveType.Cube perhaps?), which will make your code more robust and able to handle errors in referencing should they arise.
Regardless, in order to achieve the functionality you have described, first make sure yo have properly prepared whatever you would desire myCube to be. Also, for future posterity, you may want to initialize your spawnLocation in the Start routine, and assign the variable coordinates by substituting Random.value * yourValueCeiling in for each random coordinate you would like myCube to spawn on. You could even go as far to make a helper method externalized and thus independent from the start routine, such that you will not have to have a hundred instances of a single script to create a hundred instances of what you need; rather, you can call the method through a single script, and save yourself trouble in this way. If you would so appreciate it, here is my implementation of your objective, hope this helps!
using UnityEngine;
using System.Collections;
public class randomObstacles : MonoBehaviour {
public Vector3 spawnLocation;
public GameObject myCube;
// Use this for initialization
void Start () {
if (myCube != true) {
Debug.Log("myCube not set");
myCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
}
if (myCube.renderer.enabled == false) {
Debug.Log("myCube not rendered");
myCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
}
CreateCube();
}
// Update is called once per frame
void Update () {
}
void CreateCube() {
spawnLocation = new Vector3(0, Random.value * 10, 0);
Instantiate(myCube, spawnLocation, Quaternion.identity);
}
}
It may be worth pointing out that you're creating your object in the Start method, which means your code will only run once: from the name of your class, I'd assume you want to create more than one object using this code.
If you move the code into Update you'll create one object per frame, which is most likely too many. My guess would be that you want something like a coroutine that will run on a random interval, and then spawn cubes repeatedly over time, something like this:
void Start () {
StartCoroutine("SpawnObjects");
}
IEnumerator SpawnObjects()
{
while (keepAddingObjects) // a boolean - could just be "true" or could be controlled elsewhere
{
GameObject SpawnLocation = (GameObject)Instantiate(myCube, spawnLocation, Quaternion.identity);
float delay = Random.Range(1f, 5f); // adjust this to set frequency of obstacles
yield return new WaitForSeconds(delay);
}
}
Taken from my own code in a game that auto generate mazes:
public class Cell
{
private GameObject instance;
public void CreateVisual()
{
// Load a GameObject that exist inside the "Resources" folder.
GameObject prefab = (GameObject)Resources.Load("Models/Walls/3W1");
// Create an instance of the prefab
instance = (GameObject)GameObject.Instantiate(prefab);
instance.transform.position = myPosition;
}
}
I think the part you are missing is the Resources.Load() method.