Last active
January 22, 2018 22:02
-
-
Save lane-s/8e5de3d45d1b931b9891b9ff4d092f2c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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