- Home /
Door opening - Vector.slerp is really glitchy
I have a script so that when I attach it on a door, it adds a hinge to the door (empty gameobject), and it makes the hinge the parent of the door, so when I rotate the hinge, the door rotates like a door instead of spinning around.
In the script I made it so that you can set if on start the door is opened or closed, and you can set the values (in degrees) for the closedangle and the openedangle. When I run it it has a starting rotation (you can set this value in inspector) and a new rotation (you can set this value in inspector). So far everything is good, but when I try to smoothly move the door from start rotation to new rotation it is really weird and the door starts shaking.
SCRIPT:
using UnityEngine;
using System.Collections;
public class DoorScript : MonoBehaviour {
GameObject hinge; //Create a hinge for the door
//Dropdown-menu for default door state
public enum DefaultDoorState
{
Closed,
Open
}
public DefaultDoorState DoorState;
//Dropdown-menu for hinge position
public enum DoorHingePosition
{
Left,
Right
}
public DoorHingePosition HingePosition;
public float DoorOpenAngle = 90.0F;
public float DoorClosedAngle = 0.0F;
public float smooth = 2.0F;
private Vector3 StartRot;
private Vector3 NewRot;
void Start () {
hinge = new GameObject();
hinge.name = "hinge";
//Set the position of the hinge to be exactly left down under of EVERY door
if (HingePosition == DoorHingePosition.Left)
{
float PosDoorX = transform.position.x;
float PosDoorY = transform.position.y;
float PosDoorZ = transform.position.z;
float ScaleDoorX = transform.localScale.x;
float ScaleDoorY = transform.localScale.y;
Vector3 HingePosCopy = hinge.transform.position; //Make a copy of the the position of the hinge so we can modify it
HingePosCopy.x = PosDoorX - ScaleDoorX / 2;
HingePosCopy.y = PosDoorY - ScaleDoorY / 2;
HingePosCopy.z = PosDoorZ;
hinge.transform.position = HingePosCopy;
}
//Set the position of the hinge to be exactly right down under of EVERY door
if (HingePosition == DoorHingePosition.Right)
{
//Set the position of the hinge to be exactly left down under of EVERY door
float PosDoorX = transform.position.x;
float PosDoorY = transform.position.y;
float PosDoorZ = transform.position.z;
float ScaleDoorX = transform.localScale.x;
float ScaleDoorY = transform.localScale.y;
Vector3 HingePosCopy = hinge.transform.position; //Make a copy of the the position of the hinge so we can modify it
HingePosCopy.x = PosDoorX + ScaleDoorX / 2;
HingePosCopy.y = PosDoorY - ScaleDoorY / 2;
HingePosCopy.z = PosDoorZ;
hinge.transform.position = HingePosCopy;
}
transform.parent = hinge.transform; //Set the hinge to be the parent of the door (change the door's origin/pivot point)
//If the default state Closed is
if (DoorState == DefaultDoorState.Closed)
{
if(HingePosition == DoorHingePosition.Left)
{
hinge.transform.eulerAngles = new Vector3(0F, DoorClosedAngle, 0F);
StartRot = hinge.transform.eulerAngles;
NewRot = new Vector3(0F, DoorOpenAngle, 0F);
}
if(HingePosition == DoorHingePosition.Right)
{
hinge.transform.eulerAngles = new Vector3(0F, DoorClosedAngle, 0F);
StartRot = hinge.transform.eulerAngles;
NewRot = new Vector3(0F, DoorOpenAngle, 0F);
}
}
//If the default state Open is
if (DoorState == DefaultDoorState.Open)
{
if(HingePosition == DoorHingePosition.Left)
{
hinge.transform.eulerAngles = new Vector3(0F, DoorOpenAngle, 0F);
StartRot = hinge.transform.eulerAngles;
NewRot = new Vector3(0F, DoorClosedAngle, 0F);
}
if(HingePosition == DoorHingePosition.Right)
{
hinge.transform.eulerAngles = new Vector3(0F, DoorOpenAngle, 0F);
StartRot = hinge.transform.eulerAngles;
NewRot = new Vector3(0F, DoorClosedAngle, 0F);
}
}
}
void Update ()
{
print ("Default" + StartRot);
print ("New" + NewRot);
hinge.transform.eulerAngles = Vector3.Slerp(StartRot, NewRot, Time.deltaTime * smooth);
}
}
Thank you very much!!!!! The script is a bit long, but you don't have to look at the part where I set the hinge's position
Why not doing it with animation system? $$anonymous$$uch simpler.
S$$anonymous$$lth game tutorial - 303 - Single Door & Animation - Unity Official Tutorials
The problem with that is that it is not applyable to every door, I want the script to be simply drag-and-drop on any possible door, and that it will work :)
Answer by NoseKills · Dec 28, 2014 at 01:34 PM
Using Slerp or Lerp wrong is one of the most common problems on Answers, although how they work is explained quite clearly in the API docs. The 3rd parameter is basically a percentage of how close to the target value you want the returned, Slerped value to be.
So in Update() you are setting the door's rotation to something between StartRot
and NewRot
. You are setting it to value Time.deltaTime * smooth
. You have set smooth
as 2, and Time.deltaTime could be something like 0.05f
and changes every time depending on your frame rate. That gives you a 0.10f- 0.20f as the 3rd parameter so every Update you set the angle of the door to be about 10 - 20 percent of the way between StartRot
and NewRot
. The shaking you are seeing is because Time.deltaTime changes every frame, so the door could be 30% closed one frame and 10% closed the next one.
You need to change the 3rd parameter so it goes from 0 to 1 (open to closed, 0% to 100%) over the time you want. Something like:
float doorPrc = 0;
void Update ()
{
print ("Default" + StartRot);
print ("New" + NewRot);
doorPrc += Time.deltaTime * smooth;
hinge.transform.eulerAngles = Vector3.Slerp(StartRot, NewRot, doorPrc );
}
Ok so I tried this but I have two questions/comments:
1) what does the '+=' operator do? 2) when I run it, the door goes to the 'NewRot', but then goes back again, why is this?
Tyvm!
Oh never$$anonymous$$d about 2), it works, but still don't know what '+=' does :D
is a operator that does the same as adding something to the variable and storing the result back to that variable.
So x = x +3 is the same as x+=3. Just a shorter way of writing it.
Read it as "increase by".