Unity - How to force a next Input? - unity3d

I am coding a battle menu, it has a character selection panel and a sub menu panel, you need to press enter to move from each menu to the next, however it is skipping going to the sub menu and goes straight into enemy selection, I believe this is because my code is keeping the input, so is there any way to force it to go to the next input and discard the value it currently has.
public void CursorControl()
{
if (CharacterSelectActive == true)
{
if (Input.GetKeyDown(KeyCode.Return))
{
for (int i = 0; i < (CursorPosition); i++)
{
MovesPanelCursor.transform.Translate(42f, 0.0f, 0.0f);
}
CursorPosition = 0;
PanelSwitch();
}
}
if (MoveSelectActive == true)
{
if (Input.GetKeyDown(KeyCode.Escape))
{
for (int i = 0; i < (CursorPosition); i++)
{
MovesPanelCursor.transform.Translate(42f, 0.0f, 0.0f);
}
CursorPosition = 0;
PanelSwitch();
}
if (Input.GetKeyDown(KeyCode.S))
{
CursorPosition = CursorPosition + 1;
MovesPanelCursor.transform.Translate(-42f, 0.0f, 0.0f);
Debug.Log(CursorPosition);
if (CursorPosition > 3)
{
MovesPanelCursor.transform.Translate(42f, 0.0f, 0.0f);
CursorPosition = 3;
}
}
if (Input.GetKeyDown(KeyCode.W))
{
CursorPosition = CursorPosition - 1;
MovesPanelCursor.transform.Translate(42f, 0.0f, 0.0f);
Debug.Log(CursorPosition);
if (CursorPosition < 0)
{
MovesPanelCursor.transform.Translate(-42f, 0.0f, 0.0f);
CursorPosition = 0;
}
}
if (Input.GetKeyDown(KeyCode.Return))
{
if (CursorPosition == 0 || CursorPosition == -1)
{
Attack();
}
if (CursorPosition == 1)
{
}
if (CursorPosition == 2)
{
}
if (CursorPosition == 3 || CursorPosition == 4)
{
}
}
}
public void PanelSwitch()
{
CharacterPanel.SetActive(true);
MoveSelectActive = !MoveSelectActive;
MovesPanel.SetActive(MoveSelectActive);
}

can you please provide your code?... -.-
if you are detecting the enter key using
if(Input.GetKey(KeyCode.Enter))
{
// move to next menu
}
when the enter key is pressed, it will be pressed more then one game-frame, so basically it will go to your sub-menu and there immediately jump to the next menu without you being the step in-between because that submenu also detected a pressed enter-key
try using
if(Input.GetKeyDown(KeyCode.Enter))
{
// move to next menu
}
"down" instead
Edit:
If "PanelSwitch();" internally invokes the CursorControl(), be aware that the same input still holds. In that case it's better to just set the MoveSelectActive or what ever and wait for the next frame Update() to reinvade the controller
Edit:
Varialbes such as MoveSelectActive are quite intransparent in your post, I can't understand what they are initialised with, and how the change of state caused in PanelSwitch() affects the user's options in the UI and what they are meant to cause in the flow of the following CursorControl().
As a hint, I would start to find an issue with the flow, not in getting the keyboard inputs. I don't quite understand what you mean with "force the next input", maybe if you can clarify that I'd understand that there is more to it

Related

Keeping getting NullReferenceException: Object reference not set to an instance of an object OptionsConfig.Update () (at Assets/OptionsConfig.cs:45)

I'm having a problem with my code I'm trying to turn one of my menu's on and off using the setActive method and setting the GameObject to the Object PauseMenu. I'm using an enum to set up different states for the menu but it still doesn't recognise the PauseMenu. I have checked that the name is correct and everything but I still can't figure it, so I hope one of you can help.
public class OptionsConfig : MonoBehaviour {
public enum MenuPhase
{
CLOSED,
MENU,
INVENTORY
}
public MenuPhase currentPhase;
int CursorPosition;
private static GameObject OptionsPanelCursor;
public static GameObject PauseMenu;
public static GameObject InventoryMenu;
public static bool PauseMenuOpen;
void Start()
{
OptionsPanelCursor = GameObject.Find("OptionsPanelCursor");
InventoryMenu = GameObject.Find("InventoryMenu");
PauseMenu = GameObject.Find("PausePanel");
PauseMenuOpen = false;
//InventoryMenu.SetActive(false);
currentPhase = MenuPhase.CLOSED;
Debug.Log(PauseMenuOpen);
}
// Update is called once per frame
void Update()
{
switch (currentPhase)
{
case (MenuPhase.CLOSED):
if (Input.GetKeyDown(KeyCode.Escape))
{
{
Debug.Log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
GameObject Character = GameObject.Find("CharacterOverworld");
Character.GetComponent<CharacterController>().enabled = false;
PauseMenu.SetActive(true);
PauseMenuOpen = true;
currentPhase = MenuPhase.MENU;
}
if (PauseMenuOpen == true)
{
GameObject Character = GameObject.Find("CharacterOverworld");
Character.GetComponent<CharacterController>().enabled = true;
PauseMenu.SetActive(false);
PauseMenuOpen = false;
}
}
break;
case (MenuPhase.MENU):
if (Input.GetKeyDown(KeyCode.S))
{
CursorPosition = CursorPosition + 1;
OptionsPanelCursor.transform.Translate(-31.75f, 0.0f, 0.0f);
if (CursorPosition > 6)
{
OptionsPanelCursor.transform.Translate(31.75f, 0.0f, 0.0f);
CursorPosition = 6;
}
}
if (Input.GetKeyDown(KeyCode.W))
{
CursorPosition = CursorPosition - 1;
OptionsPanelCursor.transform.Translate(31.75f, 0.0f, 0.0f);
if (CursorPosition < 0)
{
OptionsPanelCursor.transform.Translate(-31.75f, 0.0f, 0.0f);
CursorPosition = 0;
}
}
if (Input.GetKeyDown(KeyCode.Return))
{
if (CursorPosition == 0 || CursorPosition == -1)
{
InventoryManage();
}
if (CursorPosition == 1)
{
}
if (CursorPosition == 2)
{
}
if (CursorPosition == 3)
{
}
if (CursorPosition == 4)
{
}
if (CursorPosition == 5)
{
}
if (CursorPosition == 6 || CursorPosition == 7)
{
}
}
break;
}
}
Obviously the object at line 45 is null.
You use GameObject.Find, please check the name again, and be careful it only returns active GameObject.
PauseMenu is a public static field, so it can be set to null from other script.
Also because it's a public static field, after you set it inactive, then you create another OptionsConfig instance, the Start method will run again to set PauseMenu to null. Notice static field is shared between instances, so at this time all OptionsConfig will fail to run.
When PauseMenu is inactive you can still call Start within the script or with GameObject.SendMessage etc, and set PauseMenu to null.
In unity, access property of a GameObject after you destroy it, NullReferenceException will throw.

Player pauses for a second before moving (on some devices)

i have a 2d platformer with a player that moves. It works perfect in unity and i packaged it and downloaded the apk on my galaxy s7 which also works perfect.
I then tested it in my local supermarkets tablet display and on both tablets i tried, if i touched left, it would pause for a second, then move left.
The animated enemies, spinning coins and physics was working fine so there wasnt that type of lag, just a pause when moving which makes me think the code i have to move is wrong. The tablets looked fairly high spec too.
Here is how i move the player, i call this in the update function:
List<FingerTouch> currentTouches = new List<FingerTouch>();
public class FingerTouch
{
public int id;
public float beganXPos;
public FingerTouch (int fingerId, float fingerBegan)
{
this.id = fingerId;
this.beganXPos = fingerBegan;
}
}
if (!disableMovment)
{
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.GetTouch(i).phase == TouchPhase.Began && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
float xPos = Input.GetTouch(i).position.x;
if(xPos < Screen.width / 5)
{
playerLeft = true;
} else if (xPos > ((Screen.width / 5) * 4))
{
playerRight = true;
} else
{
playerUp = true;
}
int fingerId = Input.GetTouch(i).fingerId;
currentTouches.Add(new FingerTouch(fingerId, xPos));
} else if (Input.GetTouch(i).phase == TouchPhase.Ended)
{
if (currentTouches.Count != 0)
{
for (int j = 0; j < currentTouches.Count; j++)
{
FingerTouch currentTouch = currentTouches[j];
if (Input.GetTouch(i).fingerId == currentTouch.id || currentTouches.Count == 1)
{
if (currentTouches[j].beganXPos < Screen.width / 5)
{
playerLeft = false;
}
else if (currentTouches[j].beganXPos > ((Screen.width / 5) * 4))
{
playerRight = false;
}
else
{
playerUp = false;
}
currentTouches.RemoveAt(j);
break;
}
}
} else {
playerUp = false;
playerRight = false;
playerLeft = false;
}
}
}
}
It looks a little over the top but it basicily divides the screen into 3 sections 20/60/20 which move left right jump. When the user touches, it stores that touch and when its released, its removed.
This allows multi touch (jumping and moving) while also preventing jumping, sliding ur finger to the right and removing it and being in an unlimited jumping state as you didnt remove your finger in the middle.
Then after that it moves the player like this:
if (hitLeftWall && playerLeft)
{
playerBody.velocity = new Vector2(0, playerBody.velocity.y);
}
Is there anything here that would cause the player to pause before moving? Should this be in fixed update as the player has a rigidbody? Im new to unity so im not sure on the proper way to do things yet.

Unity3D for Google Cardboard

I have a VR Scene with a C# Script on the camera that allows the user to Click Once to move and again to stop.
public float speed = 1.0f;
public bool startedMoving = true;
public GameObject myCam;
// Update is called once per frame
void Update () {
if (startedMoving) {
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
// if(Input.GetButtonDown("Fire1")){
if (Input.GetMouseButton(0)){
startedMoving = !startedMoving;
}
}
What I want to know is how I can CLICK & HOLD to move Backwards..?
Thank you!
~ b
Use enum the represent the status of the mouse instead of startedMoving or multiple booleans that will make everything easier to implement. The comment in the code describes how it works.
using UnityEngine;
using System.Collections;
public class ClickAndHeld : MonoBehaviour
{
public GameObject myCam;
CLICK_MODE clickMode = CLICK_MODE.NO_CLICK;
MOVE_DIRECTION moveDir = MOVE_DIRECTION.IDLE;
public float speed = 1.0f;
//If down for 0.5 secods the it is considered Click and Hold instead of Click
float clickHoldDetectTime = 0.5f;
float clickCounter = 0; //Dont not change
void Start()
{
StartCoroutine(mover());
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
//If in NO_CLICK, set to CLICKED
if (clickMode == CLICK_MODE.NO_CLICK)
{
//Change the mode to CLICKED
clickMode = CLICK_MODE.CLICKED;
}
//If in CLICKED mode, start counting to clickHoldDetectTime
if (clickMode == CLICK_MODE.CLICKED)
{
clickCounter += Time.deltaTime; //Increment counter
//Check if we have reached the clickHoldDetectTime time
if (clickCounter > clickHoldDetectTime)
{
//Reset Counter
clickCounter = 0;
//Change the mode to CLICK_AND_HELD
clickMode = CLICK_MODE.CLICK_AND_HELD;
}
}
//If STILL down and the the current mode is CLICK_AND_HELD then do clickedAndHeldDown stuff
if (clickMode == CLICK_MODE.CLICK_AND_HELD)
{
clickedAndHeldDown();
}
}
else
{
//If released and the current mode is CLICKED then do clicked stuff
if (clickMode == CLICK_MODE.CLICKED)
{
clicked();
}
//If released and the current mode is CLICK_AND_HELD, change to RELEASED then do relased stuff
if (clickMode == CLICK_MODE.CLICK_AND_HELD)
{
//Change the mode to RELEASED
clickMode = CLICK_MODE.RELEASED;
mouseReleasedAfterBeingHeld();
}
//Reset each time mouse button is released
reset();
}
}
IEnumerator mover()
{
while (true)
{
if (moveDir == MOVE_DIRECTION.IDLE)
{
}
//Move Forward
if (moveDir == MOVE_DIRECTION.FORWARD)
{
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
//Move Backward
if (moveDir == MOVE_DIRECTION.BACKWARD)
{
transform.position -= myCam.transform.forward * speed * Time.deltaTime;
}
yield return null;
}
}
private void clicked()
{
Debug.Log("CLICKED");
//If Idle, become Forward
if (moveDir == MOVE_DIRECTION.IDLE)
{
moveDir = MOVE_DIRECTION.FORWARD;
}
//If forward, moves become idle
else if (moveDir == MOVE_DIRECTION.FORWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
//--------------------------------------------------
//If backward, moves become idle
else if (moveDir == MOVE_DIRECTION.BACKWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
}
private void clickedAndHeldDown()
{
Debug.Log("CLICKED AND HELD");
//If Idle, becomes backward
if (moveDir == MOVE_DIRECTION.IDLE)
{
moveDir = MOVE_DIRECTION.BACKWARD;
}
}
//Called when released after being RELEASED from CLICKED_HELD
private void mouseReleasedAfterBeingHeld()
{
Debug.Log("RELEASED AFTER CLICKED AND HELD");
//If backward, move becomes idle
if (moveDir == MOVE_DIRECTION.BACKWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
//--------------------------------------------------
//If forward, move becomes idle
else if (moveDir == MOVE_DIRECTION.FORWARD)
{
moveDir = MOVE_DIRECTION.IDLE;
}
}
void reset()
{
clickMode = CLICK_MODE.NO_CLICK;
clickCounter = 0;
}
}
public enum CLICK_MODE
{
NO_CLICK, CLICKED, CLICK_AND_HELD, RELEASED
}
public enum MOVE_DIRECTION
{
IDLE, FORWARD, BACKWARD
}
Because you only have one trigger action you're going to have to implement something time based for toggling forward/backwards movement. For example, if you press and release the trigger quickly then forward walk could be toggled, but if you're holding the trigger after N length of time then walk backwards.
He's a practical example to get you starting.
Pressing and releasing the trigger within 300ms will toggle forward movement
Pressing and holding the trigger for longer than 300ms will begin backwards movement, releasing the trigger then will stop backwards movement
This is a theoretical example
public float speed = 1.0f;
bool triggerPressed = false;
float triggerHeldTime = 0f;
public bool movingForwards = false;
public bool movingBackwards = false;
void Update ()
{
// increment hold time if we're still holding trigger
if (Input.GetMouseButton(0) && triggerPressed)
triggerHeldTime += Time.deltaTime;
if (Input.GetMouseButton(0) && !triggerPressed)
{
// reset everything when trigger initially pressed
movingForards = false;
movingBackwards = false;
triggerHeldTime = 0f;
triggerPressed = true;
}
else if (!Input.GetMouseButton(0) && triggerPressed)
{
// upon trigger release
triggerPressed = false;
// if we are not moving backwards, toggle forwards movement
if(!movingBackwards)
movingForwards = !movingForwards;
// always reset backwards movement when we release the trigger
movingBackwards = false;
triggerHeldTime = 0f;
}
// if the trigger has been held for 300ms then move backwards
if(triggerHeldTime > 0.3f)
{
moveForwards = false;
moveBackwards = true;
}
// actually perform the movement
if (moveForwards)
{
transform.position += myCam.transform.forward * speed * Time.deltaTime;
}
else if(moveBackwards)
{
transform.position -= myCam.transform.forward * speed * Time.deltaTime;
}
}

How to have an object flip directly on right or left arrow in unity?

I am trying to get a GameObject to face right when I press the right arrow and then face left when I press left arrow.
What I currently get is the image to flip back and forth over and over again. It won't just stay facing left or right.
On occasion it will switch to the left and stay that way even though I am pressing right. I am sure there is a better way to do this.
public bool isFacingRight;
// Update is called once per frame
void Update () {
if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.LeftArrow))
{
petAnimate.AnimationName = "run_loop";
} else
{
petAnimate.AnimationName = "start_loop_2";
}
if (Input.GetKey(KeyCode.RightArrow)) {
isFacingRight = true;
}
if (Input.GetKey(KeyCode.LeftArrow)) {
isFacingRight = false;
}
Flip();
}
void Flip()
{
if (isFacingRight == true)
{
transform.Rotate(0, 0, 0);
}
if (isFacingRight == false)
{
transform.Rotate(0, 180, 0);
}
}
You can simply times the X scale by -1. Multiplying by -1 will just turn everything backwards :)
void Flip()
{
// Switch the way the player is labelled as facing
isFacingRight = !isFacingRight;
// Multiply the player's x local scale by -1
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
Note that this method will work on whichever arrow key you press (left or right). If your character is facing right in your scene, set your bool to true, otherwise set it to false
void Flip()
{
if (isFacingRight == true)
{
transform.localScale = new Vector3(.2f, .2f, 0);
}
if (isFacingRight ==false)
{
transform.localScale = new Vector3(-.2f, .2f, 0);
}
}

How to Put this strength meter bar to an object?

#pragma strict
var strengthAmount : float = 0.0F;
private var maxStrengthAmount : float = 100.0F;
var guiSkin : GUISkin;
var barSprite : Texture2D;
var powerButton : GUITexture;
function Update () {
for (var touch : Touch in Input.touches)
{
if (strengthAmount >= 100.0F)
{
strengthAmount = maxStrengthAmount;
// Do stuff here
}
else if (strengthAmount < 0.0F)
{
strengthAmount = 0.0F;
}
if(touch.phase == TouchPhase.Stationary && powerButton.HitTest(touch.position)){
strengthAmount += 1.0F;
}
else if(touch.phase == TouchPhase.Ended && powerButton.HitTest){
strengthAmount = 0.0F;
}
}
}
function OnGUI()
{
GUI.skin = this.guiSkin;
GUI.DrawTexture(new Rect(Screen.width / 8, Screen.height - 167.5F, 150
(strengthAmount / maxStrengthAmount), 31), barSprite);
GUI.Box(new Rect(Screen.width / 8, Screen.height - 167.5F, 150, 31), "Strength");
}
Here is my strength meter bar code, but I want to put it on an object that when I release the button, the object will be thrown away? I am new to Unity3D so please help me how to make a script on that or help me directly thank you
Create a JS script, paste this script and save it. Create a game object, select it, on the inspector click on the button Add component. Then find your script and add it.
Then create another script that has the following:
Update() //this is C#
{
if (GetKeyUp(KeyCode. /*here find the key code of the button that you want to release*/ )
Destroy(this); //if you want to destroy the object
}