I'm working on a laser that fires for a set amount of time before switching off.
I am using WaitForSeconds calling the fire function, waiting for x seconds and then turning it off.
I can see it working by turning the colliders and sprites on and off in the Unity menus, but they never physically appear in the game; whereas without the code they do appear.
void Start()
{
StartCoroutine(LaserTimer());
}
void LaserFire()
{
beamCollider.enabled = true;
beamSprite.enabled = true;
}
void StopFire()
{
beamCollider.enabled = false;
beamSprite.enabled = false;
}
IEnumerator LaserTimer()
{
LaserFire();
yield return new WaitForSeconds(5);
StopFire();
yield return new WaitForSeconds(5);
}
Related
I have two different timed Power-Ups in my project, both with 5 seconds duration. I'd like to make that if I pick a Power Up before the time ends, It makes the timer counts again from zero, but it is not happening. If I pick up the same Power UP while remaining 1 second, it lasts just for one second instead of 5. I'm using in the Player Script a public void that is called out by the Power UP when it is picked up
My Player's code:
public void TripleShotActive()
{
_canTripleShot = true;
StopCoroutine(TripleShotPowerDownRoutine());
StartCoroutine(TripleShotPowerDownRoutine());
return;
}
public void SpeedBoostPowerupActive()
{
_speedBoostActive = true;
StopCoroutine(SpeedBoostPowerDownRoutine());
StartCoroutine(SpeedBoostPowerDownRoutine());
return;
}
public void ShieldsActive()
{
_isShieldsActive = true;
_shieldVisualizer.SetActive(true);
}
IEnumerator TripleShotPowerDownRoutine()
{
yield return new WaitForSeconds(5.0f);
_canTripleShot = false;
}
IEnumerator SpeedBoostPowerDownRoutine()
{
yield return new WaitForSeconds(5.0f);
_speedBoostActive = false;
}
I tried using StopCoroutine before StartCoroutine, but it didn't work
You need to stop the coroutine earlier created by StartCoroutine.
Coroutine _tripleShotPowerDown;
public void TripleShotActive()
{
_canTripleShot = true;
if(_tripleShotPowerDown != null)
StopCoroutine(_tripleShotPowerDown);
_tripleShotPowerDown = StartCoroutine(TripleShotPowerDownRoutine());
return;
}
I am calling ChangeVideo() from an invoke method:
InvokeRepeating ("ChangeVideo", 1, TimeToChangeImage);
public void ChangeVideo()
{
public string[] VedioPaths ={"aa","bb"}
System.Random random1 = new System.Random();
PathNO1 = random1.Next (VedioPaths.Length);
ConfirmPath1 = VedioPaths[PathNO1];
Handheld.PlayFullScreenMovie (ConfirmPath1,Color.black,FullScreenMovieControlMode.CancelOnInput);
}
I need to play the next video soon after the other finishes. How can I do that? I tried many ways but every time I build I get an error.
I have a string array from which I randomly select a video; once the first video finishes the next one should start playing. I tried using the invoke method but it is giving me an error.
If you want to load videos in a coroutine:
void Start()
{
StartCoroutine(LoadVideos());
}
IEnumerator LoadVideos()
{
//first vid
Handheld.PlayFullScreenMovie("vid1.mp4", Color.black, FullScreenMovieControlMode.CancelOnInput);
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
//second vid
Handheld.PlayFullScreenMovie("vid2.mp4", Color.black, FullScreenMovieControlMode.CancelOnInput);
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
}
Note that two lines of yield return new WaitForEndOfFrame(); is absolutely required for this method to work. The reason is unknown to me but it won't work otherwise.
Take a look closer to the documentation : https://docs.unity3d.com/ScriptReference/Handheld.PlayFullScreenMovie.html
Calling this function will pause Unity during movie playback. When playback finishes Unity will resume
Meaning that, if you want to play 2 videos one after the other, you just have to do :
Handheld.PlayFullScreenMovie (path1,Color.black,FullScreenMovieControlMode.CancelOnInput);
Handheld.PlayFullScreenMovie (path2,Color.black,FullScreenMovieControlMode.CancelOnInput);
Waiting between the two calls may be required though.
There is a very easy way for the lastest VideoPlayer to detect the loop point even if it‘s not looping.
public VideoPlayer videoPlayer;
public VideoClip[] videos;
public VideoClip theVideo;
public static int index;
bool isPlaying = true;
void Start()
{
index = 0;
videoPlayer = gameObject.GetComponent<VideoPlayer>();
videoPlayer.loopPointReached += CheckOver;
}
void CheckOver(UnityEngine.Video.VideoPlayer vp)
{
print("Video Is Over");
index += 1;
if (index >= videos.Length)
{
index = 0;
}
theVideo = videos[index];
videoPlayer.clip = theVideo;
videoPlayer.Play();
isPlaying = true;
}
I have some code that when it executes, it pushes a character forward. The issue is that the character never stops moving and continues forever. Is there a way to stop the character from moving after 2 seconds? Here is the code I'm using:
public class meleeAttack : MonoBehaviour
{
public int speed = 500;
Collider storedOther;
bool isHit = false;
void Start()
{
}
void Update()
{
if (isHit == true )
{
storedOther.GetComponent<Rigidbody>().AddForce(transform.forward * speed);
}
}
void OnTriggerStay(Collider other)
{
if (other.gameObject.tag == "Player" && Input.GetKeyUp(KeyCode.F))
{
storedOther = other;
isHit = true;
}
}
}
I'm not sure if there's a way to stop the update() function so it stops the character movement.
The Update function is part of the life cycle of a Unity script. If you want to stop the Update function to be executed, you need to deactivate the script. For this, you can simply use:
enabled = false;
This will deactivate the execution of the life cycle of your script, and so prevent the Update function to be called.
Now, it looks like you are applying a force to your character to make it move. What you might want to do then is, after two seconds, remove any force present on your character. For that, you can use a coroutine, which is a function that will not just be executed on one frame, but on several frames if needed. For that, you create a function which returns an IEnumerator parameter, and you call the coroutine with the StartCoroutine method:
bool forcedApplied = false;
void Update()
{
if (isHit == true && forceApplied == false)
{
storedOther.GetComponent<Rigidbody>().AddForce(transform.forward * speed);
forceApplied = true;
StartCoroutine(StopCharacter);
isHit = false;
}
}
IEnumerator StopCharacter()
{
yield return new WaitForSeconds(2);
storedOther.GetComponent<Rigidbody>().velocity = Vector3.zero;
forceApplied = false;
}
Those might be different ways to achieve what you want to do. It's up to you to choose what seems relevant to your current gameplay and to modify your script this way.
this is my code
void Start () {
GetComponent<SpriteRenderer>().enabled = false;
animator = transform.GetComponentInChildren<Animator>();
if (animator == null) {
Debug.LogError("Didn't find animator");
}
}
}
GetComponent<Rigidbody2D>().AddForce(Vector2.right * forwardSpeed);
if (didFlap) {
GetComponent<Rigidbody2D>().AddForce (Vector2.up * flapSpeed);
animator.SetTrigger("Doflap");
didFlap = false;
time = 0;
}
// Do graphics & input update
void Update(){
if(Input.GetKeyDown(KeyCode.Space) || (Input.GetMouseButtonDown(0))){
didFlap=true;
}
}
public void TakeDamage(float tim) {
Application.LoadLevel(Application.loadedLevel);
}
// Do physics engine update
void FixedUpdate () {
if (dead) {
Time.timeScale = 0;
GetComponent<SpriteRenderer>().enabled = true;
if(Time.timeScale == 0 && (Input.GetKeyDown (KeyCode.Space) || Input.GetMouseButtonDown (0))){
Application.LoadLevel(Application.loadedLevel);
here when i give the line(Application.LoadLevel(Application.loadedLevel);) with out if the game restarts.but when i give inside the if its not working..on the game dead i set the Time.timeScale to 0,and a restart button appears on the screen.on a touch again i need to restart.but when i gave the code for restart inside the if its not working,when i give it with out if the game suddenly restarts after dead with out giving a space to click the restart button.
i need to restart on the button click
}
}
void OnCollisionEnter2D(Collision2D collision){
animator.SetTrigger("Death");
dead = true;
}
}
When you set the TimeScale to 0, your Inputs will also stop working as they are dependant on the actual Time ;-) You could however still use the Input.GetAxisRaw to achieve similar goal. As it is not depending on the TimeScale.
But a better solution is to just add a UI Button that are available in unity 4.6+, using their new built in UI.
is there a simple UnityScript code to hide and unhide a cube
or any other gameobjects for a particular time ?
//make the object invisible
renderer.enabled = false;
// make the object visible
renderer.enabled = true;
// toggle object's visibility each second
function Update () {
// Find out whether current second is odd or even
var seconds : int = Time.time;
// Enable renderer accordingly
renderer.enabled = oddeven;
To show/hide a game object, rather than using render.enabled property, you should use
// Deactivates the game object.
gameObject.SetActive (false);
More details can be found here.
To call this function periodically, as theodox said, startCoroutine is your friend.
You want to hide the object, fire off a coroutine that waits for N seconds, and then unhide.
This is C#, the conversion to Javascript should be simple but I don't think JS uses startCoroutine (This page in the docs explains the difference between the C# and Javascript versions).
public bool Hide = false;
void Update()
{
if (Hide && renderer.enabled) {
renderer.enabled = false;
Hide = false;
StartCoroutine("WaitUnhide");
}
}
IEnumerator WaitUnhide()
{
yield return (new WaitForSeconds(2));
renderer.enabled = true;
}
In this version you would set the 'hide' variable from some other code to start the hiding. Hide && renderer.enabled means you can't kick off a new hide until the old one completes - that's not the only way to do it but it avoids having multiple hide/unhides overlapping.
To make it loop forever:
void Start()
{
StartCoroutine("HideUnhide");
}
IEnumerator HideUnhide()
{
while (true) {
yield return (new WaitForSeconds(2));
renderer.enabled = true;
yield return (new WaitForSeconds(2));
renderer.enabled = false;
}
}