I am new to unity and have begun trying to recreate 'flappy bird' from scratch. The pipes when the move out of the game view, speed up then slow down.
Here is the code for the pipes:
public class PipeMoving : MonoBehaviour
{
public float slideSpeed = 5f;
void Update()
{
GetComponent<Rigidbody2D>().AddForce(Vector2.left * slideSpeed, (ForceMode2D)ForceMode.Impulse);
}
}
I guess the reason why your object is slowing down is because you used force mode impulse, which will initially apply that force only once.... In order to fix it do ForceMode2D.Force, which will apply a constant force on that object.
Make the variable private and use SerializeField so it can be visible in the inspector panel and not accessed anywhere else...
[SerializeField]
private float slideSpeed = 5f;
void Awake()
{
myBody = GetComponent<Rigidbody2D>();
}
void Update()
{
move();
}
void move()
{
myBody.AddForce(new Vector2.left(slideSpeed,0), ForceMode2D.Force);
}
Set a variable myBody( or anything you prefer) as the rigidbody component so you can use it multiple times in your code more efficiently...
**Edits listed below:
I have included the keyword 'new' before Vector2.left(slideSpeed,0)
I did that because there is no pre-existing vector which is Vector2.left(slideSpeed,0) so you have to use the keyword new whenever you are declaring a vector for the first time.
If you are considering to reuse the vector, then you can declare it in the top of your code...
leftVector = new Vector2.left(slideSpeed,0);
On doing so, you don't have to use the new keyword when you will use the variable later, incase that confuses you...
Related
I have a script for that Instantiates 2 game object but when something happens to one of them it also happens to the another one even when the conditions are not met for it. How can I make the script act separately for every Game Object?
GO script:
private Transform target;
public float speed = 2f;
private Animator anim;
public float H2Damage = 5f;
private healthBar Hp;
void Start()
{
target = GameObject.FindGameObjectWithTag("enemy").GetComponent<Transform>();
anim = gameObject.GetComponent<Animator>();
Hp = GameObject.FindGameObjectWithTag("enemy").GetComponentInChildren<healthBar>();
}
void Update()
{
target = GameObject.FindGameObjectWithTag("enemy").GetComponent<Transform>();
if (Hp.Died == true)
{
Hp.Died = false;
anim.SetBool("Hero2Attack", false);
anim.SetBool("Hero2Move", true);
}
if (!target || this.anim.GetCurrentAnimatorStateInfo(0).IsName("Hero2ATTACK"))
return;
transform.position = Vector2.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
anim.SetBool("Hero2Move", true);
}
private void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.CompareTag("enemy"))
{
anim.SetBool("Hero2Attack", true);
healthBar hp = col.transform.GetComponent<healthBar>();
hp.GiveDamage(H2Damage);
}
}
I believe they act the same way because they are getting the same GetComponentWithTag(), so they will Get the same objects. You also instantiate the animator, which is the exact same one, so they will do the same things. --> If it was as simple as changing the position by 1 meter per second, they would have different behavior (ie. be at different positions) But.... If you instantiate it, the current position is also instantiated, so you are going to have to get the current postion and set it to what you want, so both of these moving boxes aren't at the exact same position. You will have to do something similar here, you are going to want to either (create different scripts for the objects, or set the script values to different things)
TL;DR: You are copying the exact same script with the exact same components, so they will act similarly.
Fix: The only way to fix this is by setting their values after you instantiate them using GetComponent<>()or changing the script you assign them. (or any components for that matter)
Let me know if you have any problems or questions in the comments! :)
I want in my Unity game, to get a float of another GameObject.
The Gameonject is called "Spawner", the script on the GameObject "CarZSpawner" and the float in the script "mult". The float "mult ist changing every few seconds."
i tried many things but nothing works, and i can't find anything on the internet :(
public class TrainScript : MonoBehaviour
{
void Update()
{
float test = GameObject.Find("Spawner").GetComponent<CarScriptZ.mult>()
}
}
Thanks for help :)
I'm pretty that your script is called CarScriptZ and mult is rather the field you are trying to access so it should be
float test = GameObject.Find("Spawner").GetComponent<CarScriptZ>().mult;
Besides that you should store the references once e.g. in Start and then re-use it later like
// If possible already reference this via the Inspector by drag & drop
[SerializeField] private CarScriptZ carScriptZ;
private void Start()
{
// As fallback get it ONCE on runtime
if(!carScriptZ) carScriptZ = GameObject.Find("Spawner").GetComponent<CarScriptZ>();
}
private void Update()
{
float test = carScriptZ.mult;
}
I'm trying to make the game Snake, and I'm trying to get the apple functionality working. What this script is meant to do, is whenever my Snake goes over the Apple, the apple disappears and reappears at a random location on the screen. But instead it does nothing, any idea as to why?
P.S: Camera is Size 10 and Aspect Ratio is 16:9 which is why I have some weird Random.Range values. Also I used Debug.Log in Update to make sure that the variable worked, and yes it does, whenever my snake moves its coordinates are displayed.
public class Apple_RandomSpawn : MonoBehaviour
{
private Vector2 foodPos;
private Snake_Move snakeMove;
void Start()
{
SpawnApple();
}
public void Update()
{
transform.position = new Vector2(foodPos.x, foodPos.y);
SnakeAte();
}
public void SpawnApple()
{
foodPos = new Vector2(Random.Range(-17, 17), Random.Range(-9, 9));
}
public void SnakeAte()
{
if (Mathf.Approximately(foodPos.x, snakeMove.pos.x) && Mathf.Approximately(foodPos.y, snakeMove.pos.y))
{
SpawnApple();
}
}
}
First of all, it does not directly have something to do with your problem, but DO NOT put GetComponent() or GameObject.Find() in the Update() function. These two, especially GameObject.Find() function is super heavy, so It's recommended that you should call these kinds of function inside Start() or Awake(), or at the initiallization of a class. It can directly, and heavily impact the performance of your game, so here's my suggestion:
[SerializeField]
private Snake_Move snakeMove;
And drag your gameobject (which Snake_Head component is attatched) via Inspector. You should always consider this way first, rather than using GameObject.Find() and GetComponent().
Second, Float is not recommend to compare equality directly through =, since there must be rounding error. There is a help function with regard to comparing two float value in Unity, like Mathf.Approximately(float a, float b). Directly comparing two float value via = would almost always not work as you might think.
Third, It doesn't seem to be that there are no Instantiate() function in your code, but you are try to use one apple object, and every time you consume it, just change it's position. Then why does Object.Destroy(gameObject) exists? What you're doing is, just destroying the apple when you get it first time. I think you have to remove the Destroy() function, and SpawnApple() changes the target coordinate of apple, and the position will be updated in Update() function.
And it's no need to indirectly set the target position, and update to it in Update() function. You can directly set the position of apple, like:
// assuming you followed my suggestio aboven about snakeMove.
public void Update()
{
SnakeAte();
Debug.Log(snakeMove.pos);
}
public void SpawnApple()
{
transform.position = new Vector2(Random.Range(-17, 17), Random.Range(-9, 9));
}
public void SnakeAte()
{
if (foodPos == snakeMove.pos)
{
SpawnApple();
}
}
First of all your null ref in your last comment comes from:
private Snake_Move snakeMove;
Its a private variable and its never assigned. You either need to make it public/[SerialistField] and assign it in inspect or have some sort of initialize function that give it a value.
For the hit detection Mathf.Approximately is good if you wan to check if 2 floats are exactly the same. If you'r checking 2 positions of moving objects the chance of them being exactly the same is very low and may rely on frame rate and such. Keeping your implementation you can check instead for a minimum distance between the 2 positions. You can tweak DISTANCE_THRESHOLD for a value that suits your better.
public class Apple_RandomSpawn : MonoBehaviour
{
private const float DISTANCE_THRESHOLD = 0.1f;
private Vector2 foodPos;
private Snake_Move snakeMove;
void Start()
{
SpawnApple();
}
public void Update()
{
SnakeAte();
}
public void SpawnApple()
{
foodPos = new Vector2(Random.Range(-17, 17), Random.Range(-9, 9));
transform.position = new Vector2(foodPos.x, foodPos.y);
}
public void SnakeAte()
{
if (Vector3.Distance(foodPos, snakeMove) < DISTANCE_THRESHOLD)
{
SpawnApple();
}
}
}
Now remember that since your teleporting the apple to a purely random location it might teleport right back on top of your snake :).
I'll keep this brief and a bit short, but I currently have a particle system that seems to not be rendering even though my collision works.
I have trouble understanding other peoples work so I have not been able to find a solution I can understand.
Here is my code:
public float speed;
public Rigidbody rb;
public int health;
private float knockback;
private float knockup;
public ParticleSystem Eparticle; //*** variable for particle system ***
// Use this for initialization
void Start()
{
rb = GetComponent <Rigidbody>();
knockback = 100f;
knockup = 250f;
}
void OnCollisionEnter(Collision col)
{
if (col.gameObject.name == "enemy")
{
health = health - 20;
rb.AddRelativeForce(Vector3.back * knockback);
rb.AddRelativeForce(Vector3.up * knockup);
Destroy(col.gameObject);
Instantiate(Eparticle);
}
if (col.gameObject.name == "endgoal")
{
SceneManager.LoadScene("level 1");
}
}
What am I doing wrong with my instantiate(Eparticle) line?
Could someone please talk me through a solution?
Thank You :)
You should invoke the Instantiate method at the position where you want the particle prefab to appear.
You could do something like this...
Instantiate(Eparticle,transform.position,transform.rotation);
Actually, you can also create (instantiate) a GameObject at runtime as follows...
GameObject obj= Instantiate(Eparticle,transform.position,transfrom.rotation) as GameObject;
This way, you have some sort of 'control' over the instantiated gameobject.
For instance, you can destroy the object after using it by calling the Destroy() method.
E.g.:
Destroy(obj,2f);//Destroys the created object after 2 seconds.
Of course, this is not a good way to go about it if you are going to be instantiating and destroying a lot of objects. You should read about Object Pooling for this purpose.
public class a : MonoBehaviour
{
private float speed;
void Start()
{
speed=1;
}
void Update()
{
this.transform.Translate (Vector2.right * speed * Time.deltaTime);
animator.Play ("gub");
}
public void button ()
{
speed = 6f;
}
}
When I press button , I'd like to change the objects speed which are prefab.
The first prefab's speed changes... but the rest do not change.
What is wrong?
You are changing a variable of an instance of a GameObject, not a prefab.
A prefab is like a blueprint of a GameObject, so most of the data will be copied to each instance of that GameObject. But all the code that you write is referent to each instance, in that way each object will move freely from one to another, imagine if every time that you made a change in a GameObject variable, like its life, all the other instances changed the life together, it would be a mess.
To solve your problem you will need to get the information from that variable from a common place, something like a LevelManager, a place were every instance of the object can get the same value, it can be a static field in some object or a field in a Singleton, that depends on the structure of your game.