Giving different values to cloned prefabs with the same script.
Hey there, I am creating a game with a friend, but I realised there is a bug in my code. I am trying to create a script that opens and closes doors with an animation. I use a bool called 'open' to find out if the door is open or closed, but everytime I open/close a door, the bool value changes for every door with the same script. Any idea how I can fix this?
My code:
public class DoorController : MonoBehaviour {
private RaycastHit hit;
private GameObject door;
public bool open;
private bool cooldown;
private bool loopBool;
public GameObject pointer;
public AudioClip openSound;
public AudioClip closeSound;
// Use this for initialization
void Start () {
open = false;
cooldown = false;
loopBool = true;
door = this.gameObject;
}
private IEnumerator Open(){
while (loopBool) {
cooldown = true;
yield return new WaitForSeconds (1);
open = false;
cooldown = false;
break;
}
}
private IEnumerator Close(){
while (loopBool) {
cooldown = true;
yield return new WaitForSeconds (1);
open = true;
cooldown = false;
break;
}
}
// Update is called once per frame
void Update () {
Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 1.5f);
if (hit.collider != null && hit.collider.tag == "OpenableDoor") {
//door = hit.collider.gameObject;
pointer.SetActive (true);
if (Input.GetKey (KeyCode.Mouse0)) {
if (cooldown == false) {
if (open) {
this.door.GetComponent<Animation> ().Play ("DoorClose");
AudioSource.PlayClipAtPoint(closeSound, transform.position);
StartCoroutine (Open ());
}
if (open == false) {
this.door.GetComponent<Animation> ().Play ("DoorOpen");
AudioSource.PlayClipAtPoint(openSound, transform.position);
StartCoroutine (Close ());
}
}
}
} else {
pointer.SetActive (false);
}
}
}
Answer by yummy81 · Feb 08, 2018 at 10:41 PM
So, let's assume that there are four doors at the scene. Each of them has its own DoorController script attached. Therefore, each door has its own bool and casts its own ray. So, we have four doors, four scripts, four bools, and four raycasts. None of the raycasts distinguish between door#1, door#2, door#3 and door#4. For raycasts, all the doors are the same. For raycasts, all that matters is whether the object that was hit has "OpenableDoor" tag. Each ray starts at the same position and has the same direction and length. So, when all four rays hit one of the four doors (no matter which one) then all four bools are adjusted. The solution to this would be to get rid of those three unnecessary raycasts and leave just one. In order to do that you have to create the script for raycasting, let's name it DoorController, and the script DoorScript which will be attached to each door. Create new gameobject and drop the DoorController script on it and then drop DoorScript on each door gameobject. The following code is just a hypothetical one, but as you know now where the problem lies, it's just a matter of tinkering with it to make it work as you want. Code for DoorController script:
public class DoorController : MonoBehaviour
{
private RaycastHit hit;
public GameObject pointer;
void Update ()
{
Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 1.5f);
if (hit.collider != null && hit.collider.tag == "OpenableDoor")
{
pointer.SetActive (true);
if (Input.GetKey (KeyCode.Mouse0))
{
// this piece of code was added by me
DoorScript d = hit.collider.GetComponent<DoorScript>();
if (d!=null)
{
d.Foo();
}
// that's where my code ends
}
}
else
{
pointer.SetActive (false);
}
}
}
Code for DoorScript. I added here new public method Foo and removed Update with raycasts:
public class DoorScript: MonoBehaviour
{
private GameObject door;
public bool open;
private bool cooldown;
private bool loopBool;
public AudioClip openSound;
public AudioClip closeSound;
// Use this for initialization
void Start () {
open = false;
cooldown = false;
loopBool = true;
door = this.gameObject;
}
private IEnumerator Open(){
while (loopBool) {
cooldown = true;
yield return new WaitForSeconds (1);
open = false;
cooldown = false;
break;
}
}
private IEnumerator Close(){
while (loopBool) {
cooldown = true;
yield return new WaitForSeconds (1);
open = true;
cooldown = false;
break;
}
}
public void Foo()
{
if (cooldown == false) {
if (open) {
this.door.GetComponent<Animation> ().Play ("DoorClose");
AudioSource.PlayClipAtPoint(closeSound, transform.position);
StartCoroutine (Open ());
}
if (open == false) {
this.door.GetComponent<Animation> ().Play ("DoorOpen");
AudioSource.PlayClipAtPoint(openSound, transform.position);
StartCoroutine (Close ());
}
}
}
}
Sorry for the late reaction, but thank you! This really helped me!