I'm trying to generate 6 random ints, then assign them to 6 different objects, however I've found that simply generating the int within the object results in every number being the same, due to them all loading at identical times. To work around this issue I'm trying to generate the 6 in a row, so that the clock timing is different and gives a different number. I'm trying to figure out how to access these 6 variables.
I've tried a variety of different formats using 'GetComponent<>()' and 'GameObject.Find("")' together and storing the resulting script in a monobehaviour varibale (which I think is what might be messing me up), then trying to access the numbers through the variable I'm storing the script in. But when I do this, unity says there is no number variable (or Num1, Num2, etc. in my case) in the script.
Here is what I have, I'll only show the code trying to acquire the variables as I have verified that the variable generation works.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class NumberButton : MonoBehaviour
{
public int Num;
public GameObject Game;
void Start()
{
MonoBehaviour Game = GameObject.Find("Game").GetComponent<GameInit>();
print(Game.name);
if (gameObject.name == "Button1")
{
Num = Game.Num1;
}
else if (gameObject.name == "Button2")
{
Num = Game.Num2;
}
//There are 4 more of these, 1 for each button, I realize this is terrible code etiquette.
GetComponent<TextMesh>().text = Num.ToString();
}
}
If it works, each button should be assigned their variable based on their name, so Button1 gets Num1 from the GameInit script stored in the GamObject "Game". In actuality nothing is grabbed from GameInit, all the Num variables in the grabber objects are equal to 0, despite the variables in GameInit not being 0.
EDIT
Sorry, I misread exactly what your issue was. The compiler is telling you that those variables do not exist in the MonoBehaviour object, because MonoBehaviour does not have those variables.
You need to change
MonoBehaviour Game = GameObject.Find("Game").GetComponent<GameInit>();
To
GameInit Game = GameObject.Find("Game").GetComponent<GameInit>();
ORIGINAL
I can't yet comment due to low rep so I am going to have this as an answer.
Firstly, is the number generation happening in GameInit.Start()? If so, it is possible that the button Start()s are being called before GameInit.Start() and so all of the variables are the default value of 0 at the time of access. To ensure that this is not the case, put the number generation code in GameInit.Awake().
Also, to ensure that there is no hocus pocus happening with the MonoBehaviour object, try this:
...
if (gameObject.name == "Button1")
{
Num = GameObject.Find("Game").GetComponent<GameInit>().Num1;
}
...
Related
The game is simple, your Player has a running animation and must jump to dodge obstacles, but isn't moving. The obstacles and background are.
My gut instinct is that it is out of scope somehow or is perhaps overflowing - the score increment was increasing far beyond what I had anticipated when I had the AddScore() inside of the Destroy(gameObject); if condition instead of its own function.
However, at this point I am very confused why it isn't working. As a bonus, I cannot get Audio to play from the second commented bit (Value cannot be null.) As for why that happens, no idea. I definitely have the source I have it attached to to the prefab that is spawned, and said spawn should trigger that sound to play when it passes under the player when they jump, I originally thought that there was an issue where the object was deleted before it could reference its audio source but I am unsure.
Edit: I am going to leave the 'bonus' issue above even though I literally fixed it as I typed this up. (I had to add an Audio Source component to the prefab I was spawning.)
I still, for the life of me, cannot get an integer to go above 1 and print to the console. It might be driving me a little insane. Please help friends. I have googled a ton and none of the suggestions from other comments fixed my issue.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveLeft : MonoBehaviour
{
private float speed = 30;
private PlayerController playerControllerScript;
private float leftBound = -15;
private float scoreZone = -3;
public AudioClip scoreSound;
private int score = 0;
private AudioSource playerAudio;
// Start is called before the first frame update
void Start()
{
playerControllerScript = GameObject.Find("Player").GetComponent<PlayerController>();
playerAudio = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
// Moves objects as long as it is not game over.
if (playerControllerScript.gameOver == false)
{
transform.Translate(Vector3.left * Time.deltaTime * speed);
}
//Assigns scoring system, buggy. Commented out sound because of errors.
if (transform.position.x < scoreZone && gameObject.CompareTag("Obstacle"))
{
//playerAudio.PlayOneShot(scoreSound, 1);
}
//Destroy object out of bounds
if (transform.position.x < leftBound && gameObject.CompareTag("Obstacle"))
{
Destroy(gameObject);
AddScore();
}
}
void AddScore()
{
//Score goes to 1.
score++;
//prints 1 in console but does not increase over 1.
Debug.Log("Score! Your Score is" + score);
Debug.Log(score);
}
}
Tried: Numerous changes to configuration of ++, x = x +1, x++, x +=, etc. No idea. Am lost.
This is an issue caused by the local member int. You have an object, which has been created and this MoveLeft component is attached to it. You then destroy this object on collision, and therefore this component as well. You’ll have added one to the local instance int score, but then you destroy the component and lose this local instance.
I suspect what you thought was happening is that all the scripts/components shared the same variable values. That would only be true if you if you made the int score member a static int score, which means the member is the same shared amongst all instances of this component.
Instead of making score static, you might want to have a “Game Manager” that exposes public functions to allow you to increment and retrieve the current score.
I am trying to get my 3-D Tic-Tac-Toe game project to work, I have game objects which are named cells that are instantitated I press OnMouseDown() click it makes a cell object spawn in its grid space. I don't want to use UI with the basic prefabs I created. Is there a way to get my game objects instantiated and once it reaches a certain number as a winning condition? I have considered using pathfinding but I am not certain if that would be the correct approach. I have looked every where to find a solution that is unique to my problem but could not find a solution. Perhaps, I am asking the wrong questions but I am desperate so that is why I came her to see if I could get input on how to approach this issue.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.SceneManagement;
public class Cell : MonoBehaviour
{
public GameObject cell;
public GameObject negCell;
public GameObject alter;
public Transform transPos;
[SerializeField]
private bool isTapped = false;
private int counted;
public int gameObjectCount;
void Start()
{
gameObjectCount = GameObject.FindGameObjectsWithTag("Cell1").Length;
}
void Update()
{
}
public void OnMouseDown(int counted) //click and point to create and deestroy objects
{
counted = gameObjectCount;
isTapped = true;
transPos = alter.transform;
Instantiate(cell, transform.position, Quaternion.identity);
StartCoroutine(WaitForObject());
Debug.Log("Alter Destroyed!");
gameObjectCount++;
DestroyGameObject();
return;
}
IEnumerator WaitForObject()
{
if (isTapped == true)
{
Instantiate(negCell, -transform.position, Quaternion.identity);
isTapped = false;
}
yield return new WaitForSeconds(3f);
DestroyGameObject();
}
void DestroyGameObject()
{
if(gameObject == alter)
{
DestroyImmediate(alter, true);
}
else
{
DestroyImmediate(cell, true);
}
}
}
There are two easy ways to achieve this.
The first one would be to add a static member in your class, let's say :
private static int _instanceCounter = 0;
This will act as a class instances counter.
All you have to do is to increment this variable every time you instantiate a new game object.
Finally, base your win condition on the number of instances of the class you want.
You can also decrement this variable if for some reason at a moment you call the Destroy method on a specific game object.
The other way would be to use the FindObjectsOfType method from Unity which returns an array of all instances in your current scene.
By accessing the length of this array, you'll have the number of instances.
However, this only count for the current number of instances when this method is called. Note that you can also include the inactive game objects from the scene (those which are in grey within your hierarchy panel).
You now have two ways to do it, depending on how you want to achieve your win condition, i.e. the total of game objects instantiated OR a specific number of game objects at a given time.
This sounds dumb, but I can't get 2 simple variables to add to each other, I have set points to add to 100 in the inspector. Everything would seem to work fine but when I all AddPoints from another script I Always get a debug log of 5. No matter what I set pointsToAdd to it always comes out as 5. I've tried score++; and that comes out just fine, I also tried to write a Debug.log just to make sure pointsToAdd wasn't set to something weird and it always returned 0! I don't know what in the world is happening. I must have screwed something up somehow.
private float score = 0;
public float pointsToAdd; // Setting in the editor
public void AddPoints()
{
score += pointsToAdd;
Debug.Log(score);
}
And the script that's calling AddPoints contains:
public LevelManager levelManager; // I'm setting in the editor
void OnCollisionEnter2D(Collision2D other)
{
if (other.transform.CompareTag("Wall"))
{
levelManager.AddPoints();
}
Edit: I've been testing for a few days now, with every chance I get completely unpredictable results until I set my score and Text UI to static variables, what about static variables changes the way that works?
Going to need a little more information on this one.
However I don't know how you are doing it in the other script, I am assuming its not this script causing the problem, most likely the other. I would personally do:
OtherScript:
pS.AddPoints(100f);
PointsScript
private float score;
public void AddPoints(float pointsToAdd)
{
score += pointsToAdd;
}
I'm using Unity 4.6.9, coding in c#, and all I'm trying to do is change what starts as an input field with an Integer content type and a character limit of 2, to one that has a Standard content type and a larger character limit. I've created the object itself using Unity itself, so I can't figure out how to change it in the script. What i'm trying to do is have a single field be responsible for 2 integers and a string input, and i have the entirety of the code completely working, EXCEPT for changing the type and limit while the program is running. I've been googling and trying things for almost 2 hours now, so I'm hoping I didn't just miss something. I've already tried looking through Unity's documentation and that hasn't helped me what-so-ever.
For the purpose of answering this, my Input Field is named InputField, the class it's in is named UIInputField, and the actual output from that field is named tempInput (the data that gets sent from that field into the program). And like I said, I'm just trying to change "Content Type" and "Character Limit", I've already got the code worked out to convert strings to ints, as well as a failsafe if the input field is left blank, or has the wrong character type.
if I've left anything out that is necessary for this question to be answerable, let me know.
EDIT: Sorry, I left out the code thinking it wouldn't be necessary (thought this would be an easy fix that I just hadn't figured out yet) So here's the code for what I've got so far (I do know that there are portions of this program that could create an issue depending on what the user puts in, and already know how to fix it, but I'm trying to see about getting this input issue working properly before I worry about those issues):
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
public class UIInputField : MonoBehaviour {
string[] particNames;
string[] particInit;
int subState = 1;
int state = 1;
int particVar;
// Update is called once per frame
void Update () {
}
//Fix substate handling before building.
public void getInt(string tempInput){
if (state == 1) {
if (Int32.TryParse (tempInput, out particVar))
Debug.Log (particVar);
particNames = new string[particVar];
particInit = new string[particVar];
GameObject.Find ("InputField").characterLimit = 12;
GameObject.Find ("InputField").ContentType = standard;
state++;
} else if (state == 2) {
particNames [subState] = particVar;
subState++;
GameObject.Find ("InputField").characterLimit = 2;
GameObject.Find ("InputField").ContentType = integerNumber;
if (subState == particNames.Length){
state++;
subState = 1;
}
} else if (state == 3) {
if (Int32.TryParse (tempInput, out particVar))
Debug.Log (particVar);
particInit[subState] = particVar;
subState++;
if (subState == particNames.Length) /* The code to move on the the next portion of this program will be here once this portion is working properly*/;
}
}
}
After doing more searching over the past couple days, I found the answer to this question. It uses:
mainInputField.contentType = InputField.ContentType.Standard;
mainInputField.characterLimit = 12;//Or any integer
mainInputField is just a variable at this point, of type InputField, and you have to go into the UnityEditor to set that variable to reference the actual input field variable.
Thanks all! The issue was I was using GetComponents rather than GetComponent, thanks!
I am fairly new to programming and I am trying to make a 2D game in Unity. I have found a tutorial online which is really good, up until a point (Tut can be found here http://pixelnest.io/tutorials/2d-game-unity/shooting-1/). I've come across an error and can't figure out why. The error occurs when I try and use another script inside my current script (if that makes sense to anyone). The two scripts in question have the name ShotScript and HealthScript and they are below
ShotScript:
using UnityEngine;
using System.Collections;
public class ShotScript : MonoBehaviour {
public int damage = 1;
public bool isEnemyShot = false;
void Start () {
Destroy (gameObject, 20);
}
}
HealthScript:
using UnityEngine;
using System.Collections;
public class NewBehaviourScript : MonoBehaviour {
public int hp = 2;
public bool isEnemy = true;
void OnTriggerEnter2D(Collider2D Collider) {
ShotScript shot = collider.gameObject.GetComponents<ShotScript>();
if (shot != null) {
if (shot.isEnemyShot != isEnemy) {
hp -= shot.damage;
Destroy (shot.gameObject);
if (hp <= 0) {
Destroy(gameObject);
}
}
}
}
}
The error I get is:
"Assets/Scripts/HealthScript.cs(13,36): error CS0029: Cannot implicitly convert type ShotScript[]' toShotScript'"
I'm rather stuck and so if anyone could point me in the right direction, that'll be great =)
P.S I'm new to this asking questions thing, so if you need any extra info, I'll do my best to provide it
Well this is the problem:
ShotScript shot = collider.gameObject.GetComponents<ShotScript>();
It sounds like GetComponents<ShotScript> is returning an array of ShotScript references, i.e. its return type is ShotScript.
Do you want to take the same action for each ShotScript? If so, you probably want to just use a foreach loop... although you probably only want to check for the hp going negative at the end. I would expect you to be able to remove the check for nullity, too, assuming that GetComponents will just return an empty array if there aren't any such components:
ShotScript[] shots = collider.gameObject.GetComponents<ShotScript>();
foreach (ShotScript shot in shots)
{
if (shot.isEnemyShot != isEnemy)
{
hp -= shot.damage;
Destroy(shot.gameObject);
}
}
if (hp <= 0)
{
Destroy(gameObject);
}
(I've reformatted that to be rather more conventional C#, but of course you can use whatever indentation you want.)
You're calling GetComponents (notice the plural) which returns an array (that is ShotScript[]) of all matching components of the type on that particular GameObject.
So this is attempting to assign a ShotScript[] array into a single ShotScript instance which is not possible.
If you wanted to retrieve only one ShotScript (because you intend to have only 1 on an object), use the GetComponent (notice the singular) method instead which will return only one instance or null if none are assigned.
So change the one line to this:
ShotScript shot = collider.gameObject.GetComponent<ShotScript>();
If your intent was to handle many ShotScript instances/components on the same GameObject, use the fix/code supplied in Jon Skeet's answer.
The error message says that line 13 is in error:
ShotScript shot = collider.gameObject.GetComponents<ShotScript>();
It looks like the GetComponents method is returning an array ShotScript[], but you're trying to implicity cast it to just a single ShotScript instance. Try:
ShotScript[] shots = collider.gameObject.GetComponents<ShotScript>();