I've worked out how to make a countdown timer. I would like to make a timer that counts minutes and seconds that I specify in the inspector. when I click an object the timer gets reduced by a few minutes and/or seconds. I will decide a little later. below is my code. Thanks!
using UnityEngine;
using System.Collections;
public class controllerScript : MonoBehaviour {
public GUIText timerText;
public float minutes;
void Start(){
timerText.text = "";
}
void Update(){
if (Input.GetMouseButtonDown(0)){
Debug.Log("pressed left click, casting ray");
CastRay();
}
minutes -= Time.deltaTime;
timerText.text = minutes.ToString("f0") + "";
}
void CastRay(){
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast (ray.origin, ray.direction, Mathf.Infinity);
//start statements for what happens when Objects are clicked
if (hit.collider.gameObject.name == "target01"){
Debug.Log("you've click obj 1, good work.");
}
if (hit.collider.gameObject.name == "target02"){
Debug.Log("well that's obj 2, even better!");
}
}
}
Dont know, what exact is your question,
but you should realize, that Time.deltaTime is time in seconds and not in minutes.
So you should change the line
minutes -= Time.deltaTime;
to
minutes -= Time.deltaTime / 60.0;
Related
I am trying to make an endless runner game where the player stands stationary on a platform, and objects are instantiated in different patterns further down the platform with an initial speed. I want those objects to increase their speed after a certain time interval is met. For example, if the time interval was 30 seconds and the baseline speed was 10, I would want the speed to go to 20 after 30 seconds have passed, then increase to 30 after another 30 seconds have past, etc. I have a spawner spawning in obstacle patterns with spawn points in various areas.
As of right now, the obstacles spawn in with the same speed no matter what, but increase their speed once they've been spawned in for the duration of the time interval. For example, object 1 is spawned in, moves for 5 seconds at the initial speed, then increases speed, followed by object 2 which does the exact same thing as object 1 upon spawning. Here is my object movement code:
using UnityEngine;
public class ObstacleMovement : MonoBehaviour
{
public Rigidbody rb;
// Keeps track of the time and increases speed based off the time
float time;
int seconds;
public int timeInterval; // Time interval where speed is increased
// Speed stuff
public Vector3 speedInc; // Speed increase each time interval
public float initialSpeed; // Initial speed in the Z direction
Vector3 currentSpeed; // Current speed of the object
// Vars for locking the object in place so no rotation/sliding occurs
float startPositionX;
Quaternion startRotation;
// Start is called before the first frame update
void Start()
{
startPositionX = transform.position.x;
startRotation = transform.rotation;
currentSpeed = new Vector3(0, 0, initialSpeed);
rb.velocity = currentSpeed;
}
// Update is called once per frame
void Update()
{
TrackTime();
if (seconds == timeInterval) {
currentSpeed = SpeedUp(currentSpeed);
time = 0;
}
rb.velocity = currentSpeed;
Debug.Log("Speed is: " + currentSpeed);
LockPos();
}
Vector3 SpeedUp(Vector3 iSpeed) {
Vector3 newSpeed = iSpeed + speedInc;
Debug.Log("Speeding up");
return newSpeed;
}
void TrackTime() {
time += Time.deltaTime;
seconds = (int)time % 60;
Debug.Log(seconds + " seconds have past");
}
void LockPos() {
Vector3 pos = transform.position;
pos.x = startPositionX;
transform.position = pos;
transform.rotation = startRotation;
}
}
In the code above I am creating a timer, keeping track of the seconds, and then increasing the speed after XXX seconds have passed. What am I doing wrong? I can post the code of the spawner and spawn points if that's necessary. Is there a more appropriate place for this to be executed? Thanks!!
If I understood you correctly, the problem is that your new spawned obstacles do not have the "Game current speed", right?
This is happening cause you're controlling the speed of every obstacles separated from the game state.
So what you do right now is: spawn obstacles always with the same speed, and then every spawned obstacle check if it's his turn to increase the speed.
But what you wan't is to have one object in charge of that spawning and time control, then, when the spawner spawns the obstacle, It assigns the velocity.
Something like:
public class ObstacleSpawner : MonoBehaviour
{
// Keeps track of the time and increases speed based off the time
float time = 0;
int seconds = 0;
public int timeInterval; // Time interval where speed is increased
// Speed stuff
public Vector3 speedInc; // Speed increase each time interval
public float initialSpeed; // Initial speed in the Z direction
Vector3 currentSpeed; // Current speed of the object
//Prefab of the object
GameObject obstaclePrefab = null;
//Tracking all the objects
List<GameObject> obstacleList = new List<GameObject>();
void InstantiateNewObstacle()
{
GameObject newObstacle = Instantiate(obstaclePrefab);
newObstacle.GetComponent<RigidBody>().velocity = currentSpeed;
//If you want to Lock the position (that should not be necessary, do it here too)
obstacleList.Add(newObstacle);
}
// Update is called once per frame
void Update()
{
TrackTime();
if (seconds == timeInterval) {
currentSpeed = SpeedUp(currentSpeed);
time = 0;
}
Debug.Log("Speed is: " + currentSpeed);
LockPos();
}
Vector3 SpeedUp(Vector3 iSpeed) {
Vector3 newSpeed = iSpeed + speedInc;
Debug.Log("Speeding up");
return newSpeed;
}
void TrackTime() {
time += Time.deltaTime;
seconds = (int)time % 60;
Debug.Log(seconds + " seconds have past");
}
}
Now every time you want to spawn one new Obstacle you only need to call ObstacleSpawner.InstantiateNewObject();. Remember, the obstacleList is not necessary but I'm pretty sure that would be useful for your type of game.
In my game, the camera speed is perfect as I wanted it to be.
In phones, while testing my game camera speed is dead slow. I don't know how to fix this and what is the root cause of this problem.
This is the script which I attached to the main camera.
public float translation;
public float highspeed;//highest speed of the camera
public float incfactor;//increasing ,multiplying number
public bool ismoving = false;
private float timer = 0f;
private Rigidbody2D dia;
private void Start()
{
dia = GetComponent<Rigidbody2D>();
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (hit.collider != null)
{
if (hit.collider.tag == "dialogue")
{
Destroy(hit.collider.gameObject);
ismoving = true;
}
}
}
if (ismoving == true)
{
Updatemove();
}
}
public void Updatemove()
{
timer += Time.deltaTime;
if (timer > 1f && translation < highspeed)
{ //after 1 second has passed...
timer = 0; // reset timer
translation += incfactor; //increase speed by 0.5
}
transform.Translate(0, translation, 0);
}
You are calling Updatemove in Update which is called every frame.
But than you Translate by a fixed value translation which is frame-dependent (lower framerate => less calls => slower movement)
You're object will move with a speed of (translation * framerate) / seconds
in order to eliminate that framerate factor and get a stable, device independent speed of translation / seconds you have to multiply by Time.deltaTime.
so it should rather be
public void Updatemove()
{
timer += Time.deltaTime;
if (timer > 1f && translation < highspeed)
{ //after 1 second has passed...
timer = 0; // reset timer
translation += incfactor ; //increase speed by 0.5
}
transform.Translate(0, translation * Time.deltaTime, 0);
}
since Time.deltaTime is a quite small value (1/framerate = 0.017 (for 60 fps)) you will probably have to increase your incfactor more or less by a factor of 60
I am learning Unity from a Swift SpriteKit background where moving a sprite's x Position is as straight forward as an running an action as below:
let moveLeft = SKAction.moveToX(self.frame.width/5, duration: 1.0)
let delayAction = SKAction.waitForDuration(1.0)
let handSequence = SKAction.sequence([delayAction, moveLeft])
sprite.runAction(handSequence)
I would like to know an equivalent or similar way of moving a sprite to a specific position for a specific duration (say, a second) with a delay that doesn't have to be called in the update function.
gjttt1's answer is close but is missing important functions and the use of WaitForSeconds() for moving GameObject is unacceptable. You should use combination of Lerp, Coroutine and Time.deltaTime. You must understand these stuff to be able to do animation from Script in Unity.
public GameObject objectectA;
public GameObject objectectB;
void Start()
{
StartCoroutine(moveToX(objectectA.transform, objectectB.transform.position, 1.0f));
}
bool isMoving = false;
IEnumerator moveToX(Transform fromPosition, Vector3 toPosition, float duration)
{
//Make sure there is only one instance of this function running
if (isMoving)
{
yield break; ///exit if this is still running
}
isMoving = true;
float counter = 0;
//Get the current position of the object to be moved
Vector3 startPos = fromPosition.position;
while (counter < duration)
{
counter += Time.deltaTime;
fromPosition.position = Vector3.Lerp(startPos, toPosition, counter / duration);
yield return null;
}
isMoving = false;
}
Similar Question: SKAction.scaleXTo
The answer of git1 is good but there is another solution if you do not want to use couritines.
You can use InvokeRepeating to repeatedly trigger a function.
float duration; //duration of movement
float durationTime; //this will be the value used to check if Time.time passed the current duration set
void Start()
{
StartMovement();
}
void StartMovement()
{
InvokeRepeating("MovementFunction", Time.deltaTime, Time.deltaTime); //Time.deltaTime is the time passed between two frames
durationTime = Time.time + duration; //This is how long the invoke will repeat
}
void MovementFunction()
{
if(durationTime > Time.time)
{
//Movement
}
else
{
CancelInvoke("MovementFunction"); //Stop the invoking of this function
return;
}
}
You can use co-routines to do this. To do this, create a function that returns type IEnumerator and include a loop to do what you want:
private IEnumerator foo()
{
while(yourCondition) //for example check if two seconds has passed
{
//move the player on a per frame basis.
yeild return null;
}
}
Then you can call it by using StartCoroutine(foo())
This calls the function every frame but it picks up where it left off last time. So in this example it stops at yield return null on one frame and then starts again on the next: thus it repeats the code in the while loop every frame.
If you want to pause for a certain amount of time then you can use yield return WaitForSeconds(3) to wait for 3 seconds. You can also yield return other co-routines! This means the current routine will pause and run a second coroutine and then pick up again once the second co-routine has finished.
I recommend checking the docs as they do a far superior job of explaining this than I could here
I am learning Unity from a Swift SpriteKit background where moving a sprite's x Position is as straight forward as an running an action as below:
let moveLeft = SKAction.moveToX(self.frame.width/5, duration: 1.0)
let delayAction = SKAction.waitForDuration(1.0)
let handSequence = SKAction.sequence([delayAction, moveLeft])
sprite.runAction(handSequence)
I would like to know an equivalent or similar way of moving a sprite to a specific position for a specific duration (say, a second) with a delay that doesn't have to be called in the update function.
gjttt1's answer is close but is missing important functions and the use of WaitForSeconds() for moving GameObject is unacceptable. You should use combination of Lerp, Coroutine and Time.deltaTime. You must understand these stuff to be able to do animation from Script in Unity.
public GameObject objectectA;
public GameObject objectectB;
void Start()
{
StartCoroutine(moveToX(objectectA.transform, objectectB.transform.position, 1.0f));
}
bool isMoving = false;
IEnumerator moveToX(Transform fromPosition, Vector3 toPosition, float duration)
{
//Make sure there is only one instance of this function running
if (isMoving)
{
yield break; ///exit if this is still running
}
isMoving = true;
float counter = 0;
//Get the current position of the object to be moved
Vector3 startPos = fromPosition.position;
while (counter < duration)
{
counter += Time.deltaTime;
fromPosition.position = Vector3.Lerp(startPos, toPosition, counter / duration);
yield return null;
}
isMoving = false;
}
Similar Question: SKAction.scaleXTo
The answer of git1 is good but there is another solution if you do not want to use couritines.
You can use InvokeRepeating to repeatedly trigger a function.
float duration; //duration of movement
float durationTime; //this will be the value used to check if Time.time passed the current duration set
void Start()
{
StartMovement();
}
void StartMovement()
{
InvokeRepeating("MovementFunction", Time.deltaTime, Time.deltaTime); //Time.deltaTime is the time passed between two frames
durationTime = Time.time + duration; //This is how long the invoke will repeat
}
void MovementFunction()
{
if(durationTime > Time.time)
{
//Movement
}
else
{
CancelInvoke("MovementFunction"); //Stop the invoking of this function
return;
}
}
You can use co-routines to do this. To do this, create a function that returns type IEnumerator and include a loop to do what you want:
private IEnumerator foo()
{
while(yourCondition) //for example check if two seconds has passed
{
//move the player on a per frame basis.
yeild return null;
}
}
Then you can call it by using StartCoroutine(foo())
This calls the function every frame but it picks up where it left off last time. So in this example it stops at yield return null on one frame and then starts again on the next: thus it repeats the code in the while loop every frame.
If you want to pause for a certain amount of time then you can use yield return WaitForSeconds(3) to wait for 3 seconds. You can also yield return other co-routines! This means the current routine will pause and run a second coroutine and then pick up again once the second co-routine has finished.
I recommend checking the docs as they do a far superior job of explaining this than I could here
Hi I'm a beginner in unity and I want to be able to add 10 points to the score every 5 seconds since the game started, this is how i tried to implement it
private int score;
void Update () {
Timer = Time.time;
if (Timer > 5f) {
score += 5;
Timer -= 5f;
}
ScoreText.text = score.ToString ();
}
this is not working what happens is the score increases rapidly after 5f and then it crashes my game.
The math for calculating every 5 seconds is wrong. You should not be doing Timer = Time.time; every loop, that just throws away the old value of Timer. Use Time.deltaTime and add it to the timer instead.
//Be sure to assign this a value in the designer.
public Text ScoreText;
private int timer;
private int score;
void Update () {
timer += Time.deltaTime;
if (timer > 5f) {
score += 5;
//We only need to update the text if the score changed.
ScoreText.text = score.ToString();
//Reset the timer to 0.
timer = 0;
}
}
I know I am a bit late to answer, but the same can be done with Mathf.FloorToInt(Time.timeSinceLevelLoad)