Skip to content

Instantly share code, notes, and snippets.

@lane-s
Last active January 22, 2018 22:02
Show Gist options
  • Save lane-s/8e5de3d45d1b931b9891b9ff4d092f2c to your computer and use it in GitHub Desktop.
Save lane-s/8e5de3d45d1b931b9891b9ff4d092f2c to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using VRTK;
using VRTK.GrabAttachMechanics;
[RequireComponent(typeof(VRTK_InteractableObject))]
[RequireComponent(typeof(SphereCollider))]
[RequireComponent(typeof(CatchableBody))]
public class UtilityBall : MonoBehaviour {
public enum State{OnBelt, Grabbed, Released, Deploying, Deployed, Activating, Activated}
public bool playerHasBall;
public Transform beltAnchor;
public Transform hip;
public float actionHoldTime; //The time the trigger must be held down before the ball activates
public float invisibleColliderRadius;
public float onBeltColliderRadius;
public float trailTime = 0.45f;
public VRTK_ControllerEvents controllerEvents;
public event EventHandler UtilityBallBeginDeploy;
public event EventHandler UtilityBallDeployed;
public event EventHandler UtilityBallBeginActivate;
public event EventHandler UtilityBallActivationCancelled;
public event EventHandler UtilityBallAttemptActivate;
public event EventHandler UtilityBallDeactivated;
public event EventHandler UtilityBallRecalled;
private State state;
private float originalRadius;
private float triggerTime = 0;
private bool triggerDown = false;
private Transform catcher;
void Awake(){
state = State.OnBelt;
playerHasBall = false;
}
void Start () {
GetComponent<VRTK_InteractableObject> ().InteractableObjectGrabbed += OnGrabbed;
GetComponent<VRTK_InteractableObject> ().InteractableObjectUngrabbed += OnReleased;
controllerEvents.ButtonOnePressed += OnButtonOnePressed;
controllerEvents.TriggerPressed += OnTriggerPressed;
controllerEvents.TriggerReleased += OnTriggerReleased;
originalRadius = GetComponent<SphereCollider> ().radius;
GetComponent<SphereCollider> ().isTrigger = true;
GetComponent<CatchableBody> ().Catch += OnCatch;
GetComponent<CatchableBody> ().Released += OnCatcherReleased;
}
// Update is called once per frame
void Update () {
GetComponent<SphereCollider> ().radius = originalRadius;
if (playerHasBall) {
if (state.Equals (State.OnBelt)) {
transform.position = beltAnchor.position;
//Increase collider radius when ball is on belt and not visible
if (!GetComponent<MeshRenderer> ().isVisible) {
GetComponent<SphereCollider> ().radius = invisibleColliderRadius;
} else {
GetComponent<SphereCollider> ().radius = onBeltColliderRadius;
}
}else if (state.Equals (State.Grabbed)) {
transform.localPosition = Vector3.zero;
}else if (state.Equals (State.Deployed)) {
if (catcher != null && transform.parent == null) {
transform.parent = catcher.parent;
}
triggerTime += Time.deltaTime;
if (triggerDown && triggerTime > 0.1f) {
triggerTime = 0;
state = State.Activating;
if (UtilityBallBeginActivate != null)
UtilityBallBeginActivate (this, new EventArgs ());
}
} else if (state.Equals (State.Activating)) {
if (triggerDown) {
triggerTime += Time.deltaTime;
} else {
if (UtilityBallActivationCancelled != null) {
UtilityBallActivationCancelled (this, new EventArgs ());
}
state = State.Deployed;
}
if (triggerTime >= actionHoldTime) {
if (UtilityBallAttemptActivate != null) {
UtilityBallAttemptActivate (this, new EventArgs ());
}
}
}
}
}
void FixedUpdate(){
if (playerHasBall) {
if (state.Equals (State.OnBelt)) {
transform.position = beltAnchor.position;
GetComponent<Rigidbody> ().position = beltAnchor.position;
} else if (state.Equals (State.Grabbed)) {
transform.localPosition = Vector3.zero;
GetComponent<Rigidbody> ().position = GetComponent<VRTK_ChildOfControllerGrabAttach> ().controllerAttachPoint.position;
}
}
}
public void Release(){
transform.SetParent (null);
GetComponent<Rigidbody> ().isKinematic = false;
GetComponent<SphereCollider> ().isTrigger = false;
state = State.Released;
}
public void Deploy(){
triggerTime = 0;
state = State.Deployed;
GetComponent<Rigidbody> ().interpolation = RigidbodyInterpolation.None;
if (UtilityBallDeployed != null) {
UtilityBallDeployed(this, new EventArgs());
}
}
public void Activate(){
state = State.Activated;
}
public void Recall(bool force){
if (force || state.Equals(State.Released) ||
state.Equals(State.Deploying) ||
state.Equals(State.Deployed) ||
state.Equals(State.Activating)) {
//Set ball position to its position on the utlity belt
transform.position = beltAnchor.position;
//Attach the ball to the player's hip
transform.SetParent (hip);
//Disable physics for the ball
GetComponent<Rigidbody> ().isKinematic = true;
state = State.OnBelt;
GetComponent<Rigidbody> ().interpolation = RigidbodyInterpolation.None;
if (catcher != null) {
catcher.GetComponent<Catcher> ().ForceRelease (transform);
}
foreach (ParticleSystem p in GetComponentsInChildren<ParticleSystem>()) {
p.Clear ();
p.Stop ();
}
//Force release if grabbed
if (GetComponent<VRTK_InteractableObject> ().IsGrabbed ()) {
GetComponent<VRTK_InteractableObject> ().GetGrabbingObject ().GetComponent<VRTK_InteractGrab> ().ForceRelease ();
}
if (UtilityBallRecalled != null) {
UtilityBallRecalled (this, new EventArgs());
}
}
}
public void Recall(){
Recall (false);
}
public void GivePlayerOwnership(){
playerHasBall = true;
state = State.OnBelt;
}
void OnTriggerPressed(object sender, ControllerInteractionEventArgs args){
triggerDown = true;
if (playerHasBall) {
if (state.Equals (State.Released)) {
state = State.Deploying;
if (UtilityBallBeginDeploy != null)
UtilityBallBeginDeploy (this, new EventArgs ());
}
}
}
void OnTriggerReleased(object sender, ControllerInteractionEventArgs args){
triggerDown = false;
if (state.Equals(State.Activated)) {
state = State.Deployed;
if (UtilityBallDeactivated != null) {
UtilityBallDeactivated (this, new EventArgs ());
}
}
}
void OnGrabbed(object sender, InteractableObjectEventArgs args){
state = State.Grabbed;
playerHasBall = true;
}
void OnReleased(object sender, InteractableObjectEventArgs args){
//Only release if first grabbed from the belt
if (state != State.OnBelt) {
Release ();
}
}
void OnCatch(object sender, CatchEventArgs args){
catcher = args.catcher;
}
void OnCatcherReleased(object sender, CatchEventArgs args){
catcher = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment