I am having a problem with my game. I have a script ( that is listed below ) that is supposed to show a text for some time and then make it disappear. This script is being done through a game object with a trigger collider. This script is working fine with the first game object, but then it is not working for the next game instance where I've used it ( as seen in the video listed below ). May anybody tell me what's wrong in this instance and help me to fix this? Thank you!
Video link:https://streamable.com/zwjism
Script used for the first text trigger ( the attack text ):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class CollisionText : MonoBehaviour
{
public TextMeshProUGUI enemyWarning;
public float duration = 4f;
[SerializeField] private Animator anim;
void Start()
{
enemyWarning.enabled = false;
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
StartCoroutine ( showText(other) );
}
}
IEnumerator showText(Collider2D player)
{
enemyWarning.enabled = true; // displays text
attackDemonstration();
yield return new WaitForSeconds(duration); // waits an amount of time x
enemyWarning.enabled = false; // makes the text invisible
Destroy(gameObject); // destroys the trigger after the x amount of time
}
void attackDemonstration()
{
for(int i=1; i<=3; i++)
{
anim.SetTrigger("Attack");
}
}
}
Script used for the second text trigger that doesn't disappear ( the test text ):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class test : MonoBehaviour
{
public TextMeshProUGUI enemyWarning;
public float duration = 4f;
[SerializeField] private Animator anim;
void Start()
{
enemyWarning.enabled = false;
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
StartCoroutine(showText(other));
}
}
IEnumerator showText(Collider2D player)
{
enemyWarning.enabled = true; // displays text
yield return new WaitForSeconds(duration); // waits an amount of time x
enemyWarning.enabled = false; // makes the text invisible
Destroy(gameObject); // destroys the trigger after the x amount of time
}
}
Try activating before calling the StartCoroutine function. Sometimes we cannot make changes in IEnumerator due to some situations that I do not know the reason of. Maybe there is someone who knows better.
or
If you do something like this while you are defining it, you can try it too.
tmpScore = gameObject.AddComponent <TextMeshPro> ();
I hope it helps.
or
The duration value sounds too low and may change quickly. You can try printing something to the console with the debug.log command.
Related
VIDEO < when ever I click my replay button and when the transition is about to start it loads the game before the transition even ends you can see the game being loaded and causes this snappy effect that I'm not sure why is there anyway i could fix this?
my code even though I have a yield that waits for the aimation to finish it doesn't wait at all it only delays when the animation will show and plays the game.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
using UnityEngine.SceneManagement;
public class replayscript : MonoBehaviour
{
GameObject replaybutton;
public Animator transitionERR;
public float transitiontime = 19f;
GameObject replay;
public float timeRR = 0f;
// Start is called before the first frame update
// Update is called once per frame
void Start()
{
replay.SetActive(false);
}
void Update()
{
if (CrossPlatformInputManager.GetButton("replaybutton")){
Debug.Log("candice");
StartCoroutine(LoadLevel(1));
replay.SetActive(true);
}
}
IEnumerator LoadLevel(int levelIndex)
{
//play animation
transitionERR.SetTrigger("start");
//wait for the animaton
yield return new WaitForSeconds(1.5f);
//load the scene
SceneManager.LoadScene(1);
}
}
You could try adding the transitionERR.SetTrigger("start"); before using the StartCoroutine(LoadLevel(1));
You could make an event for the animation end and then put your load scene code in there.
Something like:
//
public UnityAnimationEvent OnAnimationComplete;
public AnimationClip clip;
//
AnimationEvent animationEndEvent = new AnimationEvent();
animationEndEvent.time = clip.length;
animationEndEvent.functionName = "AnimationCompleteHandler";
animationEndEvent.stringParameter = clip.name;
clip.AddEvent(animationEndEvent);
//
public void AnimationCompleteHandler(string name)
{
OnAnimationComplete?.Invoke(ChangeSceneMethodName);
}
Also if you plan on using a coroutine to get a animation duration you could use WaitForSeconds(anim.GetCurrentAnimatorStateInfo(0).length+anim.GetCurrentAnimatorStateInfo(0).normalizedTime);
this should be a very simple answer. I'm following a Unity with C# tutorial for making a simple Space Invaders game, and at one point it is shown that when our enemyHolder object has no child objects left (when all enemies are destroyed) the attached text under the winText function should be displayed.
So we have
if (enemyHolder.childCount == 0)
{
winText.enabled = true;
}
When I run the code the text isn't displayed after the enemies are destroyed and no child object is left. It's like the code stops getting read at that point, although the character is still movable and you can generate new shots.
If I create two "Enemy" child objects and tell it to display the winText rather when the childCount reaches 1, it does work.
So why is it not working when the function calls for == 0?
EDIT: Complete class code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyController : MonoBehaviour
{
private Transform enemyHolder;
public float speed;
public GameObject shot;
public Text winText;
public float fireRate = 0.997f;
// Start is called before the first frame update
void Start()
{
winText.enabled = false;
InvokeRepeating("MoveEnemy", 0.1f, 0.3f);
enemyHolder = GetComponent<Transform>();
}
void MoveEnemy()
{
enemyHolder.position += Vector3.right * speed;
foreach (Transform enemy in enemyHolder)
{
if (enemy.position.x < -10.5 || enemy.position.x > 10.5)
{
speed = -speed;
enemyHolder.position += Vector3.down * 0.5f;
return;
}
if (enemy.position.y <= -4)
{
GameOver.isPlayerDead = true;
Time.timeScale = 0;
}
if (enemyHolder.childCount == 1)
{
CancelInvoke();
InvokeRepeating("MoveEnemy", 0.1f, 0.25f);
}
if (enemyHolder.childCount == 0)
{
winText.enabled = true;
}
}
}
}
Your code is inside the void MoveEnemy() function.
I'm assuming your script is attached to in-game enemies. Your code doesn't run because the MoveEnemy function no longer runs if there are no enemies.
So, you need to handle enemy movement and scene handling in different scripts.
The code that checks the enemy holder's number of children should be placed inside a void Update() function. This Update() function should be placed on an object that never gets deleted. Its advantage is that it runs every frame.
As a convention, devs generally use separate empty objects or even the camera to attach scripts which contain Update functions that handle the scene. Good luck!
Read more on Update
I'm making game with Unity and I'm using SceneManager.LoadScene for loading from main scene to play scene. Everything is fine, but it takes too long time. So, game move from main scene to play scene but there is a slider between two scenes.
This is my code:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Load : MonoBehaviour
{
public Slider LoadSlider;
public Text percentSlider;
void Start ()
{
InvokeRepeating ("AdLoadPercent", 0.01f, 0.4f);
}
public void AdLoadPercent()
{
LoadSlider.value += Random.Range(0.6f,0.9f);
percentSlider.text=Mathf.RoundToInt(LoadSlider.value*100).ToString() + " %";
if (LoadSlider.value >= 1f)
{
SceneManager.LoadScene ("Scena1");
}
}
}
Why it take so long when my slider is equal 1?
" long " means that I have to wait more than 15 seconds.
Thanks and kind regards
Is it the same without using the slider?
I haven't used InvokeRepeating, never even heard about it in fact, so there's a chance that there's something going on with this function.
Place LoadScene() line in the Start() function and see if this helps. If it switches scenes instantly (or almost, like in < 1.25s) it's a problem with your repeating function. For things like that I recommend using an Update() function or an IENumerator
Example #1:
bool loadingStarted = false;
void Start()
{
loadingStarted = true;
}
void Update()
{
if(loadingStarted)
{
progressbar.value += Time.deltaTime*0.25f;
//.. and so on ...
}
}
Example #2:
void Start()
{
StartCoroutine(Countdown());
}
IENumerator Countdown()
{
while(progressBar.value < 1f)
{
//Do your incrementation here...
if(progressBar.value >= 1f) break;
return yield new WaitForEndOfFrame(); //or WaitForSeconds(0.05);
}
}
I am really new to programming and super new using unity xD I am trying to make a little game myself (2D). I need some help configuring the particle system.
using UnityEngine;
using System.Collections;
public class CharacterController : MonoBehaviour {
public float charForce = 75.0f;
public float fwMvSp = 3.0f;
void FixedUpdate ()
{
bool engineActive = Input.GetButton("Fire1");
if (engineActive)
{
rigidbody2D.AddForce(new Vector2(0, charForce));
}
Vector2 newVelocity = rigidbody2D.velocity;
newVelocity.x = fwMvSp;
rigidbody2D.velocity = newVelocity;
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
The problem is that i don't know how to implement a code to stop the particle emission if the button is not pressed. I tried with an if statement but i get an error tolding me to check if the particle system is attached to the gameobject. Thanks for help in advance :)
Instead of Input.getButton, use Input.getButtonDown, this will check to see if the button is pressed.
Then change your if statement to the following:
if (engineActive)
{
rigidbody2D.AddForce(new Vector2(0, charForce));
} else {
//run code here for when button is not pressed.
}
I'm having a bit of trouble getting the Vector3 wayPointPosition to my other script called Walking and changing it into the Transform target. My troubles lie in the fact that I'm trying to grab this dynamic variable from WayPointPositioner (it changes depending on what object is clicked in the stage and whether the player overlaps with this waypoint) and import and use it in another script.
Below is the code I'm using.
WayPointPositioner
using UnityEngine;
using System.Collections;
public class WayPointPositioner : MonoBehaviour {
public Vector3 wayPointPosition = Vector3.zero;
private bool checkPlayerWaypointCollision;
void Start()
{
}
void OnTriggerStay2D (Collider2D other)
{
// Check if collision is occuring with player character.
if (other.gameObject.name == "Player")
{
checkPlayerWaypointCollision = true;
}
else
{
checkPlayerWaypointCollision = false;
}
}
//Check if object is clicked
void OnMouseDown ()
{
// If its the player, then return a new position for the player to move to for walking
// Else debug that its not so
if (checkPlayerWaypointCollision == false)
{
Debug.Log ("Object not colliding and retrieving position");
Debug.Log (wayPointPosition);
Debug.Log (gameObject.name);
wayPointPosition = new Vector3 (transform.position.x, transform.position.y, 10);
wayPointPosition = Camera.main.ScreenToWorldPoint(wayPointPosition);
}
else
{
Debug.Log ("Object is colliding, no movement needed");
}
}
}
Walking
using UnityEngine;
using System.Collections;
public class Walking : MonoBehaviour {
public Transform target;
public WayPointPositioner wayPointPosition;
public bool walkingAnimation = false;
private Animator anim;
void Awake ()
{
anim = GetComponent<Animator> ();
wayPointPosition = GameObject.FindGameObjectWithTag ("Waypoint").GetComponent<WayPointPositioner> ();
}
void Start ()
{
}
void Update ()
{
Debug.Log ("This is in Walking, WPP =" + wayPointPosition);
}
}
As you can see I'm trying to import the wayPointPosition from the seperate class which is attached to the gameobjects called "Waypoint" (In my current layout those are empty objects with circle colliders to check if they have been clicked). However when I run this, I am not getting my Vector, but I'm getting the name of the last waypoint in the hierarchy (I have currently 6 waypoints which can be clicked) and not a Vector.
I hope someone is able to help me / point out my mistake. I'm still learning C# so I might've made a strange / odd assumption which isn't working.
Kind regards,
Veraduxxz.
It looks like invoking GameObject.FindGameObjectWithTag("Waypoint").GetComponent<WayPointPositioner>(); retrieves a component from the game object which matches the specified tag, as well as a type argument T which derives from MonoBehavior.
Calling this should actually give you an instance of your WayPointPositioner class, which you can then pass to whichever methods you want, and interact with its Vector3 however you would like.