Skip to content

Commit

Permalink
feat(Climbing): add ability to use controllers to climb objects
Browse files Browse the repository at this point in the history
  • Loading branch information
mattboy64 committed Aug 7, 2016
1 parent 7e5fd6e commit 063e35b
Show file tree
Hide file tree
Showing 14 changed files with 16,219 additions and 38 deletions.
15,573 changes: 15,573 additions & 0 deletions Assets/SteamVR_Unity_Toolkit/Examples/037_CameraRig_ClimbingFalling.unity

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 80 additions & 20 deletions Assets/SteamVR_Unity_Toolkit/Scripts/VRTK_HeightAdjustTeleport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,65 @@ namespace VRTK
public class VRTK_HeightAdjustTeleport : VRTK_BasicTeleport
{
public bool playSpaceFalling = true;
public bool useGravity = true;
public float gravityFallHeight = 1.0f;
public float blinkYThreshold = 0.1f;

private float currentRayDownY = 0f;
private GameObject currentFloor = null;
private bool originalPlaySpaceFalling;
private bool isClimbing = false;

private VRTK_PlayerPresence playerPresence;

protected override void Start()
{
base.Start();
adjustYForTerrain = true;

originalPlaySpaceFalling = playSpaceFalling;

// Listen for climb events
var climbComponent = GetComponent<VRTK_PlayerClimb>();
if (climbComponent)
{
climbComponent.PlayerClimbStarted += new PlayerClimbEventHandler(OnClimbStarted);
climbComponent.PlayerClimbEnded += new PlayerClimbEventHandler(OnClimbEnded);
}

// Required Component: VRTK_PlayerPresence
playerPresence = GetComponent<VRTK_PlayerPresence>();
if (useGravity)
{
if (!playerPresence)
{
playerPresence = gameObject.AddComponent<VRTK_PlayerPresence>();
}

playerPresence.SetFallingPhysicsOnlyParams(true);
}
}

protected override void DoTeleport(object sender, DestinationMarkerEventArgs e)
{
base.DoTeleport(sender, e);
if (e.enableTeleport)
{
DropToNearestFloor(false);
DropToNearestFloor(false, false);
}
}

protected void OnClimbStarted(object sender, PlayerClimbEventArgs e)
{
isClimbing = true;
playSpaceFalling = false;
}

protected void OnClimbEnded(object sender, PlayerClimbEventArgs e)
{
isClimbing = false;
}

protected override Vector3 GetNewPosition(Vector3 tipPosition, Transform target)
{
Vector3 basePosition = base.GetNewPosition(tipPosition, target);
Expand Down Expand Up @@ -61,17 +101,12 @@ private bool CurrentFloorChanged(RaycastHit collidedObj)
return (currentFloor != collidedObj.transform.gameObject);
}

private bool MeshYChanged(RaycastHit collidedObj, float floorY)
{
return (collidedObj.transform.GetComponent<MeshCollider>() && floorY != currentRayDownY);
}

private bool FloorIsGrabbedObject(RaycastHit collidedObj)
{
return (collidedObj.transform.GetComponent<VRTK_InteractableObject>() && collidedObj.transform.GetComponent<VRTK_InteractableObject>().IsGrabbed());
}

private void DropToNearestFloor(bool withBlink)
private void DropToNearestFloor(bool withBlink, bool useGravityFall)
{
if (enableTeleport && eyeCamera.transform.position.y > transform.position.y)
{
Expand All @@ -81,36 +116,61 @@ private void DropToNearestFloor(bool withBlink)
bool rayHit = Physics.Raycast(ray, out rayCollidedWith);
float floorY = eyeCamera.transform.position.y - rayCollidedWith.distance;

if (rayHit && ValidLocation(rayCollidedWith.transform) && !FloorIsGrabbedObject(rayCollidedWith) && (MeshYChanged(rayCollidedWith, floorY) || CurrentFloorChanged(rayCollidedWith)))
if (rayHit && ValidLocation(rayCollidedWith.transform) && !FloorIsGrabbedObject(rayCollidedWith))
{
var floorDelta = currentRayDownY - floorY;
currentFloor = rayCollidedWith.transform.gameObject;
currentRayDownY = floorY;

if (withBlink && !rayCollidedWith.transform.GetComponent<MeshCollider>())
float fallDistance = transform.position.y - floorY;
bool shouldDoGravityFall = useGravityFall && (playerPresence.IsFalling() || fallDistance > gravityFallHeight);

if (withBlink && !shouldDoGravityFall && (floorDelta > blinkYThreshold || floorDelta < -blinkYThreshold))
{
Blink(blinkTransitionSpeed);
}

Vector3 newPosition = new Vector3(transform.position.x, floorY, transform.position.z);
var teleportArgs = new DestinationMarkerEventArgs
if (shouldDoGravityFall)
{
destinationPosition = newPosition,
distance = rayCollidedWith.distance,
enableTeleport = true,
target = currentFloor.transform
};
OnTeleporting(gameObject, teleportArgs);
SetNewPosition(newPosition, currentFloor.transform);
OnTeleported(gameObject, teleportArgs);
playerPresence.StartPhysicsFall(Vector3.zero);
}
else // teleport fall
{
Vector3 newPosition = new Vector3(transform.position.x, floorY, transform.position.z);
var teleportArgs = new DestinationMarkerEventArgs
{
destinationPosition = newPosition,
distance = rayCollidedWith.distance,
enableTeleport = true,
target = currentFloor.transform
};
OnTeleporting(gameObject, teleportArgs);
SetNewPosition(newPosition, currentFloor.transform);
OnTeleported(gameObject, teleportArgs);
}
}
}
}

private bool IsExternalSystemManipulatingPlaySpace()
{
return playerPresence.IsFalling() || isClimbing;
}

private void Update()
{
if (useGravity)
{
// if we aren't climbing or falling we can go back to height adjusted falling
if (!IsExternalSystemManipulatingPlaySpace())
{
playSpaceFalling = originalPlaySpaceFalling;
}
}

if (playSpaceFalling)
{
DropToNearestFloor(true);
DropToNearestFloor(true, useGravity);
}
}
}
Expand Down
29 changes: 29 additions & 0 deletions Assets/SteamVR_Unity_Toolkit/Scripts/VRTK_InteractGrab.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,19 @@ private bool GrabTrackedObject()
return false;
}

private bool GrabClimbObject()
{
if (grabbedObject == null && IsObjectGrabbable(interactTouch.GetTouchedObject()))
{
InitGrabbedObject();
if (grabbedObject)
{
return true;
}
}
return false;
}

private void InitGrabbedObject()
{
grabbedObject = interactTouch.GetTouchedObject();
Expand Down Expand Up @@ -367,6 +380,14 @@ private void UngrabTrackedObject()
}
}

private void UngrabClimbObject()
{
if (grabbedObject != null)
{
InitUngrabbedObject();
}
}

private void InitUngrabbedObject()
{
OnControllerUngrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject));
Expand Down Expand Up @@ -420,6 +441,10 @@ private void AttemptGrabObject()
{
initialGrabAttempt = GrabTrackedObject();
}
else if (objectToGrab.GetComponent<VRTK_InteractableObject>().AttachIsClimbObject())
{
initialGrabAttempt = GrabClimbObject();
}
else
{
initialGrabAttempt = GrabInteractedObject();
Expand Down Expand Up @@ -457,6 +482,10 @@ private void AttemptReleaseObject(uint controllerIndex)
{
UngrabTrackedObject();
}
else if (grabbedObject.GetComponent<VRTK_InteractableObject>().AttachIsClimbObject())
{
UngrabClimbObject();
}
else
{
ReleaseObject(controllerIndex, true);
Expand Down
23 changes: 19 additions & 4 deletions Assets/SteamVR_Unity_Toolkit/Scripts/VRTK_InteractTouch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class VRTK_InteractTouch : MonoBehaviour
public float hideControllerDelay = 0f;
public Color globalTouchHighlightColor = Color.clear;
public GameObject customRigidbodyObject;
public bool triggerOnStaticObjects = false;

public event ObjectInteractEventHandler ControllerTouchInteractableObject;
public event ObjectInteractEventHandler ControllerUntouchInteractableObject;
Expand Down Expand Up @@ -131,6 +132,7 @@ private void Start()

Utilities.SetPlayerObject(gameObject, VRTK_PlayerObject.ObjectTypes.Controller);
CreateTouchCollider(gameObject);
CreateTouchRigidBody(gameObject);
CreateControllerRigidBody();
triggerRumble = false;
}
Expand Down Expand Up @@ -267,6 +269,22 @@ private void CreateBoxCollider(GameObject obj, Vector3 center, Vector3 size)
bc.center = center;
}

private void CreateTouchRigidBody(GameObject obj)
{
// Need a Rigidbody to interact with static objects
if (triggerOnStaticObjects)
{
Rigidbody rb = obj.GetComponent<Rigidbody>();
if (rb==null)
{
rb = obj.AddComponent<Rigidbody>();
}

rb.isKinematic = true;
rb.useGravity = false;
}
}

private void HideController()
{
if (touchedObject != null)
Expand All @@ -283,10 +301,7 @@ private void CreateControllerRigidBody()
}
else
{
controllerRigidBodyObject = new GameObject(string.Format("[{0}]_RigidBody_Holder", gameObject.name));
controllerRigidBodyObject.transform.parent = transform;
controllerRigidBodyObject.transform.localPosition = Vector3.zero;

controllerRigidBodyObject = new GameObject();
CreateBoxCollider(controllerRigidBodyObject, new Vector3(0f, -0.01f, -0.098f), new Vector3(0.04f, 0.025f, 0.15f));
CreateBoxCollider(controllerRigidBodyObject, new Vector3(0f, -0.009f, -0.002f), new Vector3(0.05f, 0.025f, 0.04f));
CreateBoxCollider(controllerRigidBodyObject, new Vector3(0f, -0.024f, 0.01f), new Vector3(0.07f, 0.02f, 0.02f));
Expand Down
42 changes: 33 additions & 9 deletions Assets/SteamVR_Unity_Toolkit/Scripts/VRTK_InteractableObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public enum GrabAttachType
Spring_Joint,
Track_Object,
Rotator_Track,
Child_Of_Controller
Child_Of_Controller,
Climbable
}

public enum AllowedController
Expand Down Expand Up @@ -311,6 +312,16 @@ public bool AttachIsTrackObject()
return (grabAttachMechanic == GrabAttachType.Track_Object || grabAttachMechanic == GrabAttachType.Rotator_Track);
}

public bool AttachIsClimbObject()
{
return (grabAttachMechanic == GrabAttachType.Climbable);
}

public bool AttachIsStaticObject()
{
return AttachIsClimbObject(); // only one at the moment
}

public void ZeroVelocity()
{
if (GetComponent<Rigidbody>())
Expand All @@ -325,13 +336,20 @@ public void SaveCurrentState()
if (grabbingObject == null)
{
previousParent = transform.parent;
previousKinematicState = rb.isKinematic;

if (rb)
{
previousKinematicState = rb.isKinematic;
}
}
}

public void ToggleKinematic(bool state)
{
rb.isKinematic = state;
if (rb)
{
rb.isKinematic = state;
}
}

public GameObject GetGrabbingObject()
Expand Down Expand Up @@ -390,13 +408,16 @@ protected virtual void Awake()
{
rb = GetComponent<Rigidbody>();

// If there is no rigid body, add one and set it to 'kinematic'.
if (!rb)
if (!AttachIsStaticObject())
{
rb = gameObject.AddComponent<Rigidbody>();
rb.isKinematic = true;
// If there is no rigid body, add one and set it to 'kinematic'.
if (!rb)
{
rb = gameObject.AddComponent<Rigidbody>();
rb.isKinematic = true;
}
rb.maxAngularVelocity = float.MaxValue;
}
rb.maxAngularVelocity = float.MaxValue;
forcedDropped = false;
}

Expand Down Expand Up @@ -460,7 +481,10 @@ protected virtual void LoadPreviousState()
transform.parent = previousParent;
forcedDropped = false;
}
rb.isKinematic = previousKinematicState;
if (rb)
{
rb.isKinematic = previousKinematicState;
}
if (!isSwappable)
{
isGrabbable = previousIsGrabbable;
Expand Down
Loading

0 comments on commit 063e35b

Please sign in to comment.