my start function works fine when i start a scene but after reloading it or going to another level it has some problems.
When my player dies i hide some canvas elements and show "restart" and "mainMenu" buttons. but when i reload the game reset/mainMenu buttons are still shown and other elements that i had hidden when player died are still hidden ?!
void Start () {
Debug.Log("LOL");
mainMenu.SetActive(false);
reset.SetActive(false);
}
void Update()
{
bool r = true;
if(Player.Life <= 0 && r == true)
{
reset.SetActive(true);
mainMenu.SetActive(true);
panel.SetActive(false);
r = false;
}
}
UPDATE :
Suddenly my problem has solved?!!
i just closed and opened my project again and it works correctly ?!
Related
Just need a way to get around this problem. I know what the issue is, I just need a viable solution.
So basically I have a script called MouseManager, which detects if you're looking at a specific game object and if you press "f" it tells another script, called UIManager, to open the GameObject's panel (I have a game where you can press f on a console and it enables a UI with a puzzle).
Basically, I want the user to be able to press "f" or "esc" and have it exit the panel, however if you press "f", it disables the panel but instantly re-enables it as you're still looking at the gameobject, and both checks are in Update()
I need a workaround, if anyone knows one PLEASE comment as this issue is getting on my nerves :P
Thanks
EDIT: By console I mean there's a GameObject that looks like a console.
EDIT 2: Here's the code, I'll put some comments in it so you can understand what each thing does. I will be refactoring it soon because it's messy...
void Start()
{
uiPuzzles = GameObject.Find("PuzzlesUI").GetComponentInChildren<UIManager>(); // Currently I have the UIManager set to a canvas called PuzzlesUI. I will soon be moving it to an empty GameObject.
}
void Update()
{
if (!uiPuzzles.invActive && !uiPuzzles.puzzleActive) // invActive and puzzleActive are two public booleans that just show if the inventory or any puzzle panel is empty (UIManager handles opening and closing the inventory too)
{
if (Input.GetButtonDown("Use") && !uiPuzzles.invActive && !uiPuzzles.puzzleActive) // Use key is bound to "f". Currently Im just checking if puzzleActive and invActive are still false.
{
ray = GetComponentInChildren<Camera>().ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 7)) // Raycast where you're looking
{
uiPuzzles.openPuzzleOverlay(hit.collider.name); // function in UIManager which will check if the hit collider is in a list of all the puzzle colliders currently added and if it is, open that panel.
}
}
}
}
As for UIManager:
public void openPuzzleOverlay(string collider) // Get a panel name
{
foreach (Puzzle item in puzzleList)
{
item.panelGameObject.SetActive(false); // Disable all puzzle panels.
if (item.consoleGameObject.name == collider) // unless its the given panel,
{
item.panelGameObject.SetActive(true); // then enable it.
Cursor.lockState = CursorLockMode.None; // Unlock the mouse.
Cursor.visible = true; // Show the mouse.
DisablePlayerUI(); // Disable the UI (e.g. crosshair)
puzzleActive = true; // Disable movement. (Because player movement requires puzzleActive and invActive to also be false
}
}
}
void Update ()
{
if (Input.GetButtonDown("Use") && puzzleActive && !invActive && // If you want to use a console and the puzzle is already active
!puzzleList.Where(p => p.panelGameObject.activeSelf).FirstOrDefault().panelGameObject.GetComponentInChildren<InputField>().isFocused) // Check if the currently active panel's input field is not focused.
{
ClosePuzzleOverlay(); // Close the puzzle.
EnablePlayerUI(); // Enable the UI.
}
}
public void ClosePuzzleOverlay()
{
foreach (Puzzle item in puzzleList)
item.panelGameObject.SetActive(false);
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Locked;
puzzleActive = false;
}
The problem is being caused by the two input checks. When F is pressed both are true so the UI is being closed and then opened in the same frame.
Take the Input code out of UIManager and keep it in one place. Then you can rework your input class to be something like this:
//MouseManager Update
if(Input.GetButtonDown("Use")){
if(uiPuzzles.isActive)
uiPuzzles.Hide();
else
uiPuzzles.Show(GetPuzzleName());
}
Now it will only call either open or close on the frame which F is pressed down.
So this should be a simple answer but I cannot seem to find it anywhere. In Unity, I have a toggle box I want to turn off when the game starts, but unlike most game objects or text, SetActive does not work with toggle boxes. What is the command to turn the graphic off?
public void StartGame () {
mainText.SetActive (false);
startButton.SetActive (false);
StartCoroutine (SpawnBalls ());
//Turn off toggle box graphic
playing = true;
}
public void AddBall () {
if (ballBox.isOn) {
ballNumber = 3;
//Debug.Log ("yes");
} else {
ballNumber = 2;
}
If I understand you correctly you want to be able to remove the display of the toggle on the start of the game? If so set a reference to the toggle you want to click on and off heres a small example:
Toggle T = GameObject.Find("myToggle").GetComponent<Toggle>();
T.gameObject.SetActive(false);
Make a reference to it and you should be able to click it of and on as you need it tested it out on a game I'm working and it worked for me let me.
I am trying to change character animations using a script, based on key inputs, but Unity seems to only play the default "standing idle" animation and occasionally switching to the "crouched idle", is there a different way to handle animations or am I just doing the script wrong? Here is my script as it currently stands
using UnityEngine;
using System.Collections;
public class CharacterControl : MonoBehaviour {
private Animator animator;
public bool crouched;
private string sc;
// Use this for initialization
void Start () {
animator = GetComponent<Animator> ();
}
// Update is called once per frame
void Update () {
if (crouched == true) {
sc = "crouch";
} else {
sc = "standing";
}
animator.Play (sc + "_idle");
if (Input.GetButton ("Fire3")) {
if (crouched == false) {
crouched = true;
} else {
crouched = false;
}
}
}
}
Try replacing
if (Input.GetButton ("Fire3")) {
if (crouched == false) {
crouched = true;
} else {
crouched = false;
}
}
with
if (Input.GetButton ("Fire3")) {
crouched = true;
} else {
crouched = false;
}
Now, when you hold down the "Fire3" button, your character should crouch, and when you release it he/she should stand again
Also a suggestion: Put the other code in the function (if (crouched == true) ... animator.Play (sc + "idle"); after this code (the Input.GetButton check). That way, your character should instantly start crouching the same frame that the button is pressed; otherwise, he/she will the frame after
Explanation
Input.GetButton will return true while you're pressing down (in the middle of clicking or touching) on the button each frame. Each time Update is called (around 1/60th of a second) your code will check if you're pressing down, and toggle crouched. When you click/tap the button, you'll likely be pressing down for a few frames, so crouched will switch from true to false, back and forth, a few times. In some cases (when you press down for an odd number of frames) crouched will be switched, but in other cases (when you press down for an even number of frames) crouched will stay as it was before you clicked on the button, preventing your character from crouching, or standing if he was crouching before.
Source: From the official API: Input.GetButton
I would strongly suggest using animation states and transit from one to another when you get an input. Checkout my answer at: Unity 2D animation running partially
Yes you can do the toggle action like this
void Update()
{
if(Input.MouseButtonDown(2))
{
crouched = true;
}
if(Input.MouseButtonUp(2))
{
crouched = false;
}
}
You can try this code:
crouched = Input.GetButtonDown("Fire3") ? true : false;
I am trying to have a simple animated loading screen between my menu scene and the game scene. I am trying to do this by loading the game scene in my loading scene asynchronously. I also want the loading screen to fade in and fade out.
I got the fade-in to work. However, I have two problems which I have been working on for hours, but without any succes. These problems are:
I cannot get the fade-out to work. I tried setting the 'allowSceneActivation' to false for my asynchronous loading, however this causes the loading to not occur at all. Removing this line makes the game load, but it then lacks the fade out.
The animation works very (and I mean VERY) choppy. I understand that the game is loading stuff, so I expect it to be bad, but it's litterally doing a frame every 2 seconds. I tried using a low thread priority (see code below), but no luck. I found people with similar problems, but the frames turned out reasonable when using a lower thread priority.
This is my code for the loading screen:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LoadIntro : MonoBehaviour {
private bool loaded;
private bool fadingOut;
private bool loading;
AsyncOperation async;
void Start(){
loaded = false;
fadingOut = false;
loading = false;
Application.backgroundLoadingPriority = ThreadPriority.Low;
}
// Use this for initialization
void Update() {
//wait for loading screen to fade in, then execute once
if (!GameObject.Find ("SceneFader").GetComponent<Image> ().enabled && !loaded && !loading) {
loading = true;
async = Application.LoadLevelAsync(mainMenuButtons.leveltoload);
async.allowSceneActivation = false;
StartCoroutine (LoadLevel (async));
}
//if next scene is loaded, start fading out loading screen
if (loaded) {
GameObject.Find ("SceneFader").GetComponent<SceneFadeInOut> ().FadeToBlack();
fadingOut = true;
}
//when faded out, switch to new scene
if (GameObject.Find ("SceneFader").GetComponent<Image> ().color.a >= 0.95f && loaded) {
async.allowSceneActivation = true;
}
}
IEnumerator LoadLevel(AsyncOperation async){
yield return async;
Debug.Log("Loading complete");
loaded = true;
}
}
I have a seperate piece of code for the actual fading, which the code above calls:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class SceneFadeInOut : MonoBehaviour
{
public float fadeSpeed = 1.5f; // Speed that the screen fades to and from black.
private bool sceneStarting = true; // Whether or not the scene is still fading in.
public bool sceneEnding = false;
public string scene;
private Image fadeTexture;
void Awake ()
{
fadeTexture = GetComponent<Image>();
}
void Update ()
{
// If the scene is starting...
if(sceneStarting)
// ... call the StartScene function.
StartScene();
if (sceneEnding)
EndScene();
}
void FadeToClear ()
{
// Lerp the colour of the texture between itself and transparent.
fadeTexture.color = Color.Lerp(fadeTexture.color, Color.clear, fadeSpeed * Time.deltaTime);
}
public void FadeToBlack ()
{
// Lerp the colour of the texture between itself and black.
fadeTexture.color = Color.Lerp(fadeTexture.color, Color.black, fadeSpeed * Time.deltaTime);
}
void StartScene ()
{
// Fade the texture to clear.
FadeToClear();
// If the texture is almost clear...
if(fadeTexture.color.a <= 0.05f)
{
// ... set the colour to clear and disable the GUITexture.
fadeTexture.color = Color.clear;
fadeTexture.enabled = false;
// The scene is no longer starting.
sceneStarting = false;
}
}
public void EndScene ()
{
// Make sure the texture is enabled.
fadeTexture.enabled = true;
// Start fading towards black.
FadeToBlack();
// If the screen is almost black...
if (fadeTexture.color.a >= 0.95f) {
// ... reload the level.
if (scene == "") Application.Quit();
else Application.LoadLevel (scene);
}
}
}
Does anyone have an idea how to solve the issues described above? I've litterally tried every topic I could find, but none of them seem to work. Building my game did not resolve the issues either.
Many thanks in advance!
You are fading out when scene loading gets done. What are you expecting when loading is done? :)
//if next scene is loaded, start fading out loading screen
if (async.isDone) {
GameObject.Find ("SceneFader").GetComponent<SceneFadeInOut> ().FadeToBlack();
fadingOut = true;
}
Obviously it will change the scene and you code doesn't getting enough time to perform fade-out operation. :)
For instance if consider your point. You wrote,
//if next scene is loaded, start fading out loading screen
if (loaded) {
GameObject.Find ("SceneFader").GetComponent<SceneFadeInOut> ().FadeToBlack();
fadingOut = true;
}
//when faded out, switch to new scene
if (GameObject.Find ("SceneFader").GetComponent<Image> ().color.a >= 0.95f && loaded) {
async.allowSceneActivation = true;
}
in Update. Here your loaded check doing 2 things.
1- Start fading out.
2- Switching scene.
Again, why it should wait for fading it out completely while its getting loaded and you are checking alpha >= 0.95 which should execute at first frame when you get loaded to true, because I believe that in first frame alpha would be greater than 0.95.
I have an FBX object with animation. The object is a box with animation for opening. What I'm trying to do is when the user clicks a button the box will open (play open animation) and when the button is clicked again the box will close (play open animation backwards).
While the opening animation is playing and I click the button again the opening animation stops and the box starts to close, that works fine.
The problem is that when the animation is finished (open) and then I click the button to close, the animation is not playing and it just jumps to a closed box without animation.
Here is my code:
public class ClickBtn : MonoBehaviour {
public GameObject box = null;
bool reverse = false;
private void OnMouseDown()
{
Debug.Log(reverse);
if (!reverse)
{
box.animation["Take 001"].speed = 1;
}
else
{
box.animation["Take 001"].speed = -1;
}
reverse = !reverse;
box.animation.Play("Take 001");
}
}
your animation.WrapMode is set wrong (probably WrapMode.Once, which is default). In your case you could use:
WrapMode.PingPong: Ping Pong's back and forth between beginning and end.
animation.wrapMode = WrapMode.PingPong;
Mind you, you don't need
box.animation["Take 001"].speed = -1;
anymore, this is done automatically.
When animation is finished its time is reseted to beginning.
Simple workaround set time to end before playing backwards.
public GameObject box;
bool direction = false;
private void OnMouseDown()
{
Debug.Log(direction);
if (!direction)
{
box.animation["Take 001"].speed = 1;
}
else
{
box.animation["Take 001"].speed = -1;
//if animation already finisihed, set time to end before playing it backwards
if(!box.animation.isPlaying){
box.animation["Take 001"].time =box.animation["Take 001"].clip.length;
}
}
direction = !direction;
box.animation.Play("Take 001");
}