I'm new to Unity and coding and am putting together a small project to help me get used to it. I have a problem with a particle system though. What I want it to do is to play two-particle systems at the same time when I hold down the spacebar and then stop when I let go, but the smoke particle system only plays after I let go of the spacebar and stops when I hold it down again. The flame particle system doesn't stop after I let go of the spacebar either. Can anyone help?
Here is the code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rocket : MonoBehaviour
{
public float fuel = 500f;
public float speed = 100f;
public Rigidbody rb;
public ParticleSystem flame;
public ParticleSystem smoke;
void Start()
{
flame.Stop();
smoke.Stop();
}
void FixedUpdate()
{
if (Input.GetKey(KeyCode.Space) && fuel > 0)
{
rb.AddForce(Vector3.up * speed);
float fuelUse = fuel-- * Time.deltaTime;
flame.Play();
smoke.Play();
}
}
}
You need to put an else after your if.
In this way when you aren't pressing space it will always stop, but will start when you press space and fuel is >0.
A great thing you can do in this cases is to put some Debug.Log() inside the if to check when it's playing so you can find other problems.
For example you can add the else with flame.Stop() and smoke.Stop() and put inside it a Debug.Log("stop") and inside the if a Debug.Log("play") so in the console you will always know what is happening and what is wrong
GetKey function resetting ur particle systems per frame so u can't see till release spacebar
if (Input.GetKeyDown(KeyCode.Space) && fuel > 0)
{
isPressed = true;
flame.Play();
smoke.Play();
}
if (isPressed && fuel > 0)
{
rb.AddForce(Vector3.up * speed);
float fuelUse = fuel-- * Time.deltaTime;
}
if (Input.GetKeyDown(KeyCode.Space))
{
isPressed = false;
flame.Stop();
smoke.Stop();
}
Related
I'm a beginner. I'm making a ball game in Unity, in which ball have to avoid the collision with the obstacle. In the game, I'm increasing the ball speed in every 3 seconds. Everything's working fine, but in the middle of game, I noticed the ball starts shaking, the speed decreases, and the camera can't catch the ball. I attached physics material to all gameobjects, and made all frictions zero, but the ball is still shaking.
Here is the link of the my game and the problem. Have a look: https://youtu.be/TR4M5whweTk
Here is the script attached to the ball:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
public Text gameOverText;
public Text scoreText;
public bool isGameOver;
public float speeder;
public float Score;
Touch touch;
public float speedmodifier ;
public float speed = 5;
// Start is called before the first frame update
private void Awake()
{
isGameOver = false;
Score = 0;
if(PlayerPrefs.GetFloat("HighScore") == 0)
{
PlayerPrefs.SetFloat("HighScore", 0);
}
PlayerPrefs.SetFloat("Score", Score);
}
void Start()
{
speeder = 4f;
gameOverText.enabled = false;
speedmodifier = 0.01f;
// GetComponent<Rigidbody>().velocity = new Vector3(0,0,speed);
}
// Update is called once per frame
void Update()
{ if(speeder >= 0)
{
speeder -= Time.deltaTime;
}
if (speeder<= 0 && speed < 50)
{
speed++;
speeder = 4f;
}
Debug.Log(speed);
if (isGameOver == false)
{
Score++;
}
scoreText.text = "Score : " + Score ;
if (Input.touchCount >0 && transform.position.x >= -3.5f && transform.position.x <= 3.5f)
{
touch = Input.GetTouch(0);
transform.Translate(touch.deltaPosition.x * speedmodifier,0,0);
}
else if(transform.position.x > 3.5f)
{
transform.position = new Vector3(3.49f,transform.position.y,transform.position.z);
}
else if(transform.position.x < -3.5f)
{
transform.position = new Vector3(-3.49f,transform.position.y,transform.position.z) ;
}
if (Input.GetKey(KeyCode.RightArrow) && transform.position.x < 3.5f)
{
transform.Translate(Vector3.right*speed* Time.deltaTime);
}
if (Input.GetKey(KeyCode.LeftArrow) && transform.position.x >-3.5f)
{
transform.Translate(Vector3.left*speed* Time.deltaTime);
}
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.tag == "enemy")
{
isGameOver = true;
StartCoroutine("Wait");
GetComponent<MeshRenderer>().enabled = false;
gameObject.GetComponentInChildren<TrailRenderer>().enabled = false;
gameOverText.enabled = true;
if(PlayerPrefs.GetFloat("HighScore") < Score)
{
PlayerPrefs.SetFloat("HighScore", Score);
PlayerPrefs.SetFloat("Score", Score);
}
else
{
PlayerPrefs.SetFloat("Score", Score);
}
}
}
IEnumerator Wait()
{
Debug.Log(" My HighScore is : " + PlayerPrefs.GetFloat("HighScore"));
Debug.Log(" Score is : " + PlayerPrefs.GetFloat("Score"));
yield return new WaitForSeconds(3f);
SceneManager.LoadScene(1);
}
}
As BugFinder pointed out you are actually not moving the ball with physics, but just teleporting the ball with Transform.Translate which might be affecting the shacking issue, the other possible problem is that your ball speed might be varying due to a collision with the road, have you tried making the road RigidBody to Kinematic? so it won't affect the speed of the ball
OK you SHOULD NOT be using unity phsyics for this.
It's a "raster" game (and that's fun).
remove all physics everything. completely remove rigidbody, collider, etc
simply move the ball and/or scenery using a calculation each time.
(It's basically just frame time * speed, obviously.)
(Note, you can use strictly triggers - if you want - simply to know if the "ball" is near a "stick". But you can do that with 1 line of code, really no need for colliders/etc.)
Your Question
I just want to make sure that I am understanding your question correctly first, I believe you are asking for a way to prevent the ball from shaking during the game. (Let me know if this is incorrect, if so I apologize). From what I have gathered, this does not seem like a code based issue
Collision Detection
In unity, the rigidbody component has a field named 'Collision Detection' and this is set to discrete by default. This means that unity will look in direction of travel for a possible collider every now and again. That is an okay method to use when trying to save computer resources, however when in constant contact or at high velocities it is best to use the 'continuous' mode. This will check for a collision every physics update which occurs every physics time-step.
Colliders
Colliders in unity are a little finicky. Most notorious are mesh colliders as they have to be more heavenly processed/calculated. Using a box collider for your ground might give more accurate physics results.
Other Solutions
Whilst looking at your game video you published on YouTube, it looks like using physics may not be able to work. Since you are only traveling left, right, and forward globally, I would suggest implementing a movement script that uses an object's transform component instead of physics. This will be less resource intensive and will save further debugging headaches in the long run.
My character just jumps continuously even in the air, I'm not sure why the boolean does not stop it and I cannot figure it out. This is what I have so far:
using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
public Rigidbody rb;
bool spacePressed = false;
float upForce = 200f;
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Obstacle")
{
spacePressed = false;
}
}
void Update()
{
if (Input.GetKey("space") && spacePressed == false)
{
spacePressed = true;
rb.AddForce(0, upForce * Time.deltaTime, 0, ForceMode.VelocityChange);
}
}
}
My guess is that 'space pressed' is never or instantly set to false. So a first step on debuging it can be to watch the boolean. You can do that with 'public ...'. Then you should just observe when it's set to true/false.
There is also the possiblilty of this being a totally different kind of issue. For instance that one of the colliders could be of the wrong size (too big/small)
And to complete the holy trinity: There is a free 2D platformer example in the unity hub. I think they use a different approche by using an empty GO as a 'isGrounded' checker. One of the first things I learned as a hobbist is not to be ashamed to copy code of example projects.
Good luck.
It is likely that the collider is hitting Obstacle as it makes its first jump. OnCollisionEnter is very unreliable when checking if an object is beside/on another object. This can be checked if you use Debug.Log and check to see how much times it randomly activates OnCollisionEnter.
To reliably check if an object is beside another object use raycasts or boxcasts instead.
This is some code that should work that uses raycasts:
using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
public Rigidbody rb;
public Collider collider;
public float extraCheckHeight = 0.1f;
float upForce = 200f;
bool isGrounded(){
Physics2D.Raycast(collider.bounds.center, Vector3.down, collider.bounds.extents.y + extraCheckHeight);
}
void Update()
{
if (Input.GetKey("space") && isGrounded)
{
rb.AddForce(0, upForce, 0, ForceMode.VelocityChange);//Time.deltaTime is should not be here because it should be the same force regardless of the time between frames
}
}
}
This should do the trick but I recommend researching about unity raycasts and boxcasts.
Here is a video on Ground Checking that I found useful when I was approached with a similar problem: Ground Check
As you can see in the screenshoot I can't see prefabs in the game tab but only in the editor. I have made a simple function for shooting(not finished yet), it works fine, it spawns the prefabs but i can't see them in the game tab, I have already tried changing the Sorting Layer, move the camera, change Z position but nothing appen.
This is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAttack : MonoBehaviour
{
[SerializeField]
float delayBetweenShots = 0.4f;
float timePassedSinceLast = 0f;
// Start is called before the first frame update
void Start()
{
timePassedSinceLast = delayBetweenShots;
}
// Update is called once per frame
void Update()
{
Aiming();
Shooting();
}
void Aiming()
{
var objectPos = Camera.main.WorldToScreenPoint(transform.position);
var dir = Input.mousePosition - objectPos;
transform.rotation = Quaternion.Euler(new Vector3(0,0,Mathf.Atan2(-dir.x, dir.y) * Mathf.Rad2Deg));
}
void Shooting()
{
if(Input.GetMouseButton(0) && timePassedSinceLast >= delayBetweenShots)
{
GameObject bullet = (GameObject)Instantiate(Resources.Load("bullet"), transform.position, transform.rotation);
timePassedSinceLast = 0f;
}
else
{
timePassedSinceLast += Time.deltaTime;
}
}
}
The prefabs get instantiated correctly. As others suggested as well, the best way to find "lost" objects in your game is to shoot some stuff, pause the game, go into scene view, turn on 3D mode and double click one of the prefabs in the hierarchy. The camera will take you straight to your object.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float speed;
public float jumpForce;
private float moveInput;
private Rigidbody2D rb;
private bool facingRight = true;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
}
void FixedUpdate()
{
moveInput = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
if(facingRight == false && moveInput > 0)
{
Flip();
}
else if(facingRight == true && moveInput < 0)
{
Flip();
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
}
I'm made a c# 2D player controller script to use in unity, but when I hit play, my player won't flip and face a different direction when he moves a different direction. Can anyone spot what's wrong in my script?
Nevermind. Was just a dumb bug. I put an outdated AND updated script component into my player. Yes I know I'm stupid.
Unity seems a good choice to developp your game but due to the simplicity of your game, i think it will be easier to create it using Android Studio, it is more easier to handler Character Sprite and Animation. All depend of what kind of game you want to create.
"""For instances guys, i create a simple SkaterBoard game using simple gravity physics with Android Studio, I would really appreciate if you could left a review on it."""
(Android Link) Skater Soldier Game: https://play.google.com/store/apps/details?id=com.fight.exempleclass
Always make sure you double check settings, values, and where you attached scripts : )
I've heard a couple people advise against flipping via scale and instead prefer :
transform.Rotate(0f, 180f, 0f);
Or depending on the gameplay / utility needed using SpriteRenderer.flipX
In case you'd like alternatives.
I Have started a new game.I have an enemy, and when the player is on a certain distance from the enemy, he attacks.My script works and the enemy follows the player, but despite the number I set there it's following the player.
I need the enemy follow only after being close enough to the player.
I have an empty object attached to the enemy and the script is on it.
I looked for the answer in unity community answers and find the script i use in this link https://answers.unity.com/questions/274809/how-to-make-enemy-chase-player-basic-ai.html
and also i have googled it but couldn't find any correct solution for it .
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AIController : MonoBehaviour
{
public int AttackTrigger2;
public Transform Player;
public int MoveSpeed = 4;
public int MaxDist = 10;
public int MinDist = 5;
void Update()
{
transform.LookAt(Player);
if (Vector3.Distance(transform.position, Player.position) >= MinDist)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
if (Vector3.Distance(transform.position, Player.position) <= MaxDist)
{
//Here Call any function U want Like Shoot at here or something
}
}
}
}
I have no errors on my code, he does what i need but i need enemy stop following the player after my player is from a certain distance.
I'm guessing that the next answer in the forum you linked actually solves your problem. The problem is simply copying and pasting without understanding why something behaves like it should. In this case:
>= MinDist
Means that the enemy will follow the player as long as it's greater than or equal to MinDist, in this case 5. I'm guessing that you want is:
<= MaxDist
so that the enemy only follows if it's less than 10 away. If it's over 10 away, stop following.
You should change condition in first if case.
According to your code enemy will follow the player, if distance between them is grater than MinDist.
Replace >= with<=.
And I think you may have wanted something like this.
if (Vector3.Distance(transform.position, Player.position) <= MaxDist)//not MinDist
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
if (Vector3.Distance(transform.position, Player.position) <= MinDist)//not MaxDist
{
//Here Call any function you want, like Shoot or something
}
}