- Home /
How to use one script for two objects? [Door opening]
I have 2 door on my scene and I open/close it using animation. I use the same script for each door (each door object have it's own script component) and when I open one door, the other are opens too. How can I detect, which door should I open?
For both doors I use the same animation
public Animation doorAnimation;
private bool isDoorClosed;
private bool isAimationReadyToPlay = true;
void Update ()
{
if (DoPlayerLookAtButton() && Input.GetButton("Fire1") && isAimationReadyToPlay)
OpenCloseDoor();
}
bool DoPlayerLookAtButton()
{
RaycastHit _hit;
Ray _ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
bool isHit = Physics.Raycast(_ray, out _hit, 1.5f);
if (isHit) return true;
else return false;
}
void OpenCloseDoor()
{
StartCoroutine("DelayBetweenAnimations");
if(!isDoorClosed) // Open door
{
doorAnimation["openDoor"].speed = 1.0f;
doorAnimation.Play();
}
else // Close door
{
doorAnimation["openDoor"].speed = -1.0f;
doorAnimation["openDoor"].time = doorAnimation["openDoor"].length;
doorAnimation.Play();
}
isDoorClosed = !isDoorClosed;
}
IEnumerator DelayBetweenAnimations()
{
isAimationReadyToPlay = false;
yield return new WaitForSeconds(0.5f);
isAimationReadyToPlay = true;
}
Answer by Garazbolg · Jan 25, 2016 at 01:40 PM
Physics.Raycast() returns true if it hit anything, so your doors should also open when you click on a wall. So the thing you should check is if it did hit this door, and you can find this in the hit variable you just declared :
//add at the start :
Collider thisCollider;
public void Start(){
thisCollider = GetComponent<Collider>();
}
//in DoPlayerLookAtButton :
bool DoPlayerLookAtButton()
{
RaycastHit _hit;
Ray _ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2, 0));
bool isHit = Physics.Raycast(_ray, out _hit, 1.5f);
if (isHit && _hit.collider == thisCollider) return true;
else return false;
}
That should do the trick, but if not comeback and we will fix it.
Hope it helps you.
Also the way you did your script is fine if you have only have 1 door but if you have like 50 of them you will do 50 Raycast. So you should do the raycast on the player check for the collider see if it has a door component and call a function to open that door.
Answer by coolraiman · Jan 25, 2016 at 03:55 PM
this is your error bool isHit = Physics.Raycast(_ray, out _hit, 1.5f); no matter what it hit, it will return true.
use if(hit.collider.name == this.name) and make sure each door have a different name
also, just by doing
if (Input.GetButton("Fire1") )
if(DoPlayerLookAtButton() && isAimationReadyToPlay)
OpenCloseDoor();
You would get a lot of performance since you raycast only when the button is pressed,
No need to use nested if statements here. Just reorder things like that:
if (isAimationReadyToPlay && Input.GetButton("Fire1") && DoPlayerLookAtButton())
The nice thing when using the &&
operator is that if the first operand evaluates to "false" it doesn't evaluate the second and just returns false. Similar the ||
operator doesn't evaluate the second operand when the first already evaluates to "true".
First you should always check simple variables as they are the cheapest to check. Next you might put low pressure method calls and the heaviest expressions should come last.
So in this case here we first check "isAimationReadyToPlay". If it's not true we're done. Only when the variable is true we actually check the button state and if the button is held down we finally call "DoPlayerLookAtButton".
However in some cases you might need to cast the ray every frame. For example when you want some kind of "mouse over" notification. The more important optimisation is what Garazbolg said in the comment above. If you have many doors you want to only cast one ray from a script on the player. Otherwise when you have 200 doors in your scene you will cast 200 rays every frame when your button is held down.
You also might want to replace "GetButton" with "GetButtonDown" or "GetButtonUp". This ensures that the door is only toggled when you actually press the button down or you released the button. When using GetButton the door would constantly toggle between open and close when the user holds down the button.
indeed, the order of condition is also a good idea for && statement but for more beginer programmer, they may not understand/remember it.
cascading condition have a better visibility for them
Also the number of raycast is an important issue for sure. if i really have to use raycast every frame, i make sure to only have one and use switch statement
Answer by Tanoshimi2000 · Jan 25, 2016 at 09:02 PM
Technically, this is not an answern but i didnt want it to get lost in the comments. Please do not flame me.
I place boxes with trigger colliders but no meshes rendered as part of my door prefab. Standing where you can open a door puts you in the box so the box trigger lets me know someone is in front of the door trying to open it. You can use code so they have to press a button to open it, or just open it if something enters the box, like electronic eye at the supermarket, or pressure pads.
Not 100% sure, but i believe thats less costly than a raycast.
what if the door can be openend by distance, on angle and only when you are ai$$anonymous$$g at it?
your solution is not bad but can only fit for a very specific design.
Your answer
Follow this Question
Related Questions
Good Game by One Person, Is it Possible? 2 Answers
Why aren't my parameters for animation not working? 0 Answers
What would be the best way to do something based on the animation state of the character? 0 Answers
2d game for my first unity project. 1 Answer
How to edit an animation in unity animation system by using script? 0 Answers