- Home /
How can I access a GameObject's script from a prefab?
Hello everyone,
I have recently posted this question on the forums with sadly no solutions :
As you can see, I'm trying to access a another script from my prefab but I am not able to link the public script to my prefab. (It wont let me drag and drop it)
I basically want, depending if my character is looking up, down, left or right, for him to shoot in front of him (ie if he is looking up, he will shoot up)
I haven't been able to make the getcomponent work and I keep getting the following error: NullReferenceException: Object reference not set to an instance of an object BeamPrefabShooting.FixedUpdate () (at Assets/BeamPrefabShooting.cs:17) or sometimes it's 18
I'm really new to unity and coding, so please could someone help me? Thank you!!
for reference, here are the scripts:
Player movement script:
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerMovement : MonoBehaviour { public float moreSpeed; private float speed = 0.02f; public Animator anim;
public bool upAnim; public bool downAnim; public bool leftAnim; public bool rightAnim; public void MoreMovement() { // --------------- Extra Speed Movements ---------------- if (Input.GetKey(KeyCode.UpArrow) && (Input.GetKey(KeyCode.Space))) { transform.Translate(0,speed + moreSpeed, 0); } if (Input.GetKey(KeyCode.DownArrow) && (Input.GetKey(KeyCode.Space))) { transform.Translate(0,-speed - moreSpeed, 0); } if (Input.GetKey(KeyCode.RightArrow) && (Input.GetKey(KeyCode.Space))) { transform.Translate(speed + moreSpeed, 0, 0); } if (Input.GetKey(KeyCode.LeftArrow) && (Input.GetKey(KeyCode.Space))) { transform.Translate(-speed - moreSpeed, 0, 0); } } public void Movement() { // ---------------Normal Movements--------------- if (Input.GetKey(KeyCode.UpArrow)) { // xUp = xUp + speed; transform.Translate(0, speed, 0); anim.SetBool("Up", true); anim.SetBool("Down", false); anim.SetBool("Left", false); anim.SetBool("Right", false); upAnim = true; downAnim = false; leftAnim = false; rightAnim = false; } if (Input.GetKey(KeyCode.DownArrow)) { // xDown = xDown - speed; transform.Translate(0, -speed, 0); anim.SetBool("Up", false); anim.SetBool("Down", true); anim.SetBool("Left", false); anim.SetBool("Right", false); upAnim = false; downAnim = true; leftAnim = false; rightAnim = false; } if (Input.GetKey(KeyCode.RightArrow)) { // yUp = yUp + speed; transform.Translate(speed, 0, 0); anim.SetBool("Up", false); anim.SetBool("Down", false); anim.SetBool("Left", false); anim.SetBool("Right", true); upAnim = false; downAnim = false; leftAnim = false; rightAnim = true; } if (Input.GetKey(KeyCode.LeftArrow)) { // yDown = yDown - speed; transform.Translate(-speed, 0, 0); anim.SetBool("Up", false); anim.SetBool("Down", false); anim.SetBool("Left", true); anim.SetBool("Right", false); upAnim = false; downAnim = false; leftAnim = true; rightAnim = false; } } void Start () { anim = GetComponent<Animator>(); } private void FixedUpdate() { //we always use FixedUpdate for physics (rigidbody2d) { Movement(); MoreMovement(); } } // Update is called once per frame void Update () { } }
Prefab Script: using System.Collections; using System.Collections.Generic; using UnityEngine;
public class BeamPrefabShooting : MonoBehaviour {
public Rigidbody2D rb;
public float bulletSpeed;
public GameObject collidedBullet;
public PlayerMovement playerMovement; // format: private - Onoma tou script - onoma tou gameobject pou epirieazete
// apo to script
private void Start()
{
playerMovement = GetComponent<PlayerMovement>();
}
void FixedUpdate () {
if (playerMovement.rightAnim == true)
{
rb.velocity = new Vector2(bulletSpeed, 0);
}
if (playerMovement.leftAnim == true)
{
rb.velocity = new Vector2(-bulletSpeed, 0);
}
if (playerMovement.upAnim == true)
{
rb.velocity = new Vector2(0, bulletSpeed);
}
if (playerMovement.downAnim == true)
{
rb.velocity = new Vector2(0, -bulletSpeed);
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "wall")
{
Destroy(collidedBullet);
}
}
private void Update()
{
}
}
Pick Up Script:
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class BeamPickUp : MonoBehaviour { public Object Player; public Object pickUpBeam; public int itemCount; // Use this for initialization void Start () {
} // Update is called once per frame void Update () { afterDestroyed(); } void OnCollisionEnter2D(Collision2D Player) { if (Player.gameObject.tag == "Beam" ) { Destroy(pickUpBeam); itemCount++; print("Item count = " + itemCount); } } void afterDestroyed() { /* if (pickUpBeam = pickUpBeam) { print("not destroyed"); } else { print("destroyed"); } */} }
The whole idea is that if the player touches the item,the item gets destroyed and he then unlocks the ability to shoot beams.
Thank you all!!
Answer by seandolan · Jun 26, 2018 at 06:17 AM
If you have 2 gameobjects each with a script attached to them, you can call the script and any public functions/variables from each other.
Let's call the objects Object1 and Object2 and the scripts Script1 and Script2 to make things easier to understand.
// Script1's code attached to Object1
public GameObject object2;
void Start() {
object2.GetComponent<Script2>.LogMessage("hello world");
}
// Script2's code attached to Object2
public void LogMessage(string _message){
Debug.Log(_message);
}
This is how you can easily call a script function from another object.
In this instance, you will need to drag Object2 into the public GameObject called "object2" attached to Object1
Thank you so much for your answer. This makes things a lot easier thanks to the simplicity. I made everything as you said but there is one problem. I cannot assign components to a prefab from the actual gameObjects in the hierarchy. (I cannot drag and drop the 'player' object to the prefab's script where I should, it wont allow me)
Once again, thank you for your help.
That's great you have gotten further. Does your player have a "Player" tag or assigned to a specific layer?
If you assign the Player tag to your player object (that has a script attached) you could try something like this on the prefab's script:
GameObject player;
Then in the Start() fuction add this:
player = GameObject.FindWithTag("Player");
When you need to call the script do this:
player.GetComponent<ScriptNameHere>().FireBullet(100);
This example assumes you have a public void FireBullet(float bulletSpeed) - but you can just do:
player.GetComponent<ScriptNameHere>().FireBullet();
if you don't want to send it a value at the same time. You can also change variable values like this if you want:
player.GetComponent<ScriptNameHere>().playerName = "PanaPetsas";
The "GameObject player;" replaces "public GameObject object2;" in our original script
Your answer
Follow this Question
Related Questions
GetComponent vs AddComponent 3 Answers
Unity crashes after I destroy a gameobject 1 Answer
C# GetComponent Issue 2 Answers
Acessing a Script Instance from Another Object 3 Answers
Can someone translate C# to Javascript? 2 Answers