Calculating Door Hinge Pivots

I’m trying to move an empty game object to a hinge position on a door, so I can use it as the pivot point to swing the door open. The door script I’ve written has a setting which allows the player to open it in multiple different ways; slide it left / right / up / down, or swing it in / out on either the left or right hinge.

Initially I ran into problems trying to get the slide movements working correctly depending on the axis the door was aligned on, but I managed to work that one out. Now I’m having a few issues with the swing movements.

This method is executed in the Start() method of my door script:

public Transform Pivot { get; private set; }

/// <summary>
///     Creates an empty gameobject that can be used as the door's pivot point when swinging open / closed
/// </summary>
private void SetUpDoorPivot() {
	var doorPivot = new GameObject(string.Concat(name, "_pivot"));

	// Move the pivot object to the door's pivot point, depending on the swing type
	// By default, just set the pivot to the device's world location
	var pivotPosition = transform.position;

    // TODO: Calculate the bottom hinge position for each swing type
	switch (_doorTransitionType) {
		case TransitionType.SwingAwayLeftHinge:
			pivotPosition = renderer.bounds.min; // add depth
			break;
		case TransitionType.SwingAwayRightHinge:
			pivotPosition = renderer.bounds.max;
			break;
		case TransitionType.SwingTowardsLeftHinge:
			pivotPosition = renderer.bounds.min;
			break;
		case TransitionType.SwingTowardsRightHinge:
			pivotPosition = renderer.bounds.max; // add depth
			break;
	}

	doorPivot.transform.position = pivotPosition;

	// Assign the pivot object to the same parent as the door device
	doorPivot.transform.parent = transform.parent;
	// Set the door device's parent to the pivot object
	transform.parent = doorPivot.transform;
	// Save the pivot for later use
	Pivot = doorPivot.transform;
}

Everything works expected, except the hinges don’t sit in the right place on the door; I get spurious results depending on which axis the door is aligned on (X or Z), and which swing type I have set.

All of my doors are currently just cubes that have been resized - they have a considerable depth at the moment, in order to better see where the hinges are. Here are some quick screenshots (gizmos are displayed where the pivot object is):


I can’t upload any more pics, but you hopefully get the idea.

As you can see, I’m creating the pivot at runtime, and making it the parent of the door object. This all works fine - however, the final positioning performed in the switch statement is where I’m falling. I’m struggling to get my head around the bounds object - I’m not sure what each property refers to (I have experimented), and the unity documentation is a bit sparse on the subject.

At the moment, the SwingAwayRightHinge and SwingTowardsLeftHinge pivot is put in a valid location for doors that are aligned on the world X axis (though both pivots are not placed at the bottom of the object - which isn’t too much of a problem, as I’m rotating around the Y axis anyway), but not on any other axis. The other pivots are placed on the opposite hinge, meaning that the door clips into the rest of the scenery. This is what I’m trying to avoid, by calculating the relevant pivot point at runtime.

The main issue is that when I rotate the doors to another axis (see the door on the left in the above pic), the hinge positions change for each setting. I know what I have to do, but I’m having issues working out how I do it! Any help will most definitely be appreciated - even if you can provide me with some tutorials, white papers or blog posts on bounds and how to calculate vertices.

Hello, I recently also made a door. I used this simple script to make a door. It allows you to press F to open a door using a trigger. You can rotate it any way to make it suitable. Here is the script:
//Make an empty game object and call it “Door”
//Rename your 3D door model to “Body”
//Parent a “Body” object to “Door”
//Make sure thet a “Door” object is in left down corner of “Body” object. The place where a Door Hinge need be
//Add a box collider to “Door” object and make it much bigger then the “Body” model, mark it trigger
//Assign this script to a “Door” game object that have box collider with trigger enabled
//Press “f” to open the door and “g” to close the door
//Make sure the main character is tagged “player”

// Smothly open a door
var smooth = 2.0;
var DoorOpenAngle = 90.0;
var AudioFile : AudioClip;
private var open : boolean;
private var enter : boolean;

private var defaultRot : Vector3;
private var openRot : Vector3;

function Start(){
defaultRot = transform.eulerAngles;
openRot = new Vector3 (defaultRot.x, defaultRot.y + DoorOpenAngle, defaultRot.z);
}

//Main function
function Update (){
if(open){
//Open door
transform.eulerAngles = Vector3.Slerp(transform.eulerAngles, openRot, Time.deltaTime * smooth);
}else{
//Close door
transform.eulerAngles = Vector3.Slerp(transform.eulerAngles, defaultRot, Time.deltaTime * smooth);
}

if(Input.GetKeyDown("f") && enter){
open = !open;
}
}

function OnGUI(){
if(enter){
GUI.Label(new Rect(Screen.width/2 - 75, Screen.height - 100, 150, 30), "Press 'F' to open the door");
}
}

//Activate the Main function when player is near the door
function OnTriggerEnter (other : Collider){
if (other.gameObject.tag == "Player") {
enter = true;
}
}

//Deactivate the Main function when player is go away from door
function OnTriggerExit (other : Collider){
if (other.gameObject.tag == "Player") {
enter = false;
}
}
//@youtube.com/user/maksimum654321
//www.warmerise.com - check this game

Hope this helps!

Well, after much testing, and many experiments, I’ve managed to sort this out myself. I’ve had to use a combination of the door’s forward / right vectors, then multiply them by the mesh’s extents, and use the localScale to resize the mesh appropriately. Here’s the finished code, for anyone who might hit the same issue:

/// <summary>
///     Creates an empty gameobject that can be used as the door's pivot point when swinging open
/// </summary>
private void SetUpDoorPivot() {
	var doorPivot = new GameObject(string.Concat(name, "_pivot"));
	var gizmo = doorPivot.AddComponent<CircleGizmo>();
	gizmo.Size = .10f;
	gizmo.Color = new Color().RandomiseChannels();

	// Move the pivot object to the door's pivot point, depending on the swing type
	// By default, just set the pivot to the device's center
	var pivotPosition = collider.bounds.center;

	var mesh = GetComponent<MeshFilter>().mesh;
	var depth = transform.right * (mesh.bounds.extents.x * transform.localScale.x);
	var direction = transform.forward * (mesh.bounds.extents.z * transform.localScale.z);

	switch (_doorTransitionType) {
		case TransitionType.SwingAwayLeftHinge:
			pivotPosition -= (direction + depth);
			break;
		case TransitionType.SwingAwayRightHinge:
			pivotPosition += (direction - depth);
			break;
		case TransitionType.SwingTowardsLeftHinge:
			pivotPosition -= (direction - depth);
			break;
		case TransitionType.SwingTowardsRightHinge:
			pivotPosition += (direction + depth);
			break;
	}

	doorPivot.transform.localPosition = pivotPosition;

	// Assign the pivot object to the same parent as the door device
	doorPivot.transform.parent = transform.parent;
	// Set the door device's parent to the pivot object
	transform.parent = doorPivot.transform;
	// Save the pivot for later use
	Pivot = doorPivot.transform;
}