I'm making and game which has digging as it's feature so I need timer which will count exact float (in seconds) and then destroy gameObject. This is what I tried now but it's freezing unity:
function Update()
{
if (Input.GetMouseButtonDown(0))
{
digTime = 1.5; // in secounds
}
while (!Input.GetMouseButtonUp(0)) // why is this infinite loop?
{
digtime -= Time.deltaTime;
if (digtime <= 0)
{
Destroy(hit.collider.gameObject);
}
}
Here is a basic example how you can check if player has clicked for a certain time period.
#pragma strict
// This can be set in the editor
var DiggingTime = 1.5;
// Time when last digging started
private var diggingStarted = 0.0f;
function Update () {
// On every update were the button is not pressed reset the timer
if (!Input.GetMouseButton(0))
{
diggingStarted = Time.timeSinceLevelLoad;
}
// Check if the DiggingTime has passed from last setting of the timer
if (diggingStarted + DiggingTime < Time.timeSinceLevelLoad)
{
// Do the digging things here
Debug.Log("Digging time passed");
// Reset the timer
diggingStarted = Time.timeSinceLevelLoad;
}
}
It is firing every DiggingTime of seconds even the player is holding the button down. If you want that the player needs to release the button and press again one solution is to add Boolean telling if the timer is on or not. It can be set true on GetMouseButtonDown and false on GetMouseButtonUp.
Update function is called every frame. If you add a while loop inside this function waiting for the mouseButtonUp, you'll freeze Unity for sure.
You don't need the while loop. Just check GetMouseButtonUp without while loop.
EDIT
This is the Update function:
void Update ()
{
if ( Input.GetMouseButtonDown( 0 ) )
{
digTime = 1.5f;
}
else if ( Input.GetMouseButton( 0 ) )
{
if ( digTime <= 0 )
{
Destroy( hit.collider.gameObject );
}
else
{
digTime -= Time.deltaTime;
}
}
}
Minor controls should be added to avoid destroying gameObject several times, but this is the idea to proceed
Related
im having trouble with the hand IK of a -recoil shoot animation- that is on an override layer in the animator. I have it set up so that when I aim(left trigger), it allows me to shoot with another button(right trigger). I have it so the weight (hand IK) increases to 1 (in the rig layer) when I aim and decreases to 0 when I let go of the aim button.
The problem is that if I shoot the gun (uses recoil gun animation) and let go of the aim button immediately afterwards, the animation will continue to play but the IK will go to 0 and the hands will look all messed up.
I've tried setting the IK hand weight to 1 when he fires the gun, so he'll still hold onto it, but it doesn't work since shoot is only true if aim is being held down.
So overall I fire the gun, he does a recoil animation, and when you let go of aim too early, the animation looks all messed up like he's waving to you from behind his back. Like it aborts the animation or something.
private void HandleMovementInput()
{
horizontalMovementInput = movementInput.x;
verticalMovementInput = movementInput.y;
animatorManager.HandleAnimatorValues(horizontalMovementInput, verticalMovementInput, runInput);
if (verticalMovementInput != 0 || horizontalMovementInput !=0) //running
{
if (aimingInput)
{
if (animatorManager.isAimingGunn == false)
{
shootInput = false;
}
}
}
if (animatorManager.isAimingGunn)
{
animatorManager.leftHandIK.weight = 1; // IK weight
animatorManager.rightHandIK.weight = 1;
horizontalMovementInput = 0f; // joystick
verticalMovementInput = 0f;
}
else if(animatorManager.isAimingGunn == false)
{
if(verticalMovementInput != 0 || horizontalMovementInput !=0) //running
{
animatorManager.leftHandIK.weight = 0;
}
animatorManager.leftHandIK.weight = 0; // IK weight
animatorManager.rightHandIK.weight = 0;
}
}
private void HandleShoot()
{
if (aimingInput) // must aim otherwise shootInput(right trigger on controller) wont work
{
if (shootInput)
{
shootInput = false;
playerManager.UseCurrentWeapon();
}
}
}
I was able to fix it. I used this code to tell the character to keep aiming if still in the current animation.This allows for the animation to finish before you set the Hand IK to 0.
if(animator.GetCurrentAnimatorStateInfo(1).IsName("Pistol_Shoot"))
{
aimingInput = true;
}
Also Due to it getting overly complicated I changed the aim cancel button to the top left trigger on the controller ( while aim is on the bottom left trigger).
This is just a portion of my code, and I hope will be easy enough to understand. I found a way to "fix" it, but I still don't understand this:
I set my float countDownTime to 2f. In DisplayTime(), i thought the do-while loop would count from 2 down to 0, but instead starts counting down from 0 to negative numbers. I thought that it would count down and stop when countDownTime reaches 0, as assigned in the while(countDownTime >= 0) but it continues beyond that. Thanks for any feedback or assistance.
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && !hasStarted)
{
hasStarted = true;
StartGame();
}
DisplayTime();
}
void DisplayTime()
{
if (timerStart)
{
do
{
countDownTime -= Time.deltaTime;
} while (countDownTime >= 0);
timer2.text = Math.Round(countDownTime, 2).ToString();
}
}
I made changes to it, which is my fix:
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && !hasStarted)
{
hasStarted = true;
StartGame();
}
DisplayTime();
}
void DisplayTime()
{
if (timerStart && countDownTime >= 0)
{
do
{
countDownTime -= Time.deltaTime;
} while (countDownTime >= 2);
timer2.text = Math.Round(countDownTime, 2).ToString();
}
}
First off, I don't see where you're initially setting countDownTime to 2.
Second, countDownTime will more likely than not stop on a negative number rather than zero. This is because deltaTime is a measure of the ms that have passed since the last update, and varies quite a bit. So you should round it back up 0 if you don't want to be shown as negative.
Finally, I think you want to execute this code as a Coroutine, otherwise the entire loop will execute in a single frame, which is most likely not what you want.
IEnumerator DisplayTime() {
countDownTime = 2;
while (countDownTime > 0) {
countDownTime -= Time.deltaTime;
timer2.text = Math.Round(countDownTime, 2).ToString();
yield return new WaitForEndOfFrame();
}
}
void Start() {
// start coroutine
StartCoroutine(DisplayTime);
}
If you did not want a coroutine, and wanted to called it each frame from your Update method, you can simply drop the while loop.
void DisplayTime() {
if (timerStart) {
if (countDownTime > 0) {
countDownTime -= Time.deltaTime;
}
}
timer2.text = Math.Round(countDownTime, 2).ToString();
}
The benefit of the Coroutine method is it usually easier to manage. Rather than calling a method every time from Update, you can call it once and just let it run. Since the looping is confined to the method itself you can use DisplayTime to set the initial value of countDownTime to 2.
You need to consider 2 factors.
Update() Method is called on every frame. You are executing do-while loop in DisplayTime() which is called from Update() so do while loop will execute many time (once per frame).
do-while loop works differently from normal while loop. do-while loop first executes code inside do{} and only after checks condition and breaks loop if condition is false. so (even if condition is false) code inside do{} will run at least once once. In case of normal while if condition is false code inside loop will not run.
So in your case on first frame countDownTime is subscribed until it will become be less than 0. (So on screen you immediately see 0 instead of 2, because after first frame its
already 0).
after 1st frame on each frame when do-while is executed code inside do is executed only once and than loop immediately breaks because condition countDownTime >= is already false. So after 1st frame countDownTime -= Time.deltaTime;this code gets executed once per frame (without looping multiple times in do-while), that is why it works "correctly" afterwards.
This is within the Update function. Excuse the brakeTorque stuff, that's just a bandaid for now. This is a drag racing game, and Staged means ready to go. Once both cars are staged, and the race hasn't started yet, then there should be a delay of 5 seconds then the words "GO 1" should appear (I added stupidCounter as a debugging tool). Then it sets the start time. Then it sets Racing to true in order to keep it from jumping back into this if statement again.
The issue is that it keeps jumping back in the if statement every frame; printing: GO1 GO2 GO3 etc.
The word "GO" is not mentioned anywhere else in any other script.
The "Racing" boolean is not mentioned anywhere else in any script.
Here's my code:
if(Staged && OtherCarStaged() && !Racing)
{
RearRightWheel.brakeTorque = 10000;
RearLeftWheel.brakeTorque = 10000;
FrontRightWheel.brakeTorque = 10000;
FrontLeftWheel.brakeTorque = 10000;
yield WaitForSeconds(5);
stupidCounter += 1;
Debug.Log("GO " + stupidCounter);
mainTimerStart = Time.realtimeSinceStartup;
Racing = true;
}
I'm assuming your function is a coroutine. The issue in your code is probably because you are calling the coroutine in every update frame. You either need to add a check to call the coroutine only once, or use your own timer to handle this instead of a coroutine.
Based on your mentioned requirement I think your code should go like this
var timeLeft : float = 5;
function Update()
{
StartCountdown();
}
function StartCountdown()
{
if(Staged && OtherCarStaged() && !Racing)
{
// your stuff
timeLeft -= Time.deltaTime;
if(timeLeft <= 0)
{
Debug.Log("GO");
mainTimerStart = Time.realtimeSinceStartup;
Racing = true;
}
}
}
Or, if you want to go with Coroutines, it would go like this
function Update()
{
if(!countdownStarted && Staged && OtherCarStaged())
StartCoroutine(StartCountdown(5));
}
var countdownStarted : bool = false;
function StartCountdown(float time)
{
countdownStarted = true;
yield WaitForSeconds(time);
Debug.Log("GO ");
mainTimerStart = Time.realtimeSinceStartup;
Racing = true;
}
So I've got this script here that moves the player by -1.25 when you click it but I want it to be continuously adding -1.25 until you release the button. Right now it only moves once when you click the button. My code:
var character : GameObject;
function OnMouseDown () {
character.GetComponent(Animator).enabled = true;
BlahBlah ();
}
function OnMouseUp () {
character.GetComponent(Animator).enabled = false;
}
function BlahBlah () {
character.transform.position.x = character.transform.position.x + -1.25;
}
Does anyone have any ideas? Thanks!
You're simply forgetting to work in the Update()
var character : GameObject;
function OnMouseDown ()
{
character.GetComponent(Animator).enabled = true;
}
function OnMouseUp ()
{
character.GetComponent(Animator).enabled = false;
}
function BlahBlah ()
{
// I added time.deltaTime, since you'll be updating the value every "frame",
// and deltaTime refers to how much time passed from the last frame
// this makes your movement indipendent from the frame rate
character.transform.position.x = character.transform.position.x - (1.25* time.deltaTime);
}
// The standard Unity3D Update method runs every frame
void Update()
{
if (character.GetComponent(Animator).enabled)
{
BlahBlah ();
}
}
What I did here is using Unity logic. Almost everything works in the Update() function, which gets called every frame. Note that frame rate can vary based on machine / complexity of scene, so make sure to use always Time.deltaTime when adding something related.
Another note for you: modifying the position directly won't make your object react to collisions ( so you'll be moving through objects, but you will still "trigger" the collision ). So, if you want to manage collision, remember to use physics!
you can use Input.GetMouseButton because it registers every frame so when you hold down the mouse it gets it but because it checks every frame while the mouse is down so your object will move so fast so you may want to add a timer that if the time is reached it moves so it moves a bit slower so we check if a specified amount of time that we set in timeLeft is passed and the mouse is held down then we move our object
float timeLeft=0.5f;
void Update(){
timeLeft -= Time.deltaTime;
if (Input.GetMouseButton(0)){
if(timeLeft < 0)
{
BlahBlah ();
}
}
}
void BlahBlah () {
timeLeft=0.5f;
character.transform.position.x = character.transform.position.x + -1.25;
}
As I remember onMouseDown fires every frame if you're holding the button, so you'll need to do the movement within that function, let me check one sec.
this will be my first question so go on easy on me please ;)
I'm building my first game in Unity using my limited knowledge, tutorials and troubleshooting on google but i can't seem to fix this issue
i have a script that counts score(with a GUIText) and another one to pause the game(using timescale) and you probably guessed it already but when i pause the game it doesn't pause the score.
Script for Pausing:
var isPaused : boolean = false;
function Update()
{
if(Input.GetKeyDown("p"))
{
Pause();
}
}
function Pause()
{
if (isPaused == true)
{
Time.timeScale = 1;
isPaused = false;
}
else
{
Time.timeScale = 0;
isPaused = true;
}
}
Script for Score:
var Counter : int = 100000;
var Substractor : int = 0;
var Score : int = Counter - Substractor;
function Update (
) {
Score--;
guiText.text = "Score: "+Score;
}
the score script is attached to a gameobject with a gui text and the script for pausing the game is attached to the player
another issue is that when i'm moving(using the arrow keys) then press pause and then unpause the player moves faster and unpredictable for a splitsecond but this is only when i press pause while pressing the arrow buttons when i only press pause there is no issue, this is a small bugg that i'l try to fix myself, just thought i'd add it here for those that have an easy answer to this issue aswell
I only know this problem from other game frameworks and I've got no experiance with unity. But it should work the same way for unity as it does in other frameworks. You have two options:
Update is called after every rendering frame! So your timescale doesn'T influence how often update is called. Instead you have to find some dt or deltaT (don't know how it is called in unity and how to get it, but I mean the time, since unities the last call to update, please tell me in the comments, so I can edit this answer).
Then don't calculate your score like:
Score--;
but use something like:
Score -= 1 * dt
or
Score -= 1 * dt * Time.timeScale
(depending how exactly unity works)
alternatively you can sourround your update-block with some if-statement:
in Score:
function Update (
) {
if (! isPaused()) { // not sure how this function / property is called in unity
Score--;
guiText.text = "Score: "+Score;
}
}