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;
}
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 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...
I've searched around and I just can't get this to work. I think I just don't know the proper syntax, or just doesn't quite grasp the context.
I have a BombDrop script that holds a public int. I got this to work with public static, but Someone said that that is a really bad programming habit and that I should learn encapsulation. Here is what I wrote:
BombDrop script:
<!-- language: c# -->
public class BombDrop : MonoBehaviour {
public GameObject BombPrefab;
//Bombs that the player can drop
public int maxBombs = 1;
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Space)){
if(maxBombs > 0){
DropBomb();
//telling in console current bombs
Debug.Log("maxBombs = " + maxBombs);
}
}
}
void DropBomb(){
// remove one bomb from the current maxBombs
maxBombs -= 1;
// spawn bomb prefab
Vector2 pos = transform.position;
pos.x = Mathf.Round(pos.x);
pos.y = Mathf.Round(pos.y);
Instantiate(BombPrefab, pos, Quaternion.identity);
}
}
So I want the Bomb script that's attached to the prefabgameobject Bombprefab to access the maxBombs integer in BombDrop, so that when the bomb is destroyed it adds + one to maxBombs in BombDrop.
And this is the Bomb script that needs the reference.
public class Bomb : MonoBehaviour {
// Time after which the bomb explodes
float time = 3.0f;
// Explosion Prefab
public GameObject explosion;
BoxCollider2D collider;
private BombDrop BombDropScript;
void Awake (){
BombDropScript = GetComponent<BombDrop> ();
}
void Start () {
collider = gameObject.GetComponent<BoxCollider2D> ();
// Call the Explode function after a few seconds
Invoke("Explode", time);
}
void OnTriggerExit2D(Collider2D other){
collider.isTrigger = false;
}
void Explode() {
// Remove Bomb from game
Destroy(gameObject);
// When bomb is destroyed add 1 to the max
// number of bombs you can drop simultaneously .
BombDropScript.maxBombs += 1;
// Spawn Explosion
Instantiate(explosion,
transform.position,
Quaternion.identity);
In the documentation it says that it should be something like
BombDropScript = otherGameObject.GetComponent<BombDrop>();
But that doesn't work. Maybe I just don't understand the syntax here. Is it suppose to say otherGameObject? Cause that doesn't do anything. I still get the error : "Object reference not set do an instance of an object" on my BombDropScript.maxBombs down in the explode()
You need to find the GameObject that contains the script Component that you plan to get a reference to. Make sure the GameObject is already in the scene, or Find will return null.
GameObject g = GameObject.Find("GameObject Name");
Then you can grab the script:
BombDrop bScript = g.GetComponent<BombDrop>();
Then you can access the variables and functions of the Script.
bScript.foo();
I just realized that I answered a very similar question the other day, check here:
Don't know how to get enemy's health
I'll expand a bit on your question since I already answered it.
What your code is doing is saying "Look within my GameObject for a BombDropScript, most of the time the script won't be attached to the same GameObject.
Also use a setter and getter for maxBombs.
public class BombDrop : MonoBehaviour
{
public void setMaxBombs(int amount)
{
maxBombs += amount;
}
public int getMaxBombs()
{
return maxBombs;
}
}
use it in start instead of awake and dont use Destroy(gameObject); you are destroying your game Object then you want something from it
void Start () {
BombDropScript =gameObject.GetComponent<BombDrop> ();
collider = gameObject.GetComponent<BoxCollider2D> ();
// Call the Explode function after a few seconds
Invoke("Explode", time);
}
void Explode() {
//..
//..
//at last
Destroy(gameObject);
}
if you want to access a script in another gameObject you should assign the game object via inspector and access it like that
public gameObject another;
void Start () {
BombDropScript =another.GetComponent<BombDrop> ();
}
Can Use this :
entBombDropScript.maxBombs += 1;
Before :
Destroy(gameObject);
I just want to say that you can increase the maxBombs value before Destroying the game object. it is necessary because, if you destroy game object first and then increases the value so at that time the reference of your script BombDropScript will be gone and you can not modify the value's in it.
I want to access the HorizontalAxis variable from the CarAgent component (of the Taxi gameobject).
It works fine when I try to access it from another gameobject, but when I try to access it in CarUserControl, which is also a Taxi component, it says that CarAgent doesn't exist.
This is the other gameobject's script and it works fine:
private float HorizontalAxis;
public void Start() {
HorizontalAxis = GameObject.Find("Taxi").GetComponent<CarAgent>().HorizontalAxis;
}
// Update is called once per frame
public void Update()
{
transform.rotation = new Quaternion(0, 0, HorizontalAxis, 360);
}
and this is the CarUserControl script:
private void Start()
{
HorizontalAxis = GameObject.Find("Taxi").GetComponent<CarAgent>().HorizontalAxis;
}
How can I access the HorizontalAxis variable in CarUserControl ?
EDIT: I tried to access other classes in this script and it doesn't work neither.
I got this script from the UnityStandardAssets/Vehicules/Car, so at the beginning, it is written:
namespace UnityStandardAssets.Vehicles.Car
{
[RequireComponent(typeof (CarController))]
public class CarUserControl : MonoBehaviour
{
I am new to unity and c# so does it change something. And if yes, how can I fix it?
Finally, the problem was that the CarUserControl was in the standard assets folder and that the CarAgent script was not in that folder. Apparently, the standard assets folder does not compilate at the same time as other folders. See more here!
Its likely that you are too low or too high in the gameobject chain.
Try
car = GetComponent<CarAgent>(this.parent);
OR
car = GetComponent<CarAgent>(this.child);
h = car.HorizontalAxis;
It's mainly because there are inconsistencies between the Update() (every frame) and the FixedUpdate() (every physics frame). Indeed a FixedUpdate can be called more than once for the same Update() frame, or not at all.
Unity's doc about Order of Execution explains it more.
Also, querying GetComponent<T> in loops is quite heavy. It is wiser to "cache" the reference in an Init method like Start() or Awake().
private HorizontalAxis hAxis;
public void Start(){
GameObject taxi = GameObject.Find("Taxi");
if(taxi != null){
hAxis = taxi.GetComponent<CarAgent>().HorizontalAxis;
}
}
public void Update(){
if(hAxis != null)
transform.rotation = new Quaternion(0, 0, hAxis, 360);
}
public void FixedUpdate(){
if(hAxis != null){
// Do only Physics related stuff: rigidbodies, raycast
// inputs and transform operations should stay in the Update()
}
}
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.