Skip to content

Instantly share code, notes, and snippets.

@kalineh
Created March 9, 2016 23:21
Show Gist options
  • Save kalineh/61bf46625b329aabf05f to your computer and use it in GitHub Desktop.
Save kalineh/61bf46625b329aabf05f to your computer and use it in GitHub Desktop.
using UnityEngine;
using System.Collections;
using DG.Tweening;
public class ToolBallWhip
: ToolCore
{
private Rigidbody rigidBody;
private Vector3 prevPosition;
private Vector3 currPosition;
private float damage;
private bool mounted;
private bool docked;
private bool charging;
private bool recall;
private bool exploded;
private float recallAccumulator;
private float whipAccumulator;
private GameObject ball;
private Collider ballCollider;
private Rigidbody ballBody;
private Vector3 ballScale;
public override void OnScriptReload()
{
base.OnScriptReload();
rigidBody = GetComponent<Rigidbody>();
prevPosition = transform.position;
currPosition = transform.position;
var interactiveCore = GetComponent<InteractiveCore>();
interactiveCore.EventMountStart.AddListener(OnMountStart);
interactiveCore.EventMountTriggerStart.AddListener(OnMountTriggerStart);
interactiveCore.EventMountTriggerEnd.AddListener(OnMountTriggerEnd);
ball = transform.Find("Ball").gameObject;
ballBody = ball.GetComponent<Rigidbody>();
ballCollider = ball.GetComponent<Collider>();
ballScale = ball.transform.localScale;
}
public new void OnMountStart(PlayerInput input)
{
docked = true;
mounted = true;
ball.transform.SetParent(transform);
ballBody.isKinematic = true;
ballBody.position = transform.position;
ballBody.transform.position = transform.position;
}
public void OnMountTriggerStart(PlayerInput input)
{
mounted = true;
if (!docked)
BallRecall();
else
BallCharge();
}
public void OnMountTriggerEnd(PlayerInput input)
{
if (!mounted)
return;
// TODO: should not be getting trigger end after mount, until pressed first
if (!charging)
return;
BallThrow(input);
// TODO: use InertiaTracker (move to PlayerInput core, CalcInstantThrowVelocity())
var force = input.CalcInstantThrowVelocity();
ballBody.AddForce(force, ForceMode.Acceleration);
}
public void BallCharge()
{
ball.SetColorDebug(Color.green);
ball.transform.DOPunchScale(ballScale * 1.1f, 0.25f, 0, 0.0f);
charging = true;
}
public void BallWhip()
{
exploded = true;
ball.SetColorDebug(Color.green);
ball.transform.DOPunchScale(ballScale * 1.1f, 0.25f, 0, 0.0f);
DebugTextHelper.Instance.Print("EXPLODE", ballBody.position, 2.0f);
var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
var radius = 1.0f;
var material = Resources.Load<Material>("Debug/DebugRed50");
var renderer = sphere.GetComponent<Renderer>();
renderer.material = material;
sphere.name = "Explosion";
sphere.transform.position = ballBody.position;
sphere.transform.localScale = Vector3.zero;
sphere.transform.DOScale(radius * 2.0f, 0.15f).OnComplete(() => Destroy(sphere));
Physics.IgnoreCollision(ballCollider, sphere.GetComponent<Collider>());
var colliders = Physics.OverlapSphere(ballBody.position, radius);
var ballCombat = ball.GetComponent<Combat>();
var ballRigidbody = ball.GetComponent<Rigidbody>();
foreach (var collider in colliders)
{
var otherObj = collider.gameObject;
var otherCombat = otherObj.GetComponent<Combat>();
var otherRigidbody = otherObj.GetComponent<Rigidbody>();
if (otherRigidbody)
{
otherRigidbody.AddExplosionForce(1.0f, ballRigidbody.position, radius);
}
if (otherCombat)
{
var force = (otherRigidbody.position - ballRigidbody.position).normalized * 0.2f;
ballCombat.TryDoDamage(otherCombat, Combat.DamageType.Physical, 5, force);
}
}
var ofs = (transform.position - ballRigidbody.position);
var dir = ofs.normalized;
ballRigidbody.AddForce(dir * 10.0f / Time.deltaTime, ForceMode.Acceleration);
}
public void BallThrow(PlayerInput input)
{
docked = false;
charging = false;
exploded = false;
ball.SetColorDebug(Color.red);
ball.transform.DOScale(ballScale, 0.25f);
ballCollider.enabled = false;
ball.layer = LayerMask.NameToLayer("Tool");
ballBody.isKinematic = false;
ball.transform.SetParent(null);
recall = false;
StopCoroutine("DoBallThrow");
StartCoroutine("DoBallThrow", input);
}
public void BallRecall()
{
ball.SetColorDebug(Color.blue);
recall = true;
recallAccumulator = 0.0f;
}
public void BallCatch()
{
docked = true;
ball.SetColorDebug(Color.white);
ball.layer = 0;
ball.transform.SetParent(transform);
ballBody.isKinematic = true;
ballBody.position = transform.position;
ballBody.transform.position = transform.position;
}
private IEnumerator DoBallThrow(PlayerInput input)
{
yield return new WaitForSeconds(0.1f);
ballCollider.enabled = true;
while (!recall)
{
yield return null;
}
ballBody.velocity = Vector3.zero;
while (true)
{
var prev = ballBody.position;
ballBody.position = Vector3.MoveTowards(ballBody.position, input.transform.position, 5.0f * Time.deltaTime);
ballBody.position = Vector3.Lerp(ballBody.position, input.transform.position, 1.0f * Time.deltaTime);
ballBody.velocity = Vector3.zero;
var curr = ballBody.position;
var travelled = curr - prev;
recallAccumulator += travelled.magnitude;
var pulse = 0.5f;
if (recallAccumulator > pulse)
{
input.DoHapticPulsateShort(0.5f);
recallAccumulator -= pulse;
}
var distance = Vector3.Distance(ballBody.position, input.transform.position);
if (distance < 0.25f)
{
BallCatch();
yield break;
}
yield return null;
}
}
public void Update()
{
prevPosition = currPosition;
currPosition = rigidBody.position;
var movement = currPosition - prevPosition;
var force = movement.magnitude / Time.deltaTime;
var ignored = 1.0f;
force *= 0.75f;
force = Mathf.Clamp(force - ignored, 0.0f, 5.0f);
damage = Mathf.Lerp(damage, force, 0.1f);
if (mounted && !docked && !exploded)
{
var offset = ballBody.position - transform.position;
var direction = offset.normalized;
var distance = offset.magnitude;
var dot = Vector3.Dot(movement, direction) * -2.0f;
whipAccumulator += dot;
whipAccumulator = Mathf.Lerp(whipAccumulator, 0.0f, 15.0f * Time.deltaTime);
whipAccumulator = Mathf.Max(whipAccumulator, 0.0f);
if (distance < 0.75f)
whipAccumulator = 0.0f;
if (whipAccumulator > 0.35f)
{
whipAccumulator = 0.0f;
BallWhip();
BallRecall();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment