I'm creating a 2D in in Unity and I have a loading screen, that it's working (the loading animation). What I want to do next is to make the next screen appear (it's a gameobject), after a certain time.
Right now, my code is:
public RectTransform mainIcon;
public float timeStep;
public float oneStepAngle;
float startTime;
// Start is called before the first frame update
void Start()
{
startTime = Time.time;
}
// Update is called once per frame
void Update()
{
if (Time.time - startTime >= timeStep) {
Vector3 iconAngle = mainIcon.localEulerAngles;
iconAngle.z += oneStepAngle;
mainIcon.localEulerAngles = iconAngle;
startTime = Time.time;
}
}
what should I do now? Thank you
go to your game object that plays animation > create new script and ignore on start & update > Add this code
// object that would appear after animaton
public GameObject obj;
void showGameObject(){
objSetActive(true);
}
go back to your object that plays animation then add game object that will appear > go to animation controller on same object > select animation that our object will appear after > add animation event > in inspector you should have this > select function showGameObject
You could use a simple timer like e.g.
public RectTransform mainIcon;
public float anglePerSecond = 90f;
public float duration;
public string nextScene;
private float timer;
// Update is called once per frame
void Update()
{
mainIcon.Rotate(Vector3.forward * anglePerSecond * Time.deltaTime);
timer += Time.deltaTime;
if(timer >= duration)
{
SceneManager.LoadScene(nextScene);
}
}
Related
My coroutine is only firing once for the first rendered red cube. The other ones in my beat map get rendered but do not move to the desired position of (5,5). Am i missing something? Thanks in advance!
I tried adding a while loop, but that did not seem to fix the problem.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class BeatMapConductor : MonoBehaviour
{
private CSVReader beatmap;
private MusicConductor music;
private Vector3 redEndPosition = new Vector2(5,5);
private Vector3 redStartPosition;
private float desirecDuration = 5f;
private float elapsedTime;
private int i;
private Queue<UnityEngine.GameObject> queue;
private UnityEngine.GameObject[] array;
// initializes variables before game starts
void Awake()
{
beatmap = GetComponent<CSVReader>();
music = GetComponent<MusicConductor>();
}
// Start is called before the first frame update
void Start()
{
i = 0;
}
// Update is called once per frame
void Update()
{
int roundedBeat = (int)Math.Round(music.songPositionInBeats, 0);
if(i < beatmap.myPlayerList.player.Length && roundedBeat == beatmap.myPlayerList.player[i].beat){
//rendering a new cube
// Create a new cube primitive to set the color on
GameObject redCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
// Get the Renderer component from the new cube
var cubeRenderer = redCube.GetComponent<Renderer>();
// Call SetColor using the shader property name "_Color" and setting the color to red
cubeRenderer.material.SetColor("_Color", Color.red);
i++;
StartCoroutine(Movement(redCube));
}
}
IEnumerator Movement(GameObject cube){
// to move the game object
redStartPosition = cube.transform.position;
while(elapsedTime < desirecDuration){
elapsedTime += Time.deltaTime;
float percentageComplete = elapsedTime / desirecDuration;
cube.transform.position = Vector2.Lerp(redStartPosition, redEndPosition, percentageComplete);
}
yield return null;
}
}
When you run Movement for the first time, it will increase elapsedTime to at least 5. When you now run Movement a second time, elapsedTime is still at least 5 thus while (elapsedTime < desirecDuration) will evaluate to false and your second cube will not be moved. You should make elapsedTime a local variable of the coroutine (and redStartPosition too).
Also, you should place yield return null; at the end within the while loop to have the cube moving on a frame basis. The way you have written it the loop will bump elapsedTime to 5 immediately in one frame.
IEnumerator Movement(GameObject cube) {
float elapsedTime = 0f; // make it local for every coroutine instance
// to move the game object
Vector3 redStartPosition = cube.transform.position;
while (elapsedTime < desirecDuration) {
elapsedTime += Time.deltaTime;
float percentageComplete = elapsedTime / desirecDuration;
cube.transform.position = Vector2.Lerp(redStartPosition, redEndPosition, percentageComplete);
yield return null; // on loop run per frame
}
}
In my most recent code update the sprite doesn't want to show anymore before I could pull the prefab into the hierarchy and it would show and it will still do that. But whenever I spawn it in with code the image doesn't show. The update I did spawns the sprites and then moves them down a path. I can see the sprite move in the inspector but can't see it on screen.
MoveEnemy script
public class MoveEnemy : MonoBehaviour
{
[HideInInspector]
public GameObject[] waypoints;
private int currentWaypoint = 0;
private float lastWaypointSwitchTime;
public float speed = 1.0f;
// Start is called before the first frame update
void Start()
{
lastWaypointSwitchTime = Time.time;
}
// Update is called once per frame
void Update()
{
// 1
Vector3 startPosition = waypoints
[currentWaypoint].transform.position;
Vector3 endPosition = waypoints[currentWaypoint + 1].transform.position;
// 2
float pathLength = Vector3.Distance(startPosition, endPosition);
float totalTimeForPath = pathLength / speed;
float currentTimeOnPath = Time.time - lastWaypointSwitchTime;
gameObject.transform.position = Vector2.Lerp(startPosition, endPosition, currentTimeOnPath / totalTimeForPath);
// 3
if (gameObject.transform.position.Equals(endPosition))
{
if (currentWaypoint < waypoints.Length - 2)
{
// 3.a
currentWaypoint++;
lastWaypointSwitchTime = Time.time;
// TODO: Rotate into move direction
}
else
{
// 3.b
Destroy(gameObject);
AudioSource audioSource = gameObject.GetComponent<AudioSource>();
AudioSource.PlayClipAtPoint(audioSource.clip, transform.position);
// TODO: deduct health
}
}
}
}
// Credit raywenderlich.com
SpawnEnemy script
public class SpawnEnemy : MonoBehaviour
{
public GameObject[] waypoints;
public GameObject testEnemyPrefab;
// Start is called before the first frame update
void Start()
{
Instantiate(testEnemyPrefab).GetComponent<MoveEnemy>().waypoints = waypoints;
}
Whenever I changed the camera render mode the screen space moved but the sprite didn't so I just had to move it back into the screen space.
I think objects spawning behind the camera. Move the camera a bit back. Set the view to 3d world space. Then move the camera along z axis. Or change the spawnpoint's z axis.
I've searched around and couldn't quite find the answer. I have two scenes, one with a play button which starts the next scene (the game) and the other scene is the game. Which has a spawner script which spawns random patterns of obsticles. Which can be seen here.
public class Spawner : MonoBehaviour {
public GameObject[] obstaclePatterns;
private float timeBtwSpawn;
public float startTimeBtwSpawn;
public float decreaseTime;
public float minTime = 0.55f;
private void Update()
{
if (timeBtwSpawn <= 0)
{
int rand = Random.Range(0, obstaclePatterns.Length);
Instantiate(obstaclePatterns[rand], transform.position, Quaternion.identity);
timeBtwSpawn = startTimeBtwSpawn;
if (startTimeBtwSpawn > minTime) {
startTimeBtwSpawn -= decreaseTime;
}
}
else {
timeBtwSpawn -= Time.deltaTime;
}
}}
I would like to after the play button is pressed and the game is started there be a delay for 1 second before the spawner begins spawning. I'm not sure how to do that. Any help would be appreciated.
You can use Unity's Start function as a coroutine directly.
private bool _canStart;
private IEnumerator Start()
{
yield return new WaitForSeconds(whatyouwant);
_canStart = true;
}
private void Update()
{
if(!_canStart) return;
whatyouwant
}
if you want to have a routine that starts after a specific amount of time since the scene was loaded you can use Time.timeSinceLevelLoad this variable holds the time in seconds since the last level(scene) was loaded
So you can either create a script that activates your spawner script or add an additional check to your spawner script
You should set timeBtwSpawn before start updating of Spawner:
timeBtwSpawn = 1; // seconds
So i have a button that is suppose to change a colour of an object. Im using color.lerp but i need it to gradually change. like slowly. what i have now:
public Renderer engineBodyRenderer;
public float speed;
public Color startColor, endColor;
float startTime;
// Start is called before the first frame update
void Start()
{
startTime = Time.time;
ChangeEngineColour();
}
public void ChangeEngineColour()
{
float t = (Time.time - startTime) * speed;
engineBodyRenderer.material.color = Color.Lerp(startColor, endColor, t);
}
so the color of the object does change just not slowly. what am i missing?
In your solution the method is only run ONCE, so only ONE color change can happen. Here's how I usually do it:
void Start()
{
// ... your other stuff
StartCoroutine(ChangeEngineColour());
}
private IEnumerator ChangeEngineColour()
{
float tick = 0f;
while (engineBodyRenderer.material.color != endColor)
{
tick += Time.deltaTime * speed;
engineBodyRenderer.material.color = Color.Lerp(startColor, endColor, tick);
yield return null;
}
}
By starting a Coroutine this code will run asyncronously beside the rest of the code and with yield return null it will loop in the same speed as your Update() functions, so essentially you've created an isolated Update() method, that run every frame and will gradually change the color every frame.
And to change back and forth between colors gradually, replace this line from Fredrick:
engineBodyRenderer.material.color = Color.Lerp(startColor, endColor, tick);
to this:
engineBodyRenderer.material.color = Color.Lerp(startColor, endColor, Mathf.PingPong(Time.time, 1));
So you will have:
I have an object in my game that is like a power object: when my player enters the power it should activate a panel that indicates that the power was grabbed, and past 3 seconds that panel should disappear. At the moment my panel appears when I hit the power, but it doesn't disappear. I am using a Coroutine like this:
using UnityEngine;
using System.Collections;
public class shrink : MonoBehaviour {
public float value = 0.1f; //1 by default in inspector
private bool colided = false;
private float speed;
Manager gameManager;
public GameObject panel;
// Update is called once per frame
void Start(){
speed = 3.4f;
gameManager = GameObject.Find ("GameController").GetComponent<Manager> ();
}
void OnTriggerEnter(Collider c)
{
if (c.gameObject.tag == "Player") {
colided = true;
gameManager.powerUp1 = true;
StartCoroutine(menuOp());
}
}
//This method is executed every frame
void Update(){
if (colided) {
Vector3 temp = transform.localScale;
//We change the values for this saved variable (not actual transform scale)
temp.x -= value * Time.time;
temp.y -= value * Time.time;
if (temp.x > 0) {
speed += 0.02f;
transform.Rotate (0f, 0f, Time.deltaTime * 90 * speed);
transform.localScale = temp;
} else {
Object.Destroy (this.gameObject);
}
}
}
IEnumerator menuOp(){
panel.SetActive (true);
yield return new WaitForSeconds (3f);
panel.SetActive (false);
}
}
Ps: what is inside the update is independent from what i need to do, so i think it doesn't interfer with my needs.
I think you might be destroying the GameObject before the WaitForSeconds(3f) has ended, which will prevent panel.SetActive(false) from executing.
In your Update-method's "else statement to if (temp.x > 0)" you're destroying the GameObject that tries to show/hide the panel.
If you absolutely need to Destroy this gameobject at that time you should break out your IEnumerator to another script and call it from this (shrink.cs) script.
Destroying the object before 3 seconds might be the issue. You can check by putting two logs:
1- After "Object.Destroy" line
2- After "WaitForSeconds"
maybe you should check if your gameobject(shrink's) is unactive or destroyed.
coroutine does not work with unactive gameobject.