quitting from a pause menu to restart from the title screen C# - c#

The game restarts fine if you win or lose. The player has the option of going back to the title screen from either of those scenes. But the problem occurs when you pause the game and quit from the pause menu. If you do, the title screen is loaded but there is no music and no way to go navigate further. It does, for some reason, allow you to navigate to the credits (without music) and back to the title screen, but no further. The order is, title screen, tutorial screen, level 1. I don't know if it has anything to do with it, but the pause menu that shows is just a canvas that is enabled/disabled when you press space. Here's the pause script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class pauseScript : MonoBehaviour {
private bool isPaused = true;
public GameObject pauseMenuCanvas;
public AudioSource audioSource;
public AudioClip Paused;
public AudioClip notPressingStart;
void Awake ()
{
audioSource = GetComponent<AudioSource> ();
}
void Update ()
{
Sound ();
Pausing ();
}
void Pausing()
{
if (!isPaused && Input.GetKeyDown (KeyCode.Escape))
{
Application.LoadLevel ("titleScreen");
}
if (!isPaused) {
Time.timeScale = 0f;
pauseMenuCanvas.SetActive (true);
isPaused = false;
AudioListener.volume = 0f;
} else {
Time.timeScale = 1f;
pauseMenuCanvas.SetActive (false);
isPaused = true;
AudioListener.volume = 1f;
}
if (Input.GetKeyDown (KeyCode.Space)){
isPaused = !isPaused;
}
}
void Sound()
{
if (Input.GetKeyDown (KeyCode.Space))
audioSource.PlayOneShot (Paused, 7f);
}
}

Within:
if (!isPaused && Input.GetKeyDown (KeyCode.Escape))
{
Application.LoadLevel ("titleScreen");
}
if (!isPaused) {
Time.timeScale = 0f;
pauseMenuCanvas.SetActive (true);
isPaused = false;
AudioListener.volume = 0f;
}
When you check to see if "KeyCode.Escape" is pressed while "!isPaused == true", the "titleScreen" is loaded but the next line:
if (!isPaused)...
will always be true when going to the "titleScreen" which always turns the volume to 0
AudioListener.volume = 0f;

Related

How to switch between the OnTriggerExit/Enter logic depending on the situation?

The script is attached to two gameobjects.
One it's colliding area the collider is big enough so when the game start the player is already inside the collider area and then when he exit the area everything is working fine.
The problem is when I attached the object to another gameobject with collider but this time the collider s smaller and he is inside the bigger collider so now the player is entering the smaller collider and not first time exiting. but I want in both case to make the same effect.
If the player exit the collider he slow down wait then turn around and move inside back.
The same I want to make when the player getting closer to the fire flames slow down wait turn around and move back in it's just with the flames the player entering the collider area and then exit while in the bigger collider he first exit then enter.
Screenshot of the two colliders areas. The small one on the left is the one the player entering first and not exiting. The game start when the player is in the bigger collider area.
And the script :
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityStandardAssets.Characters.ThirdPerson;
public class DistanceCheck : MonoBehaviour
{
public Transform targetToRotateTowards;
public Transform colliderArea;
public float lerpDuration;
public float rotationSpeed;
[TextArea(1, 2)]
public string textToShow;
public GameObject descriptionTextImage;
public TextMeshProUGUI text;
public ThirdPersonUserControl thirdPersonUserControl;
private Animator anim;
private float timeElapsed = 0;
private float startValue = 1;
private float endValue = 0;
private float valueToLerp = 0;
private bool startRotating = false;
private bool slowOnBack = true;
private bool exited = false;
private Vector3 exitPosition;
private float distance;
void Start()
{
anim = transform.GetComponent<Animator>();
}
private void FixedUpdate()
{
if (startRotating)
{
transform.rotation = Quaternion.RotateTowards(transform.rotation,
Quaternion.LookRotation(targetToRotateTowards.position - transform.position),
rotationSpeed * Time.deltaTime);
}
if (exitPosition != new Vector3(0, 0, 0) && slowOnBack)
{
distance = Vector3.Distance(transform.position, exitPosition);
}
if (distance > 5 && slowOnBack)
{
slowOnBack = false;
StartCoroutine(SlowDown());
}
}
private void OnTriggerExit(Collider other)
{
if (other.name == colliderArea.name)
{
exited = true;
slowOnBack = true;
exitPosition = transform.position;
thirdPersonUserControl.enabled = false;
descriptionTextImage.SetActive(true);
text.text = textToShow;
StartCoroutine(SlowDown());
}
}
private void OnTriggerEnter(Collider other)
{
if (other.name == colliderArea.name)
{
exited = false;
startRotating = false;
text.text = "";
descriptionTextImage.SetActive(false);
}
}
IEnumerator SlowDown()
{
timeElapsed = 0;
while (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
anim.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
yield return null;
}
if (exited)
{
yield return new WaitForSeconds(3f);
startRotating = true;
StartCoroutine(SpeedUp());
}
if (slowOnBack == false)
{
thirdPersonUserControl.enabled = true;
}
}
IEnumerator SpeedUp()
{
timeElapsed = 0;
while (timeElapsed < lerpDuration)
{
valueToLerp = Mathf.Lerp(endValue, startValue, timeElapsed / lerpDuration);
anim.SetFloat("Forward", valueToLerp);
timeElapsed += Time.deltaTime;
yield return null;
}
}
}
Two problems I'm facing right now :
The smaller collider the player enter it then exit and the bigger collider the player exit it then enter so I need to change somehow the OnTriggerExit/Enter behavior logic in the script. but how to make the logic ?
Maybe it's better to make the script to be on the player object only and make it some how generic so I can drag to it many colliders and to make the effect in each one of the colliders the problem is how to make a text field for each collider area ? Now because I attach the script to each collider object I have one colliderArea variable but if I want to make the script only attached to the player I need to change the colliderArea variable to a List<Transform> collidersAreas and then how to create a text field/area to each collider area in the List ?
I think I would do this by creating two tags, NoExit and NoEntry. Once the tags are created you can set the tag on the GameObjects that hold your colliders. Then you can check for tags in the OnTriggerEnter and OnTriggerExit and act accordingly.
I can't tell for sure which functionality you've got written is for which case, or if it's both - everything looks muddled. Ultimately what you should be going for is a function like RepositionPlayer, that moves them back to before they're violating the no entry or no exit rules, and then some kind of OnPlayerRepositioned event that restores their control.
I'll leave it up to you to split out your functionality, but in general I'd look to do something like the following:
private void OnTriggerExit(Collider other)
{
if (other.tag == "NoExit")
{
RepositionPlayer();
}
else if(other.tag == "NoEntry")
{
OnPlayerRepositioned();
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "NoExit")
{
OnPlayerRepositioned();
}
else if(other.tag == "NoEntry")
{
RepositionPlayer();
}
}
And again here it's not clear to me what you're trying to do to reposition the player, but it looks like it's something like:
private void RepositionPlayer()
{
// Stuff that needs to happen to reposition the player
exited = true;
slowOnBack = true;
exitPosition = transform.position;
thirdPersonUserControl.enabled = false;
descriptionTextImage.SetActive(true);
text.text = textToShow;
StartCoroutine(SlowDown());
}
private void OnPlayerRepositioned()
{
// stuff you need to do to clear the "repositioning" status
exited = false;
startRotating = false;
text.text = "";
descriptionTextImage.SetActive(false);
}
Splitting up the logic like this makes it easier to both read and maintain.

Time.Timescale is not pausing the game

This is the script of a ball game that I am building.
The game is supposed to pause once it hits Time.timescale but it doesn't.
I need to know what I did wrong and what I need to change here.
I am a beginner in Unity and C# so i might have messed up everything.
If there is any other way to pause the game rather than using Time.timescale i would like to know it also.
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
public class PauseScript : MonoBehaviour
{
public bool paused = false;
void Start()
{
paused = false;
Time.timeScale = 1;
}
// Update is called once per frame
public void Pause()
{
if (Input.GetKeyDown("p") && paused == false)
{
Time.timeScale = 0;
paused = true;
}
if (Input.GetKeyDown("p") && paused == true)
{
Time.timeScale = 1;
paused = false;
}
}
}
Ball.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class Ball : MonoBehaviour
{
//configuration parameter
[SerializeField] Paddle paddleInitial;
[SerializeField] float horizontalPush = 2f;
[SerializeField] float verticalPush = 15f;
[SerializeField] AudioClip[] ballSounds;
//state parameter
Vector2 paddleToBallVector;
bool mouseButtonClicked = false;
//Cached COmponent References
AudioSource myAudioSource;
// Start is called before the first frame update
void Start()
{
paddleToBallVector = transform.position - paddleInitial.transform.position;
myAudioSource = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
if (mouseButtonClicked == false)
{
stickBallToPaddle();
launchOnMouseClick();
}
if (Input.GetMouseButtonDown(1))
{
GetComponent<Rigidbody2D>().velocity = new Vector2(horizontalPush,verticalPush);
}
}
private void launchOnMouseClick()
{
if (Input.GetMouseButtonDown(0))
{
mouseButtonClicked = true;
GetComponent<Rigidbody2D>().velocity = new Vector2(horizontalPush, verticalPush);
}
}
private void stickBallToPaddle()
{
Vector2 paddlePosition = new Vector2(paddleInitial.transform.position.x, paddleInitial.transform.position.y);
transform.position = paddlePosition + paddleToBallVector;
}
//audio settings
private void OnCollisionEnter2D(Collision2D collision)
{
if (mouseButtonClicked)
{
AudioClip clip = ballSounds[UnityEngine.Random.Range(0, ballSounds.Length)];
myAudioSource.PlayOneShot(clip);
}
}
}
There are a couple of potential issues.
Your function should be called Update, or it won't run once per frame
Input.GetKeyDown returns if a key has started being pressed, but this persists on the current frame (it's only reset before the next Update call, so it will return true every time you call it in the same Update function block)
When you hit P, you check if the key is down then set the pause flag/timescale, but then you do another if check in the update method that does the opposite.
// Update is called once per frame
public void Pause()
{
// The p key is down and the game isn't paused, set timescale to 0 and paused to true...
if (Input.GetKeyDown("p") && paused == false)
{
Time.timeScale = 0;
paused = true;
}
// The p key is still down since we are on the same frame and paused flag is set so here we set timescale to 1 and paused to false...
if (Input.GetKeyDown("p") && paused == true)
{
Time.timeScale = 1;
paused = false;
}
}
You probably want to make sure only one of these conditions runs per update and ensure the function is called Update or it won't run once per frame
// Update is called once per frame
public void Update()
{
if (Input.GetKeyDown("p") && paused == false)
{
Time.timeScale = 0;
paused = true;
}
// Use else to make sure this block only gets executed if the above doesn't
else if (Input.GetKeyDown("p") && paused == true)
{
Time.timeScale = 1;
paused = false;
}
}
There are many ways to skin a cat so to speak; alternative code could look something like this:
public void Update()
{
if(Input.GetKeyDown("p"))
{
// Toggle paused
paused != paused;
// Use ternary operator to save lines because making code harder to read is fun
Time.timeScale = paused ? 0 : 1;
}
}
-- Edit:
Also make sure you are multiplying any vectors for movement etc by deltaTime each frame - otherwise your simulation will continue.
You may also need to explicitly handle paused for other aspects such as animations etc - it depends on how they are implemented, but as long as they consider the delta frame by frame they will react when timeScale is set to 0 as expected.

How can I create a boundary using C# code only?

I am trying to create a unity script that detects when the player has left a certain area using C# code only (no boundary boxes). My code should play a sound once the player leaves but the code is not working as expected and I cannot see a fault in the logic.
Expected behaviour
When the player steps outside the boundary, a sound will play once.
Actual Behaviour
The sound plays all the time no matter where the player is.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EX2BoundaryDetect : MonoBehaviour {
// create a GameObject to represent the player
public GameObject playerObject;
public bool leaveArea = false;
// create an Audio-clip object. This assumes we drag a sound file onto the myclip box in the Inspector.
public AudioClip myclip;
// Use this for initialization
void Start () {
// associate playerObject with the player. This assumes the First Person Controller is name "player
playerObject = GameObject.Find ("player");
// get the actual Sound file from the Inspector
GetComponent<AudioSource>().clip = myclip;
}
// Update is called once per frame
void Update () {
PlayAudio1();
if (leaveArea) {
GetComponent<AudioSource> ().Play ();
}
}
public void PlayAudio1 () {
// play the sound if the player is outside some boundaries
if (transform.position.x > 10) {
leaveArea = true;
}
if (transform.position.x < -29) {
leaveArea = true;
}
if (transform.position.z > 10) {
leaveArea = true;
}
if (transform.position.z < -29) {
leaveArea = true;
}
}
}
leaveArea is only set to false in the class definition. Once set to true, it may never be set to false again, and it may be inadvertently overwritten in the scene definition in the first place.
To fix this issue, set it to false at the beginning of Update:
void Update () {
leaveArea = false;
PlayAudio1();
if (leaveArea) {
GetComponent<AudioSource> ().Play ();
}
}
Also, GetComponent is an expensive action and it is good to avoid calling it in Update wherever possible. Therefore, you may want to move it into a class property and set it once in Start:
private AudioSource audioSource;
void Start () {
// associate playerObject with the player. This assumes the First Person Controller is name "player
playerObject = GameObject.Find ("player");
audioSource = GetComponent<AudioSource>();
// get the actual Sound file from the Inspector
audioSource.clip = myclip;
}
// Update is called once per frame
void Update () {
leaveArea = false;
PlayAudio1();
if (leaveArea) {
audioSource.Play ();
}
}
Got it working now, by adding
leaveArea = false;
to the Update method.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EX2BoundaryDetect : MonoBehaviour {
// create a GameObject to represent the player
public GameObject playerObject;
public bool leaveArea = false;
// create an Audio-clip object. This assumes we drag a sound file onto the myclip box in the Inspector.
public AudioClip myclip;
// Use this for initialization
void Start () {
// associate playerObject with the player. This assumes the First Person Controller is name "player
playerObject = GameObject.Find ("player");
// get the actual Sound file from the Inspector
GetComponent<AudioSource>().clip = myclip;
}
// Update is called once per frame
void Update () {
PlayAudio1();
if (leaveArea) {
GetComponent<AudioSource> ().Play ();
}
leaveArea = false;
}
public void PlayAudio1 () {
// play the sound if the player is outside some boundaries
if (transform.position.x > 10) {
leaveArea = true;
}
if (transform.position.x < -29) {
leaveArea = true;
}
if (transform.position.z > 10) {
leaveArea = true;
}
if (transform.position.z < -29) {
leaveArea = true;
}
}
}
I think the above answers still do not solve your problem of "When the player steps outside the boundary, a sound will play once."
I will share a cleaner way of doing it (possibly optimized)
Using Bounds
Create our own bounds by using Bounds https://docs.unity3d.com/ScriptReference/Bounds.html
The constructor of Bounds is Bounds(Vector3 center,vector3 size)
So in your case center will be center = (-9.5f, 0, -9.5f) (midpoint formula) and finally the size of the bounding box will be size = (39.0f, 0f, 39.0f)
Let's move to the Code Part
public class BoundsCheck: MonoBehaviour
{
public bool isInside = false;
public bool isPlayedOnce = false;
private Bounds bounds;
void Start()
{
bounds = new Bounds(new Vector3(-9.5f, 0, -9.5f), new Vector3(39.0f, 0f, 39.0f));
}
void Update()
{
CheckBounds();// play the sound if the player is outside some boundaries
if (!isInside &&!isPlayedOnce)
{
Debug.Log("PLAY");
isPlayedOnce = true;
}
}
private void CheckBounds()
{
bool isInsideBound = bounds.Contains(transform.position);
if (isInsideBound)
{
isInside = true;
if (isPlayedOnce)
{
isPlayedOnce = false;
}
}
else
{
isInside = false;
}
}
}
So instead of multiple ifs, we can just check if the position of the transform is inside the bound by using bool isInsideBound = bounds.Contains(transform.position);
Note:- To play sound only once, I have used one more boolean isPlayedOnce
I am not sure if this the most optimized way of doing it. But surely a cleaner way(via code).

Moving Player Up by holding left mouse button /space Microsoft VIsual Studio (Unity)

I'm not so good with Visual Studio.
I'm making a simple game and my gameobject (player) should move up when Space or Left Mouse Button is pressed.
Here is my code
using UnityEngine;
using System.Collections;
public class PixelMovement : MonoBehaviour {
Vector3 velocity = Vector3.zero;
public Vector3 PressVelocity;
public float maxSpeed = 5f;
public float fowardSpeed = 1f;
bool didPress = false;
// Use this for initialization
void Start () {
}
//Do Graphic & Input updates
void update() {
if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) {
didPress = true;
}
}
//Do physics engine updates here
void FixedUpdate () {
velocity.x = fowardSpeed;
if (didPress == true){
didPress = false;
velocity += PressVelocity;
}
velocity = Vector3.ClampMagnitude(velocity, maxSpeed);
transform.position += velocity * Time.deltaTime;
}
}
So, it should move like contrary to gravity. And when it stops holding, it continues to fall. I already have gravity I just need that "Up movement"
//Do Graphic & Input updates
void update() {
if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) {
didPress = true;
}
}
I think the problem is because update() should be Update()
Try:
//Do Graphic & Input updates
void Update() {
if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) {
didPress = true;
}
}
This is a quick fix: You're calling Input.GetKeyDown() and Input.GetMouseButtonDown() which only return true on the first frame that the button is pressed.
If you want a repeating event (I.E., the mouse button or space is held down), use Input.GetKey(KeyCode.Space) and Input.GetMouseButton(0).

Pause button not working

I am writing a pause button for my game (Game for mobile phones).
My Pause script:
using UnityEngine;
using System.Collections;
public class PauseScript : MonoBehaviour {
public bool paused;
// Use this for initialization
void Start () {
paused = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
paused = !paused;
}
if (paused)
{
Time.timeScale = 0;
}
else if (!paused)
{
Time.timeScale = 1;
}
}
public void Pause()
{
paused = !paused;
if (paused)
{
Time.timeScale = 0;
}
else if (!paused)
{
Time.timeScale = 1;
}
}
}
And Jump that is written like this jump = Input.GetButton("Fire1");
When I touch button my player jumps and the game does not pause.
How I can make my game pause and player doesn't jump?
Unity Docs: Time.timeScale
Except for realtimeSinceStartup, timeScale affects all the time and delta time measuring variables of the Time class.
if you want to actually use timeScale you need to use Time.deltaTime in your calculations. Like:
transfomr.position += Vector3.forward * speed * Time.deltaTime;
so, it's not going to magically pause all the scripts. Update(), FixedUpdate() and all the other MonoBehaviour functions will still get invoked normally. also, read about Time.deltaTime if you haven't already.

Categories