I just got into Game Dev and I need my script to enable when my player steps a cube trigger, but I don't know how.
This is the Script that I typed and I can't figure out if I should erase the Void Start or not?
public class CountdownTimer : MonoBehaviour {
public bool timerIsRunning;
public Text timeText;
public float timeRemaining = 10;
private void Start()
{
timerIsRunning = true;
}
void Update(){
if (timerIsRunning)
{
if (timeRemaining > 0)
{
timeRemaining -= Time.deltaTime;
DisplayTime(timeRemaining);
}
else
{
Debug.Log("Time has run out!");
timeRemaining = 0;
timerIsRunning = false;
}
}
}
void DisplayTime(float timeToDisplay){
timeToDisplay += 1;
float minutes = Mathf.FloorToInt(timeToDisplay / 60);
float seconds = Mathf.FloorToInt(timeToDisplay % 60);
timeText.text = string.Format("{0:00}:{1:00}", minutes, seconds);
}
}
I think you can make good use of a trigger collider. To do that, you need to add a collider of your choice to your zone and set it as a trigger. Be sure to have a collider and a rigidbody on your player.
Then in your script you can use the function OnTriggerEnter who will be called when an object enter in your zone defined by your trigger collider.
For your countdown method, you can make good use of a couroutine. It will look like this :
IEnumerator DisplayTime() {
timeIsRunning = true;
for (int i = 0; i < timeRemaining; i++) {
// your code to change the text
yield return new WaitForSeconds(1);
}
timeIsRunning = false;
}
private void OnColliderEnter(Collider other) {
if(!timeIsRunning) {
StartCouroutine(DisplayTime());
}
}
What this code does is when an object enter in the trigger, it starts a routine who will update the time displayed each second until the countdown is finished.
With that you won't need your Start and your Update methods anymore.
If you want more informations on trigger collider : https://docs.unity3d.com/ScriptReference/Collider-isTrigger.html
If you want more informations on couroutines : https://docs.unity3d.com/Manual/Coroutines.html
If you want more informations on the method OnTriggerEnter : https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html
I am currently doing the tutorial learn with code from unity, in this section there are bonus challenges, that do not help you in resolving it. It says that i have to prevent the player from spamming the spacebar key to spawn dogs.
I am new to C#, i started to looking online but i see something about CoRoutines and i still dont know what that is, is there a simple way to do this, searching online i found something like this, but i cant make it work.
I also tried to make some conditional like canSpawn but i do not know how to implement it well, and Unity gives me an error that i cant use && between a bool and a keypress event
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControllerX : MonoBehaviour
{
public GameObject dogPrefab;
public float time = 2.0f;
public float timer = Time.time;
// Update is called once per frame
void Update()
{
timer -= Time.deltaTime;
if (timer > time)
{
// On spacebar press, send dog
if (Input.GetKeyDown(KeyCode.Space))
{
spawnDog();
}
timer = time;
}
void spawnDog()
{
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
}
}
You were close. One thing that might make it easier to understand the logic, is to just count up instead of trying to count down. So, in your case, the code would look like this:
void Update ( )
{
timer += Time.deltaTime;
if ( timer >= time )
{
if ( Input.GetKeyDown ( KeyCode.Space ) )
{
spawnDog ( );
timer = 0;
}
}
}
void spawnDog ( )
{
Instantiate ( dogPrefab, transform.position, dogPrefab.transform.rotation );
}
The timer keeps being added to, and when it's greater than your time value (in this case 2.0f), it allows you to press a key. IF a key is then pressed, the timer is reset to 0, and the player needs to wait time time (2.0f) before being able to press the space key again.
I used Coroutines for this task, it has a little bit more code but it works nicely.
public class PlayerControllerX : MonoBehaviour
{
public GameObject dogPrefab;
private bool isCoolDown = false;
private float coolDown = 1f;
private void Update( )
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (isCoolDown == false)
{
SpawnDog( );
StartCoroutine(CoolDown( ));
}
}
}
IEnumerator CoolDown( )
{
isCoolDown = true;
yield return new WaitForSeconds(coolDown);
isCoolDown = false;
}
private void SpawnDog( )
{
Instantiated(dogPrefab, transform.position, dogPrefab.transform.rotation);
}
}
I am using my phone. I am sorry if i made some syntax error.
bool isReadyForInstantiate;
void Start(){
isReadyForInstantiate = true;
}
void Update(){
if(isReadyForInstantiate && Input.GetKeyDown(KeyCode.Space)){
StartCoroutine(PreventSpam());
Instantiate(dogPrefab, transform.position, Quaternion.identity);
}
}
IEnumerator PreventSpam(){
isReadyForInstantiate = false;
yield return new WaitForSeconds(2);
isReadyForInstantiate = true;
}
here my solution based on a StopWatch:
using UnityEngine;
using System.Diagnostics; // hides UnityEngine.Debug. if needed use qualified call
public class PlayerControllerX : MonoBehaviour
{
public GameObject dogPrefab;
public double dogDelayMillis = 2000d;
private Stopwatch stopWatch;
private void Start()
{
stopWatch = new Stopwatch();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (stopWatch.IsRunning)
{
if (stopWatch.Elapsed.TotalMilliseconds > dogDelayMillis)
{
stopWatch.Reset();
SpawnDog();
}
}
else
{
SpawnDog();
}
}
}
private void SpawnDog()
{
stopWatch.Start();
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
}
}
Another example just for fun
public GameObject dogPrefab;
[Range(0f,2f)]
private float timer = 1.0f;
private float waitTime = 1.0f;
// Update is called once per frame
void Update()
{
// Delay Input Timer - only execute the spacebar command if timer has caught up with waitTime
if (timer < waitTime)
{}
// On spacebar press, send dog
else if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
// Resets Timer
timer = 0;
}
// Run Timer every frame
timer += Time.deltaTime;
Debug.Log(timer);
}
}
I was stuck on the same exact thing, thank you. The code below is what I went with because it's short and sweet.
public GameObject dogPrefab;
[Range(0f,2f)]
private float timer = 1.0f;
private float waitTime = 1.0f;
// Update is called once per frame
void Update()
{
// Delay Input Timer - only execute the spacebar command if timer has caught up with waitTime
if (timer < waitTime)
{}
// On spacebar press, send dog
else if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(dogPrefab, transform.position, dogPrefab.transform.rotation);
// Resets Timer
timer = 0;
}
// Run Timer every frame
timer += Time.deltaTime;
Debug.Log(timer);
}
}
I have a game where I have time to give energy. My timer works fine when game is active but when game is inactive the time pauses and after I start game again the timer starts from wher it was left.
I want keep timer going even if the game is inactive and add energy.
using System;
using UnityEngine;
using UnityEngine.UI;
public class EnergyAdder : MonoBehaviour
{
// Start is called before the first frame update
public float waitTime = 600;
Timer timer;
public GameRoot gameRoot;
void Awake()
{
//timer = new Timer(waitTime);
float remainingTime = PlayerPrefs.GetFloat("TimeOnExit");
timer = new Timer(remainingTime);
}
// Update is called once per frame
void Update()
{
if (gameRoot.energyCap >= 5)
{
GetComponent<Text>().text = "Full";
timer.refresh();
}
else
{
timer.countDown();
if (timer.isFinished())
{
timer = new Timer(waitTime);
timer.refresh();
gameRoot.AddEnergy(1);
}
UpdateClock();
}
}
void UpdateClock()
{
int seconds = ((int)timer.timeLeft) % 60;
int minutes = (int)(timer.timeLeft / 60);
GetComponent<Text>().text = minutes.ToString() + ":" + seconds.ToString("00");
}
void OnApplicationQuit()
{
PlayerPrefs.SetFloat("TimeOnExit", timer.timeLeft);
}
}
Please help I'm new to unity and c#.
What you are doing is saving time value when you left, and load that value when you start the game again.
Maybe you should (when start the game) compare that loaded time with the current time, the difference will be the time elapsed.
I have an animation in 4 PNG images. I want to have the frames played through over the course of 1/2 second in the order 1-2-3-4-2-1 with transparency transitions.
What I wrote was supposed to have the first frame appear immediately when the parent object holding the different sprites is generated, then have it turn transparent over 1/12 of a second while the second frame turns opaque, and so forth until the last frame ends its transparent-opaque-transparent cycle.
It's probably not the most efficient way, but I made a prefab of en empty object under which are placed the 6 sprite-frames, with each sprite given an individual script.
I'm posting the first three scripts as an example:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Frame1 : MonoBehaviour
{
private SpriteRenderer thisSprite;
private Color alpha;
private float timer;
// Start is called before the first frame update
void Start()
{
alpha.a = 255;
thisSprite.GetComponent<SpriteRenderer>().color = alpha;
}
// Update is called once per frame
void Update()
{
timer = timer + Time.deltaTime;
alpha.a -= timer * 3060;
thisSprite.GetComponent<SpriteRenderer>().color = alpha;
if (timer >= 1/12)
{
Destroy(gameObject);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Frame2 : MonoBehaviour
{
private SpriteRenderer thisSprite;
private Color alpha;
private float timer;
private int direction;
// Start is called before the first frame update
void Start()
{
alpha.a = 0;
thisSprite.GetComponent<SpriteRenderer>().color = alpha;
}
// Update is called once per frame
void Update()
{
if (direction == 0)
{
timer = timer + Time.deltaTime;
alpha.a += timer * 3060;
thisSprite.GetComponent<SpriteRenderer>().color = alpha;
if (timer >= 1/12)
{
direction = 1;
}
}
if (direction == 1)
{
timer = timer - Time.deltaTime;
alpha.a += timer * 3060;
thisSprite.GetComponent<SpriteRenderer>().color = alpha;
if (timer >= 1/6)
{
Destroy(gameObject);
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Frame3 : MonoBehaviour
{
private SpriteRenderer thisSprite;
private Color alpha;
private float timer;
private int direction;
// Start is called before the first frame update
void Start()
{
alpha.a = 0;
thisSprite.GetComponent<SpriteRenderer>().color = alpha;
timer -= 1 / 12;
}
// Update is called once per frame
void Update()
{
if (direction == 0)
{
timer = timer + Time.deltaTime;
alpha.a += timer * 3060;
thisSprite.GetComponent<SpriteRenderer>().color = alpha;
if (timer >= 1 / 12)
{
direction = 1;
}
}
if (direction == 1)
{
timer = timer - Time.deltaTime;
alpha.a += timer * 3060;
thisSprite.GetComponent<SpriteRenderer>().color = alpha;
if (timer >= 1 / 6)
{
Destroy(gameObject);
}
}
}
}
They all seem to be visible the moment they are generated, and they don't fade away or even get destroyed at all. What is the issue?
Thanks.
As the comments suggest, using animations is a viable alternative. However, your code will not work simply because alpha accepts a value from 0 to 1 instead of 0 to 255.
So simply adjust your logic to fade from 1 down to 0 and you should see your fade transitions.
I am currently creating a hidden object game and I have been stuck on how to add a timer and countdown to my game. I have currently a score which generates after all of the objects have been clicked however I would love if the score went up gradually once the user clicked on each one. here is my code below so far.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class trackingclicks : MonoBehaviour {
//static variable added to count users clicks
public static int totalclicks=0;
//"mouseclick" keycode variable to look for mouse click
public KeyCode mouseclick;
public Transform scoreObj;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
//checks the change in time, aka how much time has passed- bonus time starts at 90
clickcontrol.timeBonus -= Time.deltaTime;
if (clickcontrol.remainItems == 0)
{
clickcontrol.totalScore += (70 + (Mathf.RoundToInt(clickcontrol.timeBonus)));
scoreObj.GetComponent<TextMesh>().text = "Score : " + clickcontrol.totalScore;
clickcontrol.remainItems = -1;
}
//Check for mouse click
if (Input.GetKeyDown (mouseclick))
{
totalclicks += 1;
}
if (totalclicks >= 5)
{
Debug.Log ("FAIL!!!");
totalclicks = 0;
}
}
}
You can use coroutines for timers (coroutines execute code after a certain amount of time). If you want your score to increment gradually once the player clicks on an object (I think that's what you're asking), then something like this should work:
public int score;
IEnumerator IncrementScore(int amount, int interval) { //amount is the amount of score to add over the time, interval is the time IN SECONDS between adds
for (int i = 0; i < amount; i++) {
yield return new WaitForSeconds(interval);
score++;
}
}
I wasn't sure where the score variable was so I made a new one; you can set it to your own, wherever it is. If you need more help, feel free to ask.