Trying to write a script that's on several different objects where on mouseclick, 1 is added to a defined variable which then prints out. Currently when I click the objects, 1 is always printed.
#pragma strict
import UnityEngine.UI;
var theImage:UnityEngine.UI.Image;
var theSprite:Sprite; //The image you want to drag in the inspector
private var clickCount = 0;
function OnMouseDown () {
theImage.sprite = theSprite;
clickCount++;
Debug.Log(clickCount);
}
Here's my script. It also changes a GUI sprite. Seems like an easy fix, not sure where I've gone wrong.
Related
so I wanted to create a secret or something in my game. Basically what i wanted to ask is how do you make a button work after clicking it a 100 times. After clicking a 100 times it should give me 100 money. Im new to unity so it would be nice if you could explain it more precise. I tried this code:
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class SecretButton : MonoBehaviour
{
public int clickcounter = 0;
public TMP_Text scoreText;
int moneyAmount;
void Start()
{
}
void Update()
{
if (clickcounter == 100)
{
moneyAmount += 100;
PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
moneyAmount = PlayerPrefs.GetInt("MoneyAmount");
scoreText.text = moneyAmount.ToString();
}
}
public void increaseClicks()
{
clickcounter++;
}
}
but it started giving me 100 money all the time, but i wanted it to give me only once 100 money.
Easiest way I can think of is creating a variable _counter assigned to the button and increase it by one for each button press.
inside the button press function, include an if statement that checks whether the _counter>100 and in that case it starts the followup actions, otherwise it skips the action.
The answer is quite high level, but if you want more details, you have to share more details about what you are trying to accomplish
update:
I can see in your edit the code now, your additional problem with giving 100 money multiple times is because you don't make this function execute only once.
You can solve this by adding another variable _secret_available and initiate it as True, when the function is activated, set the variable to False.
You also need to edit the if clause to be like this:
if(counter ==100 && _secret_available)
Also my suggestion would be to replace counter==100 with counter >=100 so that you don't have possible bugs in case the counter jumps from 99 to 101 without passing by 100. Might not be a problem in the moment but I believe it is more robust
I just want to ask how can I multiple the buttons by using the input field? Like for example, I typed 100 in the input field and then the buttons will become 100. Please bear in mind that I'm new in Unity. Thank you!
First you need to define what button you want to instantiate, on the UI Canvas or a 3D world button.
public class TestingScript : MonoBehaviour{
// the button to create
public GameObject button;
}
You need to create a prefab or assign an existing button in the world for the script to use as a template when creating them. Next you need to create the input field itself and assign the reference to it through code or in the inspector view, here I am going to have it assigned in the inspector.
// assigned in inspector view
public TMP_InputField inputField;
It should look like this in the component view
Now where you call the function is your choosing, I am doing it through a unity button on which I have the script attached
The method here would look something like this
public void CreateButtons()
{
// here we assume the input is always an integer, otherwise you would create a try catch clause
int amount = int.Parse(inputField.text);
// using world 0 position here, you would need to define where you want them yourself
Vector2 pos = new Vector2(0, 0);
for (int i = 0; i < amount; i++)
{
// the loop will execute the amount of times read from input field
Instantiate(button, pos, Quaternion.identity);
pos.x += 0.5f;
}
}
Note I am using TextMeshPro elements here but the standard unity ones would work too.
In my 2D project I create a canvas and a button in code. I would like to set the text of the button in code, but after numerous attempts I can't seem to do it.
My UnityScript code:
#pragma strict
var loginButton : UnityEngine.UI.Button;
function Start () {
var canvas = new GameObject ("canvas", Canvas);
var instance : UnityEngine.UI.Button = Instantiate(loginButton);
instance.GetComponent(UnityEngine.UI.Text).text = "login"; //Error below
instance.transform.position = Vector2(0,0);
instance.transform.SetParent(canvas.transform);
}
This provides an error
"NullReferenceException: Object reference not set to an instance of an object
GameLogicLogin.Start () (at Assets/GameLogicLogin.js:11)"
--------------------------------Edit---------------------------------------
The generated hierarchy looks like this: http://puu.sh/iMYe6/4f4a8f545c.png
On the left at the bottom is the prefab I link to the script.
The following line doesn't cause an error and seems to change the text, but the change doesn't show up in game nor does the original text assigned to the "Text"in the prefab.
instance.GetComponentInChildren(UnityEngine.UI.Text).text = "login";
If you would of built your button in the unity editor you could easily change its text in script like this:
var button = GameObject.Find("buttonObjectName").GetComponent<Button>();
button.GetComponentInChildren<Text>().text = "What ever you like";
I imagine you can easily adjust this to fit your needs without being spoon fed.
You are instantiating a UnityEngine.UI.Button, that doesn't have a component for UnityEngine.UI.Text hence the error.
Is there any reason why you are instantiating that object?
If you are linking in the editor a game object to loginButton, and I think you are, you should do something like this:
var comps = loginButton.gameObject.GetComponentsInChildren(UnityEngine.UI.Text);
comps[0].text = "login";
I'm programming a simple game (the first one I do on my own) in which basically there are two scoring goals, and when a player scores, I want to reset the position for all players to some coordinates.
I have a script attached to the goals, which detects collision with the ball, as follows:
Goal.js
#pragma strict
function OnTriggerEnter2D (hitInfo : Collider2D) {
if (hitInfo.name == "Ball")
{
var wallName = transform.name;
GameManager.Score (wallName);
hitInfo.gameObject.SendMessage ("ResetBall");
//Here I need to call the ResetPlayer function
PlayerControlHS.ResetPlayer();
}
}
The following script is attached to the players
PlayerControlHS.js
#pragma strict
var resetPosX : float;
var resetPosY : float;
//keys
var moveUp : KeyCode;
var moveLeft : KeyCode;
var moveRight : KeyCode;
var speed : int = 4;
function Update () {
if (Input.GetKey(moveUp)) {
rigidbody2D.velocity.y = speed;
}
if (Input.GetKey(moveLeft)) {
rigidbody2D.velocity.x = -speed;
}
else if (Input.GetKey(moveRight)) {
rigidbody2D.velocity.x = speed;
}
else {
rigidbody2D.velocity.x = 0;
}
}
function ResetPlayer () {
Debug.Log("I'm being called");
}
Both the goals and the players have a RigidBody 2D and a collider of some kind, as well as the ball.
I've gotten to get the function called as it is right now, but if I try to modify the position coordinates of a player, I enter a loop of death errors that when I fix one, I get another one.
That happens when I put this code in ResetPlayer():
rigidbody2D.position.x = resetPosX;
rigidbody2D.position.y = resetPosY;
Mostly, the errors are because I need an object of type PlayerControlHS to access those fields. I've tried adding a variable of that type (and referencing it to each player) but it doesn't work because it tells me I need an object to access that variable... I don't know how to initialize it if I make it static.
How could I get it working?
EDIT: I'm thinking the best approach would be sending a message just like the ResetBall one, but it doesn't work (I think because the function is called from ball, object of another type and it can't find the function). This way, the function ResetPlayer could stop being static. But I'm not sure if this is right, since I can't get it without compile errors.
EDIT2: It worked, even though I had to put it one liner
hitInfo.gameObject.GetComponent(PlayerControlHS).ResetPlayer();
Because Unity was telling me that I needed to put a semicolon here (I don't understand :S):
PlayerControlHS playerScript ; = hitInfo.gameObject.getComponent(PlayerControlHS);
But I still can't get to modify the variables of the position...
I have tried fixing it but I get an error saying that "I need an instance of type UnityEngine.Component to access non static member 'rigidBody2D' in a variable declaration I made
static var test : PlayerControlHS = rigidbody2D.GetComponent(PlayerControlHS);
And the code I'm trying in ResetPlayer:
test.GetComponent(PlayerControlHS).rigidbody2D.position.x = test.GetComponent(PlayerControlHS).resetPosX;
test.GetComponent(PlayerControlHS).rigidbody2D.position.y = test.GetComponent(PlayerControlHS).resetPosY;
Try changing this line:
PlayerControlHS.ResetPlayer();
To this:
PlayerControlHS playerScript = hitInfo.gameObject.getComponent(PlayerControlHS);
playerScript.ResetPlayer();
That is how you call a function from another script.
EDIT 1:
Sorry I got mixed up with C# even though you are using javascript, I figured out why you got that error. There's a slight difference in variable declaration.
Change the above code to this:
var playerScript:PlayerControlHS = hitInfo.gameObject.GetComponent(PlayerControlHS);
playerScript.ResetPlayer();
As for resetting the player's position, the script is inside the player game object is it not? Then you can just simplify it like this:
function ResetPlayer () {
rigidbody2D.position.x = resetPosX;
rigidbody2D.position.y = resetPosY;
}
Really sorry for that :(
I'm learning unity scripting. But I don't understand the following :
static private var lastRecalculation = -1;
static function RecalculateValue () {
if (lastRecalculation == Time.frameCount)
return;
ProcessData.AndDoSomeCalculations();
}
I don't get the third line or the condition in the IF statement. I know its a bit amateur, but pls help.
Thank You.
This is from the Time.frameCount documentation. This example shows how to create a function that executes only once per frame, regardless of how many objects you attach your script to. I suspect though that this example is incomplete because it never updates lastRecalculation (or it was assumed you would do so in AndDoSomeCalculations() ).
The reason setting lastRecalculation = -1 initially is so this function runs during the first frame.
Working version:
static var lastRecalculation = -1;
static function RecalculateValue () {
if (lastRecalculation == Time.frameCount) {
return;
}
lastRecalculation = Time.frameCount;
Debug.Log (Time.frameCount);
//ProcessData.AndDoSomeCalculations();
}
function Update () {
RecalculateValue();
}
Attach this script to 2 different GameObjects and run it. You will only see unique frame values 1,2,3,4,5.... even though 2 GameObjects are each calling RecalculateValue()
Now comment out the return and run it again. Now the ProcessData portion of that code runs for both objects every frame and you'll see something like 1,1,2,2,3,3,4,4......