I'm having trouble with this code I'm trying to make.
My goal: Make each level button have that level's rank on it as well,
but I'm trying to do it from one script.
Firstly, here's how I have set up everything:
Those are the ranks inside each button and with a Rankdictator script that I made inside each rank gameobject.
Here's the script for the Rankdictator:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Rankdictator : MonoBehaviour
{
int levelnumberrank;
private Image thisimage;
public Sprite rankgold;
public Sprite ranksilver;
public Sprite rankbronze;
public Sprite blank;
private Levellockcheck levellockcheck;
public void Start()
{
levellockcheck = FindObjectOfType<Levellockcheck>();
thisimage = this.GetComponent<Image>();
levelnumberrank = PlayerPrefs.GetInt(("rankoflevel") + (levellockcheck.thisbuttonlevel));
if(levelnumberrank == 3)
{
thisimage.sprite = rankgold;
}
else if(levelnumberrank == 2)
{
thisimage.sprite = ranksilver;
}
else if (levelnumberrank == 1)
{
thisimage.sprite = rankbronze;
}
else if (levelnumberrank == 0)
{
thisimage.sprite = blank;
}
}
}
Now here's the problem. As I said, the ranks don't show on each button correctly when there are multiple buttons active, however, when I only have one button active, the rank shows. Here's an example:
That is when I have both buttons active. (Level 1 should have full rank and level 2 should have low rank. But it's showing nothing)
Now here's when only one button is active. It shows correctly.
Edit
I already used Debug.Log to confirm the levelnumberrank on each button and it references as expected.
But, it still doesn't reference the rank on each button when all of them are active, only does so when one button is active while the others are inactive.
I figured the problem out: it was the levellockcheck!
On each button, there was a levellockcheck script with a public int thisbuttonlevel.
I was, on each Rankdictator, referencing the levellockcheck like so:
Levellockcheck = FindObjectofType<levellockcheck>();
levelnumberrank = PlayerPrefs.GetInt(("rankoflevel") + (levellockcheck.thisbuttonlevel));
By doing that, I'm referencing different numbers all at the same time from each single button. Because the (thisbuttonlevel) on each button was different.
What I was supposed to do on Rankdictator:
Levellockcheck = this.GetComponentInParent<levellockcheck>();
By doing that, I referenced the (thisbuttonlevel) of the button itself.
And now:
It works!
Related
so i'm trying to do a little game on unity . And i did a script , when you press left click on an object , it open a canvas and another one and then it add +1 to i , like that when i found every object . (so when i=3) it shows the end screen. But when i go in game mode , when i press left click it doesnt add the number , like every object have his same i , but i dont understand they have the same function no ?
And sometimes 2 of 3 works, i dont know if thats clear to understand.
using UnityEngine;
using UnityEngine.UI;
public class ActionObjet : MonoBehaviour
{
public Image image1;
public Image image2;
public Image image3;
public int i = 0;
void Start()
{
image1.enabled = false;
image2.enabled = false;
image3.enabled = false;
}
void Update()
{
if (Input.GetKeyDown("space"))
{
if (image1.enabled == true)
{
i = i + 1;
print(i);
image2.enabled = !image2.enabled;
image1.enabled = !image1.enabled;
FindObjectOfType<AudioManager>().Play("bruit_recuperer_objet");
}
}
}
void OnMouseDown()
{
if (image1.enabled == false)
{
image1.enabled = !image1.enabled;
}
}
}
https://i.stack.imgur.com/sOSJH.png
So I found the solution , I'm a bit sad that I wasted 5 hours just for that but yea..
I just changed the
public int i=0
into
static int i=0;
This is because each gameObject with this script has its own instance of all the variables. A static variable's value is universal to all instances of the same class so any one of them can update it for all of them when marked static.
Good morning everyone.
I must finish a little project for next month in unity.
This project is a remestered Angry Bird.
I want to create a code which allow to display and hide a panel everytime when I use Space touch on my keyboard.
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RadialMenu : MonoBehaviour
{
public GameObject[] RadialMenuItems;
public AudioSource AudSourc;
public AudioClip MovementClip;
public AudioClip UseClip;
public GameObject radialMenu;
Vector2 NormalizedMPose;
float AngleOfMouse;
int SelectedItem;
int PrevItemID=5;
void Update()
{
if ((radialMenu.activeSelf == true) && Input.GetKey("space"))
radialMenu.SetActive(false);
else if((radialMenu.activeSelf == false) && Input.GetKey("space"))
radialMenu.SetActive(true);
}
}
But it doesn't work.
I can hide the panel when I click in Space button for the first time but I can't display it again with the button.
I'm actually stuck on it and I can't finish my project.
Any help please
Thanks
If the GameObject is disabled the Update method is not executed executed anymore.
A solution would be to disable a child GameObject, so that the Update method is executed.
Hello! I am trying to make a room that will generate a random Layout from a list and get a variable from that layout. I have had some trouble with this since the layout is not there from the start of the game, and I have been working on this problem for a few days now. Currently, the "Room" GameObject searches it's children for the ones tagged "Layouts", then, after finding that GameObject, the code gets the "waves" variable from the Layouts component of the Layout. The code is here:
foreach (Transform child in transform)
{
if (child.tag == "Layouts")
{
layout = child.gameObject.GetComponent<Layout>();
}
}
layout.testFunction();
totalKillsNeeded = layout.waves;
When I run the code, nothing happens. No errors or anything. testFunction doesn't run, despite my Visual Studio showing the reference between the two scripts, and totalKillsNeeded returns 0 despite me checking and seeing that layout.waves equals 1 or 2. I have tried multiple methods of getting the Layout script, all of which have returned the same result. It is probably something small I havn't considered, but I still have not been able to figure it out. Thank you!
Your code should work, but in case, try this. Here's ScriptA.cs, put this on the parent
using UnityEngine;
public class ScriptA: MonoBehaviour
{
int totalKillsNeeded = 0;
ScriptB layout;
// Start is called before the first frame update
void Start()
{
foreach(Transform child in transform)
{
if(child.CompareTag("Layouts"))
{
layout = child.gameObject.GetComponent<ScriptB>();
}
}
layout.testFunction();
totalKillsNeeded = layout.waves;
Debug.Log($"Total Kills needed: {totalKillsNeeded}, layout waves {layout.waves}");
}
}
And ScriptB.cs, put this on the Child game objects, and set the wave in inspector if needed
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ScriptB: MonoBehaviour
{
public int waves = 12;
public void testFunction()
{
Debug.Log("Test Function Called, waves: {waves}");
}
}
Console output:
The hierarchy should look something like this:
If your last child has 0 waves, your for loop will only show the last one:
my character shoots arrows. She starts without zero arrows and cannot shoot any until she picks up an arrow icon. Arrow icons have a value of 3. After this she can shoot arrows. That code works fine. Now I have to make it so these arrows decrease in value through the UI text display. The UI text value changes from 0 to 3 when an arrow icon is picked up, but it doesn't decrease when I shoot an arrow. I have another game object with a script that will detect when an arrow is shot. when this happens, it tells that main script that, "hey, an arrow was just shot." The focus is on getting the Text to decrease when I shoot an arrow.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class arrowManager : MonoBehaviour {
private Text text;
public static int arrowCount;
public static int arrowRecount;
private int maxArrows = 99;
void Start ()
{
text = GetComponent<Text> ();
arrowCount = 0;
}
void Update ()
{
FullQuiver ();
arrowCounter ();
}
void arrowCounter()
{
if (arrowCount < 0) {
arrowCount = 0;
text.text = "" + arrowCount;
}
if (arrowCount > 0)
text.text = "" + arrowCount;
}
public static void AddPoints(int pointsToAdd)
{
arrowCount += pointsToAdd;
}
public static void SubtractPoints(int pointsToSubtract)
{
arrowCount -= pointsToSubtract;
}
public void FullQuiver()
{
if (arrowCount >= maxArrows)
{
arrowCount = maxArrows;
}
}
}
the game object with the script that detects arrows looks like this.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class arrowDetector : MonoBehaviour {
public int pointsToSubtract;
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "arrow")
{
arrowManager.SubtractPoints (pointsToSubtract);
}
}
}
Forgive me if I've misunderstood, but it looks to me like you are subtracting from the wrong variable.
Since you are displaying the 'arrowCount' variable, I imagine that's what should be subtracted from.
public static void SubtractPoints(int pointsToSubtract)
{
if (arrowCount > 0) {
arrowCount -= pointsToSubtract;//pointsToSubtract is an int value passed to this script from my player script whenever she shoots an arrow.
}
}
In SubtractPoints method you are detracting from the variable "arrowRecount".
Wouldn't you want to be subtracting from "arrowCount" instead? If you used "arrowCount" your text value should update properly.
I figured it out. Before, I was trying to get it to detect my arrows whenever a bool became true from my player script. That wasn't working so I said screw it and just made an empty that detects gameobjects with the tag "arrow." Then I updated the script in here to reflect that. I was dead tired last night after not getting any sleep for two days so I forgot to put in a value of pointsToSubtract in the hierarchy. Thanks everyone for their responses.
I want to change the UI image in random order. I have a gameobject in UI(canvas) containing Image component and it has null image initially. I have a script attached to it(gameobject) to change the image on run time.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class changeImg : MonoBehaviour {
public Sprite sprite1;
public Sprite sprite2;
public Sprite sprite3;
void Start()
{
ChangeImg();
}
void ChangeImg()
{
int rand=Random.Range(0,3);
if(rand==0)
{
gameObject.GetComponent<Image> ().sprite = sprite1;
//gameObject.GetComponent<UnityEngine.UI.Image> ().sprite = sprite1;
}
else if(rand==1)
{
gameObject.GetComponent<Image> ().sprite = sprite2;
// gameObject.GetComponent<UnityEngine.UI.Image> ().sprite = sprite2;
}
else if(rand==2)
{
gameObject.GetComponent<Image> ().sprite = sprite3;
//gameObject.GetComponent<UnityEngine.UI.Image> ().sprite = sprite3;
}
}
}
I have assigned the public field (sprite1,sprite2,sprite3) in inspector. And I tried the both option as I had commented in code. I did not get an error but also the image did not get change as I want. During runtime of a program, GameObject(to which the script is attached) has null image source as it was initially.
Use overrideSprite field instead of sprite - documentation
Unfortunately, unity ui is full of such pitfalls and it's api is totally counter-intuitive, so you have to be careful and check the docs regularly
You can also just use Image if you are in Unity 2017.3 (not sure if this works for older versions). For example:
using UnityEngine.UI;
-----
public Image ObjectwithImage;
public Sprite spriteToChangeItTo;
void Start () {
ObjectwithImage.sprite = spriteToChangeItTo;
}
Works great for me.
Have you checked the position of the Gameobject? Also the color of the image?
To change the Image from a Button, don't use GetComponent<Image> () as you can potentially get another Image component that does not belong to the button. It can also return null if the object is disabled.
Use the Button.image.sprite or Button.image.overrideSprite variable instead.
public Button pb;
public Sprite newSprite;
void Start()
{
pb.image.sprite = newSprite;
}
Or
pb.image.overrideSprite = newSprite;
It really doesn't matter which one is used. Any of these two should work.