The cursor doesn't lock back in FPS Camera - c#

I am making a FPS Game. So, when I start the game, the cursor is locked and I can not see it.
When I press Escape key, now, I am able to see the Cursor and I can move it around and interact with it on my screen and I can not control the game camera now. That is fine. Now, I press Escape key again, and now, I can resume controlling the camera in game, but I can still see the cursor and I can move the camera in game while making the cursor interact with all the stuff even outside of my game window.
The Code
void Update()
{
LockAndUnlockCursor();
if(Cursor.lockState == CursorLockMode.Locked)
{
LookAround();
}
}
void LockAndUnlockCursor()
{
if(Input.GetKeyDown(KeyCode.Escape))
{
if(Cursor.lockState == CursorLockMode.Locked)
{
Cursor.lockState = CursorLockMode.None;
}
else if (Cursor.lockState == CursorLockMode.None)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
}
}```

In the editor this tends to bug out, you have to constantly set it in Update() by saving them into variables.
bool isCursorLocked;
Update() {
if (Input.GetKeyDown(blah))
isCursorLocked = !isCursorLocked;
if (isCursorLocked)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
else
{
// etc
just use variables and always set the cursor lock every Update(). If you don't want this code running always then you could use #if UNITY_EDITOR in a way to only set it every single update for unity editor

Related

Pause Menu in FPS GAME buttons problem using Unity

I am trying to create a pause menu within my FPS game. However, when the game is paused, whenever I mouse over any of the buttons that appear I cannot click on them. I've tried disabling my FPS controller (I'm using the unity fps controller provided) script and checked my canvas has an event system etc.
Any suggestions would be a huge help! Here is my code for the pause menu I have :
public Transform menu;
public GameObject Player;
public GameObject Gun;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
Pause();
}
}
public void Pause()
{
if (menu.gameObject.activeInHierarchy == false)
{
menu.gameObject.SetActive(true);
Time.timeScale = 0;
Gun.GetComponent<Gun>().enabled = false;
Player.GetComponent<FirstPersonController>().enabled = false;
Cursor.lockState = CursorLockMode.None;
Cursor.lockState = CursorLockMode.Confined;
Cursor.visible = true;
}
else
{
menu.gameObject.SetActive(false);
Time.timeScale = 1;
Player.GetComponent<FirstPersonController>().enabled = true;
Gun.GetComponent<Gun>().enabled = true;
}
}
public void QuitToMain()
{
SceneManager.LoadScene("Menu 3D");
}
} ```
Does the pause menu work outside of the games pause state? Have you checked whether the buttons are obstructed by other UI objects that are in the way?
This link might help you to debug the UI issues:
https://answers.unity.com/questions/1148727/ui-button-not-working-2.html

Can't solve hitbox issues in mobile game made in Unity

I am developing a game where objects fall from the top of the screen, and you try to and tap on them before they reach the bottom of the screen. The code works fine when I played the game in the editor (with the touch controls swapped to mouse controls), except when I run the game on a phone, the game only seems to register a successful hit if you tap slightly in front of the object in the direction that it is traveling, and does not register a hit if you tap towards the back end or center of the object. I have built and ran the game over 10 times now, each time trying to fix this issue but nothing seems to help. My theory at the moment is that my code for the touch controls have too much going on and/ or have redundancies and by the time it checks whether or not an object is at the position of the touch, the object has moved to a different location. Any thoughts on why the hit boxes are off, and is there a better way to do hit detection with touch screen?
void FixedUpdate()
{
if (IsTouch())
{
CheckTouch(GetTouchPosition());
}
}
// Returns true if the screen is touched
public static bool IsTouch()
{
if (Input.touchCount > 0)
{
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
return true;
}
}
return false;
}
// Gets the position the touch
private Vector2 GetTouchPosition()
{
Vector2 touchPos = new Vector2(0f, 0f);
Touch touch = Input.GetTouch(0);
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
touchPos = touch.position;
}
return touchPos;
}
// Checks the position of the touch and destroys the ball if the
ball is touched
private void CheckTouch(Vector2 touchPos)
{
RaycastHit2D hit =
Physics2D.Raycast(Camera.main.ScreenToWorldPoint(
(Input.GetTouch(0).position)), Vector2.zero);
if (hit.collider != null)
{
destroy(hit.collider.gameObject);
}
}

Not understanding why it is not recognising a key input

When I press escape, the pause menu in my game should become visible to the user and the game time should freeze. However, the program seems to not recognize the input when I press escape. I have tried using different Keys and they did not work either. I went to make sure that it was the input that was the problem by doing a Debug.Log command and when I tested I was still not getting any signs of it triggering. Here is the code. I hope someone can help me out.
public static bool GameIsPaused = true;
public GameObject PauseMenuUI;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
if (GameIsPaused)
{
Resume();
}
else
{
Pause();
}
}
}
void Resume()
{
PauseMenuUI.SetActive(false);
Time.timeScale = 1f;
GameIsPaused = false;
}
void Pause()
{
PauseMenuUI.SetActive(true);
Time.timeScale = 0f;
GameIsPaused = true;
}
As we discussed in the comments, the GameObject which the PauseMenu-script is attached to was not active.
An inactive gameobject will have all its components disabled.
Update is called every frame, if the MonoBehaviour is enabled.
https://docs.unity3d.com/ScriptReference/MonoBehaviour.Update.html
So your update code did not run, hence never detecting when Escape was pressed.

can't use WaitForSeconds with OnMouseDown

I used OnMouseDown() to deactivate an object but i want the object to activate again in a few seconds. I have used WaitForSeconds() for other things but this time it just doesn't work
this is what i could gather by researching (the deactivating part works fine):
void Start()
{
StartCoroutine(wait());
}
void Update(){}
void OnMouseDown()
{
gameObject.SetActive(false);
}
IEnumarator wait()
{
yield return new WaitForSeconds(3);
gameObject.SetActive(true);
}
There are too many reasons your code isn't work right. You are doing it backwards. Your coroutine starts immediately when your program starts because wait() is called from the Start() function. When it starts, it pauses for 3 seconds and set your GameObject to SetActive(true);
If your GameObject is already visible to the screen, your code wont do anything because SetActive(true) will be called even when it is visible. If you fail to press/click on the screen before that 3 seconds, you wont be able to see SetActive(true); because your coroutine code would have finished running by that time.
Also, if you disable a GameObject, the coroutine attached to it will stop. The solution is to create a reference of the GameObject you want to disable then use that reference to disable and enable it from another script without problems.
Since provided a code, I fixed/re-wrote it for you. I replaced the OnMouseDown fucntion with something more robust.
All you have to do is create an empty GameObject. Attach this script to that empty GameObject. Then drag and drop that GameObject you want to disable and enable to the this "Game Object To Disable" slot in this script, from the Editor.
Do NOT attach this script to that GameObject you want to disable and enable.
Tested with cube and it worked.
using UnityEngine;
using System.Collections;
public class ALITEST: MonoBehaviour
{
//Reference to the GameObject you want to Disable/Enable
//Drag the Object you want to disable here(From the Editor)
public GameObject gameObjectToDisable;
void Start()
{
}
void Update()
{
//Keep checking if mouse is pressed
checkMouseClick();
}
//Code that checks when the mouse is pressed down(Replaces OnMouseDown function)
void checkMouseClick()
{
//Check if mouse button is pressed
if (Input.GetMouseButtonDown(0))
{
RaycastHit hitInfo = new RaycastHit();
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo))
{
//Check if the object clicked is that object
if (hitInfo.collider.gameObject == gameObjectToDisable)
{
Debug.Log("Cube hit");
StartCoroutine(wait()); //Call the function to Enable/Disable stuff
}
}
}
}
//This value is used to make sure that the coroutine is not called again while is it already running(fixes many bugs too)
private bool isRunning = false;
IEnumerator wait(float secondsToWait = 3)
{
//Exit coroutine while it is already running
if (isRunning)
{
yield break; //Exit
}
isRunning = true;
//Exit coroutine if gameObjectToDisable is not assigned/null
if (gameObjectToDisable == null)
{
Debug.Log("GAME OBJECT NOT ATTACHED");
isRunning = false;
yield break; //Exit
}
gameObjectToDisable.SetActive(false);
//Wait for x amount of Seconds
yield return new WaitForSeconds(secondsToWait);
//Exit coroutine if gameObjectToDisable is not assigned/null
if (gameObjectToDisable == null)
{
Debug.Log("GAME OBJECT NOT ATTACHED");
isRunning = false;
yield break; //Exit
}
gameObjectToDisable.SetActive(true);
isRunning = false;
}
}
Because you're calling StartCoroutine() in Start(), your coroutine will resume 3 seconds after the component is started. You want to call StartCoroutine(wait()) in OnMouseDown() so the GameObject will become active after that.
You cannot deactivate GameObject and continue Coroutine on it. If you deactivate GameObject that has runing Coroutine it will be stoped.
So if you want to do it right, you need Coroutine runing on other GameObject and from there actvating this GameObject.
If you need more help, ask.

How to stop a moving object

My script is about when my ball hit a "Trap Object", it'll be moved to start position and STOP right there. How to do that?
void OnTriggerEnter (Collider other)
{
if (other.gameObject.CompareTag ( "Trap" ))
{
//move object to start position
transform.position = startposition.transform.position;
// I want to stop the object here, after it was moved to start position. Because my ball was moving when it hit Trap object, so when it was moved to start position, it keeps rolling.
}
}
As I mentioned in my comment, you need to reset the force of the rigidbody to make sure that your ball is stopped completely. The following code could fix your issue.
// LateUpdate is triggered after every other update is done, so this is
// perfect place to add update logic that needs to "override" anything
void LateUpdate() {
if(hasStopped) {
hasStopped=false;
var rigidbody = this.GetComponent<Rigidbody>();
if(rigidbody) {
rigidbody.isKinematic = true;
}
}
}
bool hasStopped;
void OnTriggerEnter (Collider other)
{
if (other.gameObject.CompareTag ( "Trap" ))
{
var rigidbody = this.GetComponent<Rigidbody>();
if(rigidbody) {
// Setting isKinematic to False will ensure that this object
// will not be affected by any force from the Update() function
// In case the update function runs after this one xD
rigidbody.isKinematic = false;
// Reset the velocity
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
hasStopped = true;
}
//move object to start position
transform.position = startposition.transform.position;
// I want to stop the object here, after it was moved to start position. Because my ball was moving when it hit Trap object, so when it was moved to start position, it keeps rolling.
}
}
The code is untested, so I wouldnt be suprised if it didnt compile on first try, I could have misspelled Rigidbody or something.
(I don't have Unity at work either so hard to test ;-))
Hope it helps!
Do you add some form of speed or velocity to your ball? If you do, you need to reset this to zero to stop your ball from rolling.

Categories

Resources