- Home /
Door smoothly opens to the side - Problem
I have a problem to make a smooth transition to open the door to the side. My script is working except the smooth sliding. With my script the door "jumps" to the given coordinates, why?
public class Door : MonoBehaviour
{
public bool doorOpen = false;
//Sliding Door
private Vector3 doorStartPosition;
public Vector3 doorEndPosition;
[Header ("Sliding Door")]
public bool isSlidingDoor = false;
[Tooltip ("The distance how far the door should slide. Leave at 0 if the door should rotate.")]
public float doorMoveDistance = 0;
void Start ()
{
doorStartPosition = transform.position;
}
// Update is called once per frame
void Update ()
{
if(isSlidingDoor && doorOpen )
{
OpenSlidingDoor ();
}
}
public void ChangeDoorState ()
{
doorOpen = !doorOpen;
}
public void OpenSlidingDoor ()
{
transform.position = Vector3.Lerp (doorStartPosition, doorEndPosition, doorMoveDistance * Time.deltaTime);
transform.position = doorEndPosition;
}
Thanks!
Answer by Legend_Bacon · Nov 15, 2017 at 05:48 PM
Hello there,
I use scripts to perform all these sorts of animations, opening/closing doors included. In your script, in the function "OpenSlidingDoor ", you use transform.position = doorEndPosition;
, which sets it to its target position immediately.
Instead, I encourage you to use something like this:
float f_animDuration = 1.25f;
private void ToggleDoor(bool isOpening)
{
StartCoroutine(DoorSlide(isOpening));
}
private IEnumerator DoorSlide(bool isOpening)
{
float timer = 0.0f;
Vector3 startPos = transform.position;
Vector3 endPos = isOpening ? doorEndPosition : doorStartPosition;
while (timer < f_animDuration)
{
timer += Time.deltaTime;
float t = timer / f_animDuration;
t = t * t * t * (t * (6f * t - 15f) + 10f);
transform.position = Vector3.Lerp(startPos, endPos, t);
yield return null;
}
yield return null;
}
With this, you can tell the door to open just by calling ToggleDoor(true);
, or false if you want to close it. It will always take the same duration (f_animDuration) to fully open or close. I use a smoothstep formula here, but any kind of animation would do. You can find more info HERE.
I hope that helps!
~LegendBacon
Thank you for this solution and for the help! the only thing i dont understand correctly ist this line of code:
Vector3 endPos = isOpening ? doorEndPosition : doorStartPosition;
the opening thing works correctly but if i want to call ToggleSlidingDoor(false); the Vector 3 coordinates will be set to a different location and not to the manually setted values in the inspector and also the door dont close. heres my script
if(isSlidingDoor && doorOpen )
{
ToggleSlidingDoor (true);
}
else if(isSlidingDoor && !doorOpen )
{
//ToggleSlidingDoor (false);
}
public void ToggleSlidingDoor (bool doorOpen)
{
StartCoroutine (DoorSlide (doorOpen));
}
private IEnumerator DoorSlide(bool doorOpen)
{
float timer = 0.0f;
doorStartPosition = transform.position;
doorEndPosition = doorOpen ? doorEndPosition : doorStartPosition;
while(timer < door$$anonymous$$oveDistance )
{
timer += Time.deltaTime;
float t = timer / door$$anonymous$$oveDistance;
transform.position = Vector3.Lerp (doorStartPosition, doorEndPosition, t);
yield return null;
}
yield return null;
}
Opening works fine thank you :) But the closing one not. Need to read more about it or learn.
Hello there,
So first about the line : Vector3 endPos = isOpening ? doorEndPosition : doorStartPosition;
It's basically a fancy IF statement, and could be written ins$$anonymous$$d as: Vector3 endPos = Vector3.zero; if(isOpening){endpos = doorEndPosition;} else {endPos = doorEndPosition;}
.
That means, if the door is opening, we want it to move towards "doorEndPosition". If it is closing, we want it to move towards "doorStartPosition". $$anonymous$$ore about the "?" operator HERE.
Now about the code not working: I noticed you changed a few things about it, so let's review.
First, when you call the function, you should probably just have
if(isSlidingDoor){ToggleSlidingDoor(doorOpen);}
, since doorOpen already has the proper value.Second, I see you are using "door$$anonymous$$oveDistance" ins$$anonymous$$d of a duration. I just want to point out that regardless of the distance, this code will always take the same time to perform the animation. You should probably rename that variable to "door$$anonymous$$oveDuration".
And last, in the IEnumerator itself, you assign doorStartPosition and doorEndPosition to something else. That means that the opening works fine, but let's take a look at what happens when you close: "doorStartPosition" gets assigned to the door's current position, and then it tries assigning "doorEndPosition" to "doorStartPosition", which is now your current position. So now it is trying to move from and to the same point. Ins$$anonymous$$d, what you want to do is this:
if(isSlidingDoor ) { ToggleSlidingDoor(doorOpen); } public void ToggleSlidingDoor (bool doorOpen) { StartCoroutine (DoorSlide (doorOpen)); } private IEnumerator DoorSlide(bool doorOpen) { float timer = 0.0f; // Define point to move from: Vector3 startPosition = transform.position; // Define point to move to: Vector3 endPosition = Vector3.zero; if(doorOpen) { // The door is opening, so we want it to move towards the "opened state" endPosition = doorEndPosition; } else { // The door is opening, so we want it to move back to the "closed state" endPosition = doorStartPosition; } // Start $$anonymous$$ovement while(timer < door$$anonymous$$oveDistance ) { timer += Time.deltaTime; float t = timer / door$$anonymous$$oveDistance; transform.position = Vector3.Lerp (startPosition, endPosition, t); yield return null; } // $$anonymous$$ovement over yield return null; }
This code should just work with your setup. I hope that helps!
~LegendBacon
Thank you for your help! But it dont work as i want it or perhaps something is wrong. The door opens but dont close. i try to close but it cant for some reason. also the boolean doorOpen wont change when the door is opening and i dont really know why?!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FPSHorror
{
public class Door : $$anonymous$$onoBehaviour
{
public bool isDoorLocked = false;
public string needed$$anonymous$$eyToUnlock = "";
public bool doorOpen = false;
//Rotating Door
[Header ("Rotating Door")]
public bool isRotatingDoor = false;
public float openDoorSmooth = 2f; // Speed of the opening/closing door
public float doorClosedAngle = 0f;
public float doorOpenAngle = -90f;
//Sliding Door
private Vector3 doorStartPosition;
[Header ("Sliding Door")]
public bool isSlidingDoor = false;
public Vector3 doorEndPosition;
public float door$$anonymous$$oveDuration = 0;
void Update ()
{
if (isRotatingDoor && doorOpen )
{
OpenRotatingDoor ();
}
else
{
CloseRotatingDoor ();
}
if ( isSlidingDoor)
{
ToggleSlidingDoor (true);
}
}
public void ChangeDoorState ()
{
doorOpen = !doorOpen;
//ToggleSlidingDoor (doorOpen);
}
public void OpenRotatingDoor ()
{
Quaternion doorOpenRoatation = Quaternion.Euler (0, doorOpenAngle, 0);
transform.localRotation = Quaternion.Slerp (transform.localRotation, doorOpenRoatation, openDoorSmooth * Time.deltaTime);
}
public void CloseRotatingDoor ()
{
Quaternion doorCloseRoatation = Quaternion.Euler (0, doorClosedAngle, 0);
transform.localRotation = Quaternion.Slerp (transform.localRotation, doorCloseRoatation, openDoorSmooth * Time.deltaTime);
}
public void ToggleSlidingDoor (bool doorOpen)
{
StartCoroutine (DoorSlide (doorOpen));
}
private IEnumerator DoorSlide(bool doorOpen)
{
float timer = 0.0f;
Vector3 startPosition = transform.position;
Vector3 endPosition = Vector3.zero;
if ( doorOpen )
{
endPosition = doorEndPosition;
}
else
{
endPosition = doorStartPosition;
}
while(timer < door$$anonymous$$oveDuration )
{
timer += Time.deltaTime;
float t = timer / door$$anonymous$$oveDuration;
transform.position = Vector3.Lerp (startPosition, endPosition, t);
yield return null;
}
yield return null;
}
}//end class
}//end namespace
Thank you and sorry!
Answer by shadowpuppet · Nov 15, 2017 at 04:46 PM
I like to avoid trying to make code for something so simple to visualize and get tangled in words and syntax. I would have just had the door in the open and shut states in the Animator and adjusted the blend to get the speed I want for the transition. That is , of course, your primary interest is having the door slide open and not trying to figure out how to do it in code
Answer by strudi1986 · Nov 15, 2017 at 05:06 PM
Hmm ok thank you! I thought to have this in code it is more flexible if i have doors in different sizes and so on. so i only need to change the value.
yeah, the same script for every door and changing the variables to get different speeds makes things easier - once you have that script, of course. To do that with my suggestion would mean a different animator controller for each door speed variation. ( same door speeds use same animator controller). may sound like more to do than it is. just copy the controller and rename it and change blend speed. But i get to where sometimes it isn't so much the door i want as to figure out a script to do it. But after failing for a few hours i realize it wasn't saving me any time at all over using 2 or 3 different controllers. But, like i said, sometimes the fun is trying to code something and sometimes it's just a bother if it can be achieved another way faster
Your answer
![](https://koobas.hobune.stream/wayback/20220612142907im_/https://answers.unity.com/themes/thub/images/avi.jpg)