I'm having a bit of trouble with some Unityscript.
What I want to do is have a GUI message appear when certain objects are touched (then vanish after a time). I think I have it mostly worked out, but the message trips automatically.
My attempted solution is to have a conditional part of the GUI message that only allows it to appear when a boolean is true. Then in a different script that is already tripped when the object is touched, the boolean is set to true, so the script can run, and reset the boolean to false.
However I'm getting a "You can only call GUI functions from inside OnGUI. I'm not sure what that means.
Message code:
youdied.js
static var deathMessageShow : boolean = false;
function OnGUI() {
if(deathMessageShow == true){
if(Time.time >= 5 )
GUI.Box(Rect(200,300,275,150),"You Died");
}
deathMessageShow = false;
}
Other code (truncated):
dead.js
function OnTriggerEnter()
{
//code that resets environment
youdied.deathMessageShow = true;
}
Any suggestions on what is going on, or a better solution would be greatly appreciated.
The following code will show GUI message for 5 seconds then hides it:
youdied.js
static var deathMessageShow : boolean = false;
function OnGUI()
{
if(deathMessageShow)
{
GUI.Box(Rect(200,300,275,150),"You Died");
// call the function HideDeathMessage() after five seconds
Invoke("HideDeathMessage", 5.0f);
}
}
function HideDeathMessage()
{
deathMessageShow = false;
}
Other code:
dead.js
function OnTriggerEnter()
{
//code that resets environment
youdied.deathMessageShow = true;
}
Related
I have an action that is mapped to both my left amd right hand triggers on my VR controllers. I would like to access these instances...
Player.instance.rightHand
Player.instance.leftHand
...depending on which trigger is used but I can't fathom the proper way to do it from the SteamVR API. So far the closest I have gotten is this...
public SteamVR_Action_Boolean CubeNavigation_Position;
private void Update()
{
if (CubeNavigation_Position[SteamVR_Input_Sources.Any].state) {
// this returns an enum which can be converted to string for LeftHand or RightHand
SteamVR_Input_Sources inputSource = CubeNavigation_Position[SteamVR_Input_Sources.Any].activeDevice;
}
}
...am I supposed to do multiple if statements for SteamVR_Input_Sources.LeftHand and SteamVR_Input_Sources.RightHand? That doesn't seem correct.
I just want to get the input device that triggered the action and then access it using Player.instance.
I was also looking for an answer to this. I've for now done what I think is what you mean with the if-statements. It works, but definitely not ideal. You want to directly refer to the hand which triggered the action, right?
With the 'inputHand' variable here I get the transform.position of the hand from which I will raycast and show a visible line. I could have put a separate instance of a raycastScript like this on each hand, of course, but I wanted to make a 'global' script, if that makes sense.
private SteamVR_Input_Sources inputSource = SteamVR_Input_Sources.Any; //which controller
public SteamVR_Action_Boolean raycastTrigger; // action-button
private Hand inputHand;
private void Update()
{
if (raycastTrigger.stateDown && !isRaycasting) // If holding down trigger
{
isRaycasting = true;
inputHand = inputChecker();
}
if (raycastTrigger.stateUp && isRaycasting)
{
isRaycasting = false;
}
}
private Hand inputChecker()
{
if (raycastTrigger.activeDevice == SteamVR_Input_Sources.RightHand)
{
inputHand = Player.instance.rightHand;
}
else if (raycastTrigger.activeDevice == SteamVR_Input_Sources.LeftHand)
{
inputHand = Player.instance.leftHand;
}
return inputHand;
}
i have a problem. iam making a game that have button for buy item , and the button have no issue, it run normally, but the problem is the button immediately executes the method without seeing that the method contains an if statement, so what is wrong here Here's the code :
public void TakeMoney()
{
int minusCoin = PlayerInfo.coin -= 5;
PlayerPrefs.SetInt("MyCoinAmount", minusCoin);
}
public void DisableBuyButton()
{
disableBuyButtonRocket3 = 1;
PlayerPrefs.SetInt("DisableBuyButtonRocket3", disableBuyButtonRocket3);
}
public void Buy()
{
int getPlayerCoin = PlayerInfo.coin;
if (getPlayerCoin > 4)
{
if (MyRocket._rocket3 == 1)
{
GetComponent<AudioSource>().Play();
MyRocket._rocket3 = 1;
PlayerPrefs.SetInt("Rocket3Bought", MyRocket._rocket3);
}
}
}
so the button will perform all of the 3 functions above, but as can be seen that I make an if statement so the item can only be purchased if we already have enough money, but when I try I try to reset all values, so my money by default it is 0, but I can buy the item and my money becomes a minus.
Btw, PlayerInfo above is a script from another scene.
Sorry for my bad english.
Your problem is that you do everything in separated methods. It's basically not a problem - but, when you execute them concurrently, it is. Also, your methods are completely independent of each other - an if statement in one will not affect the others' execution. The solution is that you first remove the event listeners to TakeMoney and DisableBuyButton. Then, call them from Buy. If you think it through, it is more logical. Also, remove the temporary variables, as they slow down your code a bit and also make it less readable. Final code could be something like this:
public void TakeMoney()
{
PlayerInfo.coin -= 5;
PlayerPrefs.SetInt("MyCoinAmount", PlayerInfo.coin);
}
public void DisableBuyButton()
{
PlayerPrefs.SetInt("DisableBuyButtonRocket3", 1);
}
public void Buy()
{
if (PlayerInfo.coin > 4) {
TakeMoney();
DisableBuyButton();
if (MyRocket._rocket3 != 1 /* changed this, because it seemed that you want to check whether it is NOT one */)
{
GetComponent<AudioSource>().Play();
// I changed the if statement because this
MyRocket._rocket3 = 1;
PlayerPrefs.SetInt("Rocket3Bought", MyRocket._rocket3);
}
}
}
the playerinfo.coin value would be more than 4 because it will decrease coin at click so it will minus only 5 at a click you could check playerinfo.coin value
I have a character that a Boolean flag which determines whether or not he is jumping (if he is jumping, he cannot jump again). When he jumps, the jump flag is set to true, and when he collides with something it is set back to false (so he can jump again).
However, he only jumps once, and jump stays true even when it's supposed to reset to false. Why is this so? My definition for OnCollisionEnter() is supposed to reset the flag.
var trump;
var jump = false;
function Start() {
// Assigns the Rigidbody to a variable
trump = GetComponent(Rigidbody2D);
// Variable Switches:
}
function OnCollisionEnter() {
jump = false;
trump.velocity.y = 0;
trump.velocity.x = 0;
}
function FixedUpdate() {
trump.velocity.x = Input.GetAxis("Horizontal") * 10;
if ((Input.GetKeyDown(KeyCode.UpArrow)) && (jump == false)) {
trump.AddForce(Vector2(0, 10), ForceMode2D.Impulse);
jump = true;
}
}
EDIT: Based on an answer given I tried adding the Collision parameter to OnCollisionEnter(), but it still doesn't look like the function is being called after I added a Debug.Log() inside of it to check. Is there something else wrong?
function OnCollisionEnter(collision: Collision) {
jump = false;
Debug.log("He Hit The Wall");
trump.velocity.y = 0;
trump.velocity.x = 0;
}
Your function signature for OnCollisionEnter() is incorrect. When defining these MonoBehaviour-specific functions, it is imperative that the name and parameters of the function match that shown in the documentation. Otherwise, the MonoBehaviour won't recognize them and the function won't be called when expected.
In this case, OnCollisionEnter() requires a Collision parameter:
function OnCollisionEnter(collision: Collision) {
jump = false;
trump.velocity.y = 0;
trump.velocity.x = 0;
}
Note: The above was written before the question was edited to implement the suggestion - before, OnCollisionEnter() was being defined without a parameter.
However, in your case that isn't the only problem - you're using Unity's 2D physics, which means you should actually be using the 2D variant of the function: OnCollisionEnter2D, which also takes a slightly different parameter of a Collision2D.
So you would need:
function OnCollisionEnter2D(collision: Collision2D) {
jump = false;
trump.velocity.y = 0;
trump.velocity.x = 0;
}
Hope this helps! Let me know if you have any questions.
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......
I have a problem to display a text at run time in my game for a second , so I want to know if its possible to add or remove a GUI label to the seen at run time ?
Do you mean something like this?
void OnGUI() {
if (textShouldBeShown) {
GUI.Label(new Rect(10f, 10f, 100f, 50f), "MyText");
}
}
GUI components get drawn on every frame. the OnGUI() function is just like the Update() function except that unlike the Update() function GUI components can be called in it.
You can think of OnGUI as a loop. It will call GUI components declared inside of it in order, then do it all over again every frame. So if you hook into this loop and block some components from being called at runtime, the very next frame those componants will not be rendered.
Here is a set of functions that can allow you to do this is a specified time:
private bool guiIsOn = true;
private void TurnOffGUIInSeconds(int seconds)
{
StartCoroutine(_TurnOffGUIInSeconds(seconds));
}
private IEnumerator _TurnOffGUIInSeconds(int seconds)
{
yield return new WaitForSeconds(seconds);
guiIsOn = false;
}
void OnGUI()
{
if(guiIsOn)
{
GUI.Label(new Rect(5,5,5,5), "Label text");
}
}