I am somewhat new to C# and currently programming a method for instantiating objects in the Unity Editor.
The problem I am having with the code below is a logical error as follows: Instead of objects being created with 10 seconds in between, they are all spawned at the same time.
It is clear to me that this is a logical error. I find this hard to debug because it more so seems that my code for the timer simply isn't running. I've scratched my head as to why, can anyone help an aspiring rookie out? Thanks.
private void CreateObjects(GameObject objectToSpawn, float timer = 0.0f, float timerMax = 10.0f)
{
//If count of objects is less than the maximum constant, instantiate more at random web positions.
while (spiderCount < 7)
{
//StartCoroutine("SpiderGeneration");
timer += Time.deltaTime;
if (timer >= timerMax)
{
//spiderArray = GameObject.FindGameObjectsWithTag("spider");
//spiderCount = spiderArray.Length;
Debug.Log("spawnTime is set to true via ObjectGeneration");
//Generate a random number to choose from a series of set spawn points.
randPos = Random.Range(1, 4);
if (randPos == 1)
{
//Instantiate(object, position, quat);
Instantiate(objectToSpawn, rand1, transform.rotation);
Debug.Log("SPAWN 1");
timer = 0.0f;
}
else if (randPos == 2)
{
Instantiate(objectToSpawn, rand2, transform.rotation);
Debug.Log("SPAWN 2");
timer = 0.0f;
}
else if (randPos == 3)
{
Instantiate(objectToSpawn, rand3, transform.rotation);
Debug.Log("SPAWN 3");
timer = 0.0f;
}
else
{
Debug.Log("OBJECT GEN ERROR");
}
}
}
}
You could approach this in another way and code it simply using the Update() method that Unity calls every frame.
private int spiderCount;
private float timer;
public float TimerMax;
public List<Transform> spawnPoints = new List<Transform>(0);
private void Update ( )
{
timer += Time.deltaTime;
if ( spiderCount < 7 && timer >= TimerMax )
{
if ( spawnPoints.Count == 0 ) { Debug.LogError ( "You don't have any spawn points!" ); return; }
var spawnPointIndex = UnityEngine.Random.Range ( 0, spawnPoints.Count );
Instantiate ( objectToSpawn, spawnPoints[spawnPointIndex], transform.rotation );
++spiderCount;
timer = 0;
}
}
Not knowing how you'd like to set up your scene though, you might want ALL 7 spiders to appear straight away, with a 10 second (TimeMax) delay after that? But, either way, this should get you started.
I believe your issue is that this isn't being run in the update function. I'm fairly certain this would work if you were to call for the method to run in the update function and remove the while loop. This is because the Update() function runs once every frame, so when you add Time.deltaTime to a value, it will always only increase by 1 every second (allowing the timer you have here to work), however, what you have here does not add Time.deltaTime once every frame, it adds it recursively as long as your while(spiderCount < 7) returns true, this causes it to happen a bunch of times on the first frame, because it is reaching the timer value required on that first frame as is adding to the timer many times until it meets the criteria of the while function. This should definitely work if you do the following (also I read that you said you have the method in your FixedUpdate() method, you should only use FixedUpdate for physics updates, rather place it in your Update() method):
void Update()
{
CreateObjects({input the parameters here});
}
private void CreateObjects(GameObject objectToSpawn, float timer = 0.0f, float timerMax = 10.0f)
{
//If count of objects is less than the maximum constant, instantiate more at random web positions.
if (spiderCount < 7)
{
timer += Time.deltaTime;
if (timer >= timerMax)
{
randPos = Random.Range(1, 4);
if (randPos == 1)
{
//Instantiate(object, position, quat);
Instantiate(objectToSpawn, rand1, transform.rotation);
Debug.Log("SPAWN 1");
timer = 0.0f;
}
else if (randPos == 2)
{
Instantiate(objectToSpawn, rand2, transform.rotation);
Debug.Log("SPAWN 2");
timer = 0.0f;
}
else if (randPos == 3)
{
Instantiate(objectToSpawn, rand3, transform.rotation);
Debug.Log("SPAWN 3");
timer = 0.0f;
}
else
{
Debug.Log("OBJECT GEN ERROR");
}
}
}
}
I am fairly certain this should work, otherwise you can just use coroutines(which I would personally use), like so:
private void Start()
{
StartCoroutine(CreateObjects({input parameters here}));
}
IEnumerator CreateObjects(GameObject objectToSpawn, float timer = 0.0f, float timerMax = 10.0f)
{
//Wait for the allotted time amount (in this case 10 seconds)
yield return new WaitForSeconds(timerMax);
randPos = Random.Range(1, 4);
if (randPos == 1)
{
//Instantiate(object, position, quat);
Instantiate(objectToSpawn, rand1, transform.rotation);
Debug.Log("SPAWN 1");
timer = 0.0f;
}
else if (randPos == 2)
{
Instantiate(objectToSpawn, rand2, transform.rotation);
Debug.Log("SPAWN 2");
timer = 0.0f;
}
else if (randPos == 3)
{
Instantiate(objectToSpawn, rand3, transform.rotation);
Debug.Log("SPAWN 3");
timer = 0.0f;
}
else
{
Debug.Log("OBJECT GEN ERROR");
}
//If the spider count less than required, start the coroutine again to spawn another
if(spiderCount < 7)
{
StartCoroutine(CreateObjects({input parameters here}));
}
}
If you have any questions at all let me know, I am sure this isn't difficult at all to fix, just let me know if you need anything cleared up! (I also apologize if the beginning is a tad confusing to read, I confused myself at first and it shows through haha, but I cleared up when I got to the code)
Alright I have figured it out. To anyone reading this that had to same issues as me, my advice is as follows:
So you want a coroutine to start in the update function and not start multiple coroutines every frame, right? You need to set a flag for the coroutine. That was the answer. I simply set a one-time flag to activate upon starting the coroutine that prevents any more from starting until you decide to run it again.
Here is the code.
(Also I wanna say thanks to everyone that helped me out with this! I was able to find the right answer thanks to everyones input :) )
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spiderGenerator : MonoBehaviour
{
public GameObject player;
public GameObject spiderPrefab;
public GameObject[] spiderArray = new GameObject[7];
public int spiderCount = 0;
private int randPos;
private Vector3 rand1;
private Vector3 rand2;
private Vector3 rand3;
bool inRange = false;
bool spawnerFlag = false;
// Start is called before the first frame update
void Start()
{
player = GameObject.FindGameObjectWithTag("Player");
rand1 = new Vector3(20.49f, 66.671f, 56.98f);
rand2 = new Vector3(8.88f, 66.671f, 61.65f);
rand3 = new Vector3(-1f, 66.671f, 65.52f);
}
// Update is called once per frame
void Update()
{
spiderArray = GameObject.FindGameObjectsWithTag("spider");
spiderCount = spiderArray.Length;
if (player.transform.position.z < 78 && player.transform.position.z > 47 && player.transform.position.x < 25 && player.transform.position.x > -6 && player.transform.position.y < 70 && player.transform.position.y > 60)
{
inRange = true;
}
else
{
inRange = false;
}
if (inRange == true && spawnerFlag == false)
{
StartCoroutine(CreateObjects(spiderPrefab));
Debug.Log("Coroutine CreateObjects for {0} STARTED", spiderPrefab);
spawnerFlag = true;
}
}
IEnumerator CreateObjects(GameObject objectToSpawn, float timerMax = 10.0f)
{
while (inRange == true && spiderCount < 7)
{
yield return new WaitForSeconds(timerMax);
Debug.Log("spawn for {0} is set to true via ObjectGeneration", objectToSpawn);
//Generate a random number to choose from a series of set spawn points.
randPos = Random.Range(1, 4);
if (randPos == 1)
{
//Instantiate(object, position, quat);
Instantiate(objectToSpawn, rand1, transform.rotation);
Debug.Log("SPAWN 1");
}
else if (randPos == 2)
{
Instantiate(objectToSpawn, rand2, transform.rotation);
Debug.Log("SPAWN 2");
}
else if (randPos == 3)
{
Instantiate(objectToSpawn, rand3, transform.rotation);
Debug.Log("SPAWN 3");
}
else
{
Debug.Log("OBJECT GEN ERROR");
}
}
Debug.Log("Coroutine TERMINATED");
yield break;
}
// need to put everything below the wait for 10 seconds to get results.
}
Related
I am very new to c# and I've come across a problem with my enemy spawner. I am making an endless top-down shooter, and after 20 enemies have been spawned and then destroyed, the enemies stop appearing. My score counter continues to increase though, which leads me to believe they're somehow being destroyed.
Here is the enemy spawn controller:
void Update()
{
if (!spawningObject && GameController.EnemyCount < spawnSettings[0].maxObjects)
{
spawningObject = true;
float pick = Random.value * totalWeight;
int chosenIndex = 0;
float cumulativeWeight = enemySpawnables[0].weight;
while(pick > cumulativeWeight && chosenIndex < enemySpawnables.Count - 1)
{
chosenIndex++;
cumulativeWeight += enemySpawnables[chosenIndex].weight;
}
StartCoroutine(SpawnObject(enemySpawnables[chosenIndex].type, Random.Range(spawnSettings[0].minWait / GameController.DifficultyMultiplier, spawnSettings[0].maxWait / GameController.DifficultyMultiplier)));
Spawn();
}
}
private IEnumerator SpawnObject(string type, float time)
{
yield return new WaitForSeconds(time);
randomSpawnPoint = Random.Range(0, enemySpawners.Length);
randomEnemy = Random.Range(0, enemy.Length);
enemyPool.SpawnObject(enemySpawners[randomSpawnPoint].position, transform.rotation);
spawningObject = false;
GameController.EnemyCount++;
}
And here is the enemy controller (attached to enemy prefab):
public void Start()
{
myRB = GetComponent<Rigidbody>();
player = FindObjectOfType<PlayerController>();
}
private void OnEnable()
{
player = FindObjectOfType<PlayerController>();
}
void Update()
{
if (health <= 0)
{
Die();
}
}
void FixedUpdate()
{
transform.LookAt(player.transform.position);
myRB.velocity = (transform.forward * moveSpeed);
//Falling
if(myRB.velocity.y < 0)
{
myRB.velocity += Vector3.up * Physics.gravity.y * (fallMultiplier - 1) * Time.deltaTime;
}
}
public void Die()
{
print("Enemy" + this.gameObject.name + " has died!");
EnemySpawn.instance.enemyPool.ReturnObject(this.gameObject);
player.GetComponent<PlayerController>().points += pointsToGive;
ScoreController.scoreValue += 1;
}
The only thing that should affect enemy health is the bullet. Here is the part of the bullet controller that affects enemy health:
public void OnTriggerEnter(Collider other)
{
if(other.tag == "Enemy")
{
triggeringEnemy = other.gameObject;
triggeringEnemy.GetComponent<EnemyController>().health -= damage;
PlayerController.instance.bulletPool.ReturnObject(gameObject);
}
}
The issue always happens after 20 enemies have been spawned/destroyed and 20 points have been achieved. Before then, enemy movement is normal and everything seems to be working as it should. It could very well be something very simple that I'm missing, but I'd appreciate any help!
When you do engage logic mistake good way to find it is Visual Studio debugging.
Here is good official article about whole process - https://docs.unity3d.com/Manual/ManagedCodeDebugging.html.
I would place breakpoint right at start of Update method to see that EnemyCount increases over time and then you will understand that you forgot to do decrement it.
I have a ship which is moving around with rigidbody velocity, and when the player has no input I want the ship to slow down to 0 and then stay at 0 until there's more input. What I have now is:
if(yAxis == 0)
{
StartCoroutine (StopRoutine());
}
IEnumerator StopRoutine()
{
yield return new WaitForSeconds (0.5f);
Vector2 force = rb.velocity;
rb.velocity = (new Vector2(0.2f,0.2f)) - force;
}
and all that does is make the ship go backward which I understand is due to it subtracting forever with no clamp, I just don't know how to make it go to 0 and STAY at 0, I also don't know how I would do it the other way too (making a vector2 which is in the negatives go to 0)
Actually you able to do many different ways. If want a use coroutines for this sample. Try this at update method in your script...
First of all you need to declare a variable to check have any input? (I think this is wind, fuel etc.)
bool isInput = true;
IEnumerator stopRoutine(float targetX, float targetY, float valueX, float valueY, float t) //targetX and targetY your target speed values, valueX and valueY is your acceleration or deceleration values and t is waitTime for while loop...
{
if (isInput)
{
isInput = !isInput; // You've to do this because unity update function re-runs every deltaTime.
Vector2 firstVelocity = rb.velocity;
if (firstVelocity.x < 0f && firstVelocity.y < 0f)
{
while (rb.velocity.x < targetX || rb.velocity.y < targetY)
{
rb.velocity += new Vector2(valueX, valueY);
yield return new WaitForSecondsRealtime(t);
}
}
else
{
while (rb.velocity.x > targetX || rb.velocity.y > targetY)
{
rb.velocity -= new Vector2(valueX, valueY);
yield return new WaitForSecondsRealtime(t);
}
}
}
}
I don't want to do it for you completely, but I want you to understand the logic in the event. Ok try this method in update()...
I am creating a 3D Shooter and I am trying to make an enemy deal damage to the player every set seconds. I have made the enemy deal damage with a raycast but it deals the damage way too fast.
I thought using yield return new WaitForSeconds(2) would take 1 damage away from the player every 2 seconds but it deals damage to the player a lot faster.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMove : MonoBehaviour
{
public Transform target;
public Transform player;
public float enemySpeed;
public int moveTrigger = 1;
public int isAttacking;
public float distanceFromPlayer;
void Update()
{
distanceFromPlayer = Vector3.Distance(target.transform.position, player.transform.position);
if (distanceFromPlayer <= 10 && moveTrigger == 1)
{
transform.LookAt(target);
StartCoroutine(EnemyDamage());
}
if (distanceFromPlayer <10 && moveTrigger == 1 && distanceFromPlayer >3)
{
transform.Translate(Vector3.forward * enemySpeed * Time.deltaTime);
}
}
IEnumerator EnemyDamage()
{
RaycastHit PlayerHit;
if (Physics.Raycast(target.transform.position, target.transform.forward, out PlayerHit))
{
Debug.Log(PlayerHit.transform.name);
Target target = PlayerHit.transform.GetComponent<Target>();
if (target != null)
{
yield return new WaitForSeconds(2);
GlobalHealth.playerHealth -= 1;
yield return null;
}
}
}
}
You are starting a coroutine in every update loop so every frame your damage coroutine gets called and applies your 1 damage after 2 seconds.
If you want a damage over time effect the suggestion of using an game tick timer is correct, but if you want your enemy to only be able to attack every x seconds you need to implement some kind of cooldown on your damage function. For example add up Time.deltaTime until the time you want has past, and only then the enemy is able to deal damage again. You can do that with a boolean.
As mentioned in other answers, you are starting a new coroutine each frame. You should do all your waiting and looping inside your coroutine, as execution exits and re-enters your coroutine from the yeild statment. This is how you would write this to work
// in update
if (distanceFromPlayer <= 10 && moveTrigger == 1){
transform.LookAt(target);
if(!isAttacking)
StartCoroutine(EnemyDamage());
}
IEnumerator EnemyDamage()
{
isAttacking = true;
while(distanceFromPlayer <= 10){ // in range
RaycastHit PlayerHit;
if (Physics.Raycast(target.transform.position, target.transform.forward, out PlayerHit)){
Target target = PlayerHit.transform.GetComponent<Target>();
if (target != null){
GlobalHealth.playerHealth -= 1;
yield return new WaitForSeconds(2);
}
}
}
isAttacking = false; // out of range
yield return null;
}
You can use FixedUpdate → set a local variable bool alreadyShoot = false.
In your EnemyDamage() add a if(!alreadyShoot) before damages application and set alreadyShoot to true after damages application.
In FixedUpdate you can set alreadyShoot to false.
You can choose an other solution to set alreadyShoot to false instead of FixedUpdate (for example a coroutine that trigger each seconds, ...)
in update loop, check when two seconds have passed when the player is in range
float timeInRange = 0.0f;
bool inRange = false;
if (distanceFromPlayer <= 10 && moveTrigger == 1)
{
inRange = true;
}
else
{
inRange = false;
timeInRange = 0;
}
if (inRange)
{
timeInRange += Time.DeltaTime;
}
if (timeInRange > 2.0f)
{
GlobalHealth.playerHealth -= 1;
timeInRange = 0.0f;
}
I am having difficulty delaying the movement of my character in Unity 2018.4, I suspect this is more of just a problem with my code as apposed to unity.
Edit:
I want to be able to hold down the right arrow key, have the character not move for 415ms, then be able to move for 580ms, after which he cannot move for 350ms (to let the animation finish playing)
I tried using countdown in a IE numerator to wait and then call my movement function but this results in my character not moving after the animation has played.
//What makes the character move, works fine if executed on its own in update
private void ExecuteMovement(float dir)
{
currentPosition = transform.position;
currentPosition.x += dir * Time.deltaTime * speed;
transform.position = currentPosition;
}
//Trying to use waitforseconds to delay the execution while the animation plays
private IEnumerator Movement(float dir)
{
yield return new WaitForSeconds(0.5f);
ExecuteMovement(dir);
}
void Update()
{
if (0 > Input.GetAxis("Horizontal"))
{
//This is to flip image
transform.eulerAngles = new Vector3(0, 180, 0);
//starts animation
animator.SetBool("isSkipping", true);
//calls the movement function with the direction to move in
Movement(Input.GetAxis("Horizontal"));
}
else if (0 < Input.GetAxis("Horizontal"))
{
//This is to flip image
transform.eulerAngles = new Vector3(0, 0, 0);
//starts animation
animator.SetBool("isSkipping", true);
//calls the movement function with the direction to move in
Movement(Input.GetAxis("Horizontal"));
}
}
I'm happy to try any alternatives to delaying movement of the character. The animation shows the character charging up to jump and then jumps. I want to only move while it is in the air which is approximately half a second into the animation.
You are trying to call your IEnumerator like a method.
Instead you have to start it as a Coroutine using StartCoroutine
StartCoroutine(Movement(Input.GetAxis("Horizontal")));
Saw your edit
I want to be able to hold down the right arrow key, have the character not move for 415ms, then be able to move for 580ms, after which he cannot move for 350ms (to let the animation finish playing)
until now so since you want a continues movement but still fully control the speed I would keep it in Update and use the coroutine only for controlling a flag. Coroutine is still way better to read/write and maintain. (Now it also allows direction switch midair .. not sure if you want this or not):
// control the ability to move with a simple flag
// instead of various states
public bool canMove;
// check if a jumping is already being animated/executed
// -> disallow a new jumping animation until it is finished
private bool canJump = true;
private void Update()
{
// avoid repeated API calls
var input = Input.GetAxis("Horizontal");
if (input < 0)
{
//This is to flip image
transform.eulerAngles = new Vector3(0, 180, 0);
if(canJump)
{
//starts the movement
StartCoroutine(Jump());
}
}
else if (input > 0)
{
//This is to flip image
transform.eulerAngles = new Vector3(0, 0, 0);
if(canJump)
{
//starts the movement
StartCoroutine(Jump());
}
}
// if can not move do nothing else
if(!canMove) return;
// execute the movement
transform.position += Vector3.right * input * speed * Time.deltaTime;
}
private IEnumerator Jump()
{
// disable jumping
canJump = false;
// disable move during animation
canMove = false;
//starts animation
animator.SetBool("isSkipping", true);
// not move for 415ms
yield return new WaitForSeconds(0.415f);
// enable move
canMove = true;
// be able to move for 580ms
yield return new WaitForSeconds(0.580f);
// disable move
canMove = false;
// cannot move for 350ms during end of animation
yield return new WaitForSeconds(0.350f);
// enable move again
canMove = true;
// re-enable jumping
canJump = true;
}
How about using timer in Update?
float timer = 0f;
void Update()
{
var dir = Input.GetAxis("Horizontal");
if (0 > dir)
{
//This is to flip image
transform.eulerAngles = new Vector3(0, 180, 0);
//starts animation
animator.SetBool("isSkipping", true);
//calls the movement function with the direction to move in
timer +=Time.deltaTime;
if(timer >= 0.5){
ExecuteMovement(dir);
timer -=0.5f;
}
//Movement(Input.GetAxis("Horizontal"));
}
else if (0 < dir)
{
//This is to flip image
transform.eulerAngles = new Vector3(0, 0, 0);
//starts animation
animator.SetBool("isSkipping", true);
//calls the movement function with the direction to move in
timer +=Time.deltaTime;
if(timer >= 0.5){
ExecuteMovement(dir);
timer -=0.5f;
}
//Movement(Input.GetAxis("Horizontal"));
}
}
I found a rather crude way of making this work after heavily modifying Gray_Rhino's answer to this question. I set up 3 stages of my jump animation, when continually moving one direction a timer will check to see how far into the animation it is and decide whether or not to allow movement input. the timer resets after the animation is finished or the character is told to move in the other direction.
bool facingRight;
int jumpPhase = 1;
float timer = 0f;
float dir;
void Update()
{
if (jumpPhase != 3)
{
dir = Input.GetAxis("Horizontal");
}
if (0 > dir || (jumpPhase == 3 && facingRight == true))
{
timer += Time.deltaTime;
if (facingRight != true)
{
transform.eulerAngles = new Vector3(0, 180, 0);
jumpPhase = 1;
timer = 0f;
facingRight = true;
}
else if (jumpPhase == 1)
{
//starts animation
animator.SetBool("isSkipping", true);
if (timer >= 0.415f)
{
jumpPhase = 2;
}
}
else if (jumpPhase == 2)
{
ExecuteMovement(dir);
if (timer >= 0.995f)
{
jumpPhase = 3;
}
}
if (jumpPhase == 3)
{
if (timer >= 1.5f)
{
jumpPhase = 1;
timer = 0f;
}
}
}
else if (0 < dir || (jumpPhase == 3 && facingRight != true))
{
timer += Time.deltaTime;
if (facingRight == true)
{
transform.eulerAngles = new Vector3(0, 0, 0);
jumpPhase = 1;
timer = 0f;
facingRight = false;
}
else if (jumpPhase == 1)
{
//starts animation
animator.SetBool("isSkipping", true);
if (timer >= 0.415f)
{
jumpPhase = 2;
}
}
else if (jumpPhase == 2)
{
ExecuteMovement(dir);
if (timer >= 0.995f)
{
jumpPhase = 3;
}
}
if (jumpPhase == 3)
{
if (timer >= 1.5f)
{
jumpPhase = 1;
timer = 0f;
}
}
}
}
I am looking for a help with make a delay in Unity in Update function.
I created something like this below. The cube is moving rotates once and then is waiting > rotates once > waiting ....
And there is my question. How i can make cube rotates constantly for some time instead of once. For Example: Wait 2sec, rotating constantly 5sec, Wait 2sec, rota....
I thinked about replace
ForCube.transform.Rotate (10, 10, 10);
by rotating Animation. But I want create it with transform.Rotate. Is there any option to do this?
using UnityEngine;
using System.Collections;
public class Ruch : MonoBehaviour
{
public float speed = 5;
public GameObject ForCube;
bool work = true;
// Use this for initializat
void Start ()
{
ForCube = GameObject.Find ("Cube");
Debug.Log (ForCube);
}
// Update is called once per frame
void Update ()
{
if (work) {
StartCoroutine (WaitSome ());
}
}
private IEnumerator WaitSome ()
{
work = false;
yield return new WaitForSeconds (3f);
ForCube.transform.Rotate (10, 10, 10);
work = true;
}
}
At the moment it looks like to me you are using a StartCoroutine which will work fine, but if you want maybe a little more control over when to rotate and when to stop you can use the Time.deltaTime The time in seconds it took to complete the last frame (Read Only).http://docs.unity3d.com/ScriptReference/Time-deltaTime.html
So basically you have yourself a float variable called Rotate which is lets say 10f
Then inside of your Update function
void Update ()
{
if(Rotate > 0)
{
Rotate -= Time.deltaTime;
ForCube.transform.Rotate (10, 10, 10);
}
}
Then when Rotate is equal to 0 it will stop, but then you can use your work bool to start a new timer.
One big think to take in is to use the Time.deltaTime, if you don't use this and you just use an int or whatever variable type the timer will differ depending on the FPS of the game for the player.
Let me know if you need anymore help :)
Instead of using coroutines, you can do it directly in the update function like this:
[SerializeField]
private float timeToWait; //In seconds
[SerializeField]
private float timeToRotate; //In seconds
private float timer = 0;
private bool waiting = true; //Set this to false if you want to rotate first, wait later
void Update()
{
if(!waiting) RotateYourObjectALittleBit(); //Call your own function or do whatever you want
timer += Time.deltaTime;
if(timer >= timeToWait && waiting) {
waiting = false;
timer = 0;
}
else if(timer >= timeToRotate && !waiting) {
waiting = true;
timer = 0;
}
}
This code is untested, so please let me know if you require further clarification or if it doesn't work.
Thanks everyone for fast Answer and help to solve my problem. I really appreciate that.
I created something like this:
Version 1.0
When the space key is down the cube start rotating for RotateTime, after this the Timer reset to start value(RotationTime), and u can click again button for rotate.
using UnityEngine;
using System.Collections;
public class Ruch : MonoBehaviour
{
public GameObject ForCube;
public float RotateTime = 5;
public float Timer = 0;
private bool Rotate = false;
// Use this for initializat
void Start ()
{
Timer = RotateTime;
ForCube = GameObject.Find ("Cube");
Debug.Log (ForCube);
}
// Update is called once per frame
void Update ()
{
//Start Rotating When Press Space Key
if (Input.GetKeyDown (KeyCode.Space)) Rotate = true;
else if (!(Input.GetKeyDown (KeyCode.Space))&&Timer <=0) Rotate = false;
RotateForSec (ref Timer);
}
//Function to Rotate for X sec
void RotateForSec(ref float sec)
{
if (Rotate && sec > 0) {
Debug.Log (Time.time);
ForCube.transform.Rotate (10, 10, 10);
sec -= Time.deltaTime;
}
//Reset Rotating Time after rotating
if (!Rotate && sec <= 0) Timer = RotateTime;
}
}
Version 2.0
The rotating of cube continues for 5 seconds and then automatically without pressing a key it wait some time and start over rotating. Again again and again ...
public GameObject ForCube;
public float RotateTime = 5;
public float Timer = 0;
public float PauseTime = 0;
private bool Pause = false;
private bool Rotate = true;
// Use this for initializat
void Start ()
{
Timer = RotateTime;
PauseTime = RotateTime;
ForCube = GameObject.Find ("Cube");
Debug.Log (ForCube);
}
// Update is called once per frame
void Update ()
{
//Start Rotating When Press Space Key
if (Rotate)
Pause = false;
else if (!Rotate) {
Pause = true;
}
if (!Pause)
RotateForSec (ref Timer);
else RotatePause ();
}
//Function to pause PauseTime sec
void RotatePause()
{
if (PauseTime > 0) {
PauseTime -= Time.deltaTime;
} else {
Pause = false;
Rotate = true;
PauseTime = RotateTime;
}
}
//Function to Rotate for X sec
void RotateForSec(ref float sec)
{
if (Rotate && sec > 0) {
Debug.Log (Time.time);
ForCube.transform.Rotate (10, 10, 10);
sec -= Time.deltaTime;
} else Rotate = false;
//Reset Rotating Time after rotating
if (!Rotate && sec <= 0) Timer = RotateTime;
}
}
Its working but what you think about that, is it done correctly or it is a bad way?