I'm using this code to fade in a CanvasGroup at the beginning of my scene loading, and then if the player loses I want to fade out the scene and reload it from the beginning.
void Update () {
if (Time.time < 1 && fade.alpha >= 0)
fade.alpha = .99f - Time.time;
if (fadeOut)
fade.alpha += .02f;
if (fade.alpha >= 1)
{
Debug.Log("Change scene");
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
The problem is that when it hits this it shows the gamescene twice in the hierarchy, and neither one on the screen. I'll upload a picture below. When it does this is also hits the Debug.Log repeatedly. Does this not work if it's the only scene in the project? Only thing I can think of.
I've updated the method to include a boolean to ensure it SHOULD only run one time. Somehow it is still running countless times until I end the unity editor. The new update method is this :
void Update () {
if (Time.time < 1 && fade.alpha >= 0)
fade.alpha = .99f - Time.time;
if (fadeOut)
fade.alpha += .02f;
if (fade.alpha >= 1 && !reloadStarted)
{
Debug.Log("Change scene");
reloadStarted = true;
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
I guess Update is executed more rapidly than the scene is reloaded. So it starts to reload on every update. Introduce a bool property to indicate, that reload is already started.
if (fade.alpha >= 1 && !isReloadStarted)
{
Debug.Log("Change scene");
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
isReloadStarted = true;
}
Furthermore according to your description, you might want to reload when fade.alpha is less or equal to 0.
fade.alpha <= 0
I ended up refactoring the code and implementing this in a completely different way. I still don't know why it was acting so weird.
Related
I am trying to get my 'player' to change directions with my below script
however, it is contently staying stuck in the first 2 if statements of my 'void Update()'
I am trying to use these two scripts (1. https://pastebin.com/AGLatvUD (I wrote this one) and 2. https://pastebin.com/2XA3w04w)
I am attempting to use CharacterController2D to move my player with specified points and actions
Don't know if this is the right place to ask but I figured I'd try!!
void Update() // not sure if should have more in 'FixedUpdate' or others (maybe?)
{
if (isRight && transform.position.x > currentPoint.position.x) // flipping the character -- I'm pretty sure I can use TestCharacterController2D to do this for me, this is comparing the player's 'transform'
{
moveSpeed = -0.25f; // tells controller to head in the left direction
isRight = false; // no longer facing right
}
if (!isRight && transform.position.x < currentPoint.position.x) // reverse of above
{
moveSpeed = -0.25f; // tells controller to head in the right direction
isRight = true; // no longer facing left
}
if (transform.position == currentPoint.position) // checks to see if player is at 'currentPoint'
{
pause = true; // starts the pause sequenece
if (pause) // when the movement is pause do the the following
{
animator.SetFloat("Speed", 0); // player stops moving -- works!
if (maxPause <= 100) // checks to see if still paused
{
Debug.Log(maxPause);
maxPause--; // reduce pause amount (working way out of loop)
if (maxPause < 0) // found 'maxPause' was going to far below zero
maxPause = 0;
}
if (maxPause == 0) // when 'maxPause' timer has finished
{
pointsSelection++; // move to netx point
maxPause = 100; // reset 'maxPause' timer
pause = false; // resume 'transform.position == currentPoint.position' process
}
}
if (pointsSelection == points.Length) // makes sure 'pointsSelection' doesn't go out of bounds
pointsSelection = 0; // start the player's movement process over again
}
else // not sure if requried
Debug.Log("removed pause = false");
any help would be appreciated!!!
Thank you very much!!
I am an amateur (obviously :))
littlejiver
There's nothing that sets the character's position exactly to currentPoint. There are a number of ways to solve this. One way is to check if the character is near the currentPoint instead of exactly on it.
if (Vector2.Distance(transform.position, currentPoint.position) < 0.1f) {
pause = true; // starts the pause sequenece
...
I'm completely stumped by this one. I have a book in game and when you are looking in its general direction while within a certain distance of it and press the Action button (e or left mouse click), it's supposed to display a UI panel (bookPage). Here's my code for it.
void Update () {
Vector3 direction = player.transform.position - this.transform.position;
angle = Vector3.Angle (direction, player.transform.forward);
distance = direction.magnitude;
if (angle >= 160 && distance <= 2 && !bookPage.activeSelf) {
if(Input.GetButtonDown("Action")) {
bookPage.SetActive (true);
}
}
if (bookPage.activeSelf && Input.GetButtonDown("Action")) {
bookPage.SetActive (false);
}
}
This doesn't work. Specifically, the line to set the page to active doesn't work. If it's open, it will close correctly. If I copy and paste bookPage.SetActive (true);
anywhere within this method besides within if(Input.getButtonDown("Action")){}, it will make the bookPage active. If I put Debug.Log("message"); within that if statement though, it will show up in the console. It's just the one line that sets bookPage to active that isn't working. I have no idea why. I've tried moving it to a different method then calling it and doing the same but using a Coroutine. Neither worked. I also tried using other keys which did work, but I need it to work with the action key. It's also worth noting that the action key works in other usage. I already use it to open doors. Has anyone else run into a problem like this?
When you call SetActive(true), activeSelf will return true for your second condition which will invoke SetActive(false) immediately after.
Change this;
if (angle >= 160 && distance <= 2 && !bookPage.activeSelf)
{
if (Input.GetButtonDown("Action"))
{
bookPage.SetActive(true);
}
}
if (bookPage.activeSelf && Input.GetButtonDown("Action"))
{
bookPage.SetActive(false);
}
To this;
if (angle >= 160 && distance <= 2 && !bookPage.activeSelf)
{
if (Input.GetButtonDown("Action"))
{
bookPage.SetActive(true);
}
}
else if (bookPage.activeSelf && Input.GetButtonDown("Action"))
{
bookPage.SetActive(false);
}
My goal is simple, like a lot of applications, I want to make my cursor invisible after a certain time of inactivity of my user.
My solution doesn't seem really optimized, here's the algorithm :
void Start {
Timer t = new Timer(5000);//Create a timer of 5 second
t.start();
}
void Update {
if(MouseMoved){
t.reset();
}
timeLeft = t.deltaTime;
if ( timeLeft == 5000 )
{
Cursor.visible = false;
}
}
I really don't like to check at every frame if the mouse is moved, I'd prefer that my mouse moved trigger something, but I'm lost here, is anyone have a better solution ?
This should be the good way to achieve the task, using coroutine, without any memory issue:
private Coroutine co_HideCursor;
void Update()
{
if (Input.GetAxis("Mouse X") == 0 && (Input.GetAxis("Mouse Y") == 0))
{
if (co_HideCursor == null)
{
co_HideCursor = StartCoroutine(HideCursor());
}
}
else
{
if (co_HideCursor != null)
{
StopCoroutine(co_HideCursor);
co_HideCursor = null;
Cursor.visible = true;
}
}
}
private IEnumerator HideCursor()
{
yield return new WaitForSeconds(3);
Cursor.visible = false;
}
There are two ways to check for things like this outside of the update loop, that I know of:
1 - Custom Events.
Writing your own custom event would allow you to call something like "OnMouseMove()" outside of the update function and it would only execute when the mouse cursor's position changes.
2 - Coroutines
Creating a separate coroutine would allow you to perform this check less frequently. To do this, you make an IEnumerator and put your mouse movement logic in there. Something like:
IEnumerator MouseMovement()
{
while(true)
{
if(MouseMoved)
{
//Do stuff
}
yield return new WaitForSeconds(1f);
}
}
That coroutine would perform the check once every second while it is running. You would start the coroutine by saying:
StartCoroutine(MouseMovement());
And to stop it, you call
StopCoroutine(MouseMovement());
If you Start it when the timer reaches 0 and stop it when the cursor is moved, you can also prevent the coroutine from running all the time, only using it while the cursor is inactive.
I have an animatormanager able to create run time animation from 1 animation (start frame, end frame and delay then the speed is calculated, will do morphing and more later). My unity version is 5.3.1f1
Everything work fine, some stuff are not done but are optional. The animator can queue requested animation to prevent interupting the current one.
The thing is, I can only start 1 time an animation with an object. The code to launch the next animation is exactly the same but there is just nothing to do.
Event if its 2 time the same animation with the same animation data
All formula are good and tested.
I did intensive debugging with breakpoint to make sure everything is fine at any point
Is there something to prevent me from starting an animation 2 time on an object one after an other?. I have no error or warning at all. The first animation work fine no matter the settings I put in my AnimData struct, but the second time, nothing happen.
Here is the essential:
public int? startAnim(int index)
{
if(index < animIndex.Count)
{
startAnim(animIndex[index]);
}
return null;
}
//private because the struct is internal, this make sure the animator keep control of the list.
private int? startAnim(AnimData animD)
{
if(locked)
{
#if UNITY_EDITOR
Debug.Log("anim locked");
#endif
return null;
}
//current anim (queue anim) not finished
if(endTime > Time.time)
{
if(canQueue)
{
addToQueue(animD);
return animDataQ.Count;
}
else
{
return null;
}
}
else
{
endTime = Time.time + animD.TotalTime;
StartCoroutine(animManager(animD));
return 0;
}
return null;
}
#endregion anim starters
private IEnumerator animManager(AnimData animData)
{
animator.speed = Mathf.Abs(animData.calculateSpeed(animLength, AnimType.main, currentKey).Value);
//animator.Play(0,0, animData.StartKey/animLength);
if(animData.AnimSpeed > 0)
{
animator.Play(0,0, animData.StartKey/animLength/2);
}
else
{
//animator.Play(0,0, (animLength * 2) - (animData.StartKey/animLength));
animator.Play(0,0, (((animLength*2) - animData.StartKey)/(animLength * 2)));
}
//animator.Play(0,0, (animData.AnimSpeed > 0) ? animData.StartKey/animLength : ((animLength * 2) - (animData.StartKey/animLength)));
yield return new WaitForSeconds(animData.Delay);
animator.Stop();
yield return null;
endAnim();
}
private void addToQueue(AnimData animD)
{
animDataQ.Enqueue(animD);
endTime += animD.TotalTime;
queueTime += animD.TotalTime;
}
private void endAnim()
{
if(canQueue && animDataQ.Count > 0)
{
StartCoroutine(animManager(animDataQ.Dequeue()));
}
}
Thanks for your time.
i found a work around.
I dont want to mark it as an accepted solution since its not "clean" in my opinion
there is certainly some kind of problem with the animator for some specific case like mine.
my solution was to use animator.speed = 0 instead of animator.stop();
everything worked instantly with that small change
i will ask my question to the unity forum because there is something strange for sure
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 ?!