You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
340 lines
14 KiB
C#
340 lines
14 KiB
C#
|
3 years ago
|
using System.Collections;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.Events;
|
||
|
|
using MalbersAnimations.Events;
|
||
|
|
using MalbersAnimations.Scriptables;
|
||
|
|
using MalbersAnimations.Controller;
|
||
|
|
using UnityEngine;
|
||
|
|
using System.Collections;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Linq;
|
||
|
|
using MalbersAnimations.Scriptables;
|
||
|
|
using UnityEngine.Events;
|
||
|
|
|
||
|
|
public class Grapple : MonoBehaviour
|
||
|
|
{
|
||
|
|
public MalbersAnimations.Controller.MAnimal Player;
|
||
|
|
public GameObject Camera;
|
||
|
|
public GameObject AttachmentPrefab;
|
||
|
|
public GameObject ropeSegment;
|
||
|
|
private GameObject attachment;
|
||
|
|
private Vector3 attachedPoint;
|
||
|
|
private Rigidbody attachedObject;
|
||
|
|
private MalbersAnimations.Controller.MAnimal attachedCharacter;
|
||
|
|
public float RopeSegmentLength;
|
||
|
|
public bool isAttached;
|
||
|
|
public float minDistance = 1.0f;
|
||
|
|
public float maxDistance = 30.0f;
|
||
|
|
public float pullForce = 20.0f;
|
||
|
|
public float MaxPullForce = 25.0f;
|
||
|
|
public float PushForce = 30.0f;
|
||
|
|
public float pullAccel = 20.0f;
|
||
|
|
public float playerWidth = 0.5f;
|
||
|
|
public float playerHeight = 1.6f;
|
||
|
|
public float playerHeightBuffer = 0.5f;
|
||
|
|
public float breakChainTime = 0.5f;
|
||
|
|
public float breakChainDistance = 0.5f;
|
||
|
|
public float defaultRopeSegmentOrientation = 90.0f;
|
||
|
|
private GameObject chain;
|
||
|
|
private bool limitingPosition;
|
||
|
|
private bool hasPullChainInputSequenceStarted;
|
||
|
|
private bool inputPaused;
|
||
|
|
private float pullChainInputTiming = 0.5f;
|
||
|
|
private float inputPauseTiming = 1.0f;
|
||
|
|
private float timer = 0.0f;
|
||
|
|
private bool grappling;
|
||
|
|
|
||
|
|
bool CheckInputDepressedThisFrame()
|
||
|
|
{
|
||
|
|
if (grappling)
|
||
|
|
{
|
||
|
|
grappling = false;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return Input.GetAxis("Fire1") > 0.0f;
|
||
|
|
}
|
||
|
|
|
||
|
|
public virtual void StartGrapple()
|
||
|
|
{
|
||
|
|
grappling = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Start is called before the first frame update
|
||
|
|
void Start()
|
||
|
|
{
|
||
|
|
chain = new GameObject("Chain");
|
||
|
|
chain.AddComponent<LineRenderer>();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update is called once per frame
|
||
|
|
void Update()
|
||
|
|
{
|
||
|
|
timer += Time.deltaTime;
|
||
|
|
|
||
|
|
if (inputPaused)
|
||
|
|
{
|
||
|
|
if (timer < inputPauseTiming)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
inputPaused = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var cameraTransform = Camera.transform;
|
||
|
|
if (attachment != null)
|
||
|
|
{
|
||
|
|
attachedPoint = attachment.transform.position;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (Vector3.Distance(Player.transform.position, attachedPoint) > maxDistance)
|
||
|
|
{
|
||
|
|
//check if time limit has passed for being beyond distance limit without breaking
|
||
|
|
}
|
||
|
|
|
||
|
|
if (Vector3.Distance(Player.transform.position, attachedPoint) > maxDistance + breakChainDistance)
|
||
|
|
{
|
||
|
|
if (attachment != null)
|
||
|
|
{
|
||
|
|
GameObject.Destroy(attachment);
|
||
|
|
var lineRenderer = chain.GetComponent<LineRenderer>();
|
||
|
|
lineRenderer.SetWidth(0, 0);
|
||
|
|
}
|
||
|
|
if (ropeSegment != null)
|
||
|
|
{
|
||
|
|
GameObject.Destroy(ropeSegment);
|
||
|
|
}
|
||
|
|
isAttached = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isAttached)
|
||
|
|
{
|
||
|
|
|
||
|
|
// limit the position of both sides of the chain to the length of the chain
|
||
|
|
// // //
|
||
|
|
// //
|
||
|
|
if (Vector3.Distance(Player.transform.position, attachedPoint) > maxDistance)
|
||
|
|
{
|
||
|
|
var forceHeading = attachedPoint - cameraTransform.position;
|
||
|
|
var forceDirection = forceHeading / forceHeading.magnitude;
|
||
|
|
|
||
|
|
if (Player.GetComponent<Rigidbody>().velocity.x > MaxPullForce
|
||
|
|
|| Player.GetComponent<Rigidbody>().velocity.x < -MaxPullForce
|
||
|
|
|| Player.GetComponent<Rigidbody>().velocity.y > MaxPullForce
|
||
|
|
|| Player.GetComponent<Rigidbody>().velocity.y < -MaxPullForce)
|
||
|
|
{
|
||
|
|
Player.Force_Add(forceDirection, Vector3.Distance(Player.transform.position, attachedPoint), pullForce * 0.05f, false );
|
||
|
|
}
|
||
|
|
if (attachedObject != null && attachedObject.velocity != null && attachedObject.velocity.x > MaxPullForce
|
||
|
|
|| attachedObject.velocity.x < -MaxPullForce
|
||
|
|
|| attachedObject.velocity.y > MaxPullForce
|
||
|
|
|| attachedObject.velocity.y < -MaxPullForce)
|
||
|
|
{
|
||
|
|
attachedObject.AddForce(-forceDirection * Vector3.Distance(Player.transform.position, attachedPoint) * pullForce * 0.05f);
|
||
|
|
}
|
||
|
|
if (attachedCharacter != null && attachedCharacter.GetComponent<Rigidbody>().velocity.x > MaxPullForce
|
||
|
|
|| attachedCharacter.GetComponentInParent<Rigidbody>().velocity.x < -MaxPullForce
|
||
|
|
|| attachedCharacter.GetComponentInParent<Rigidbody>().velocity.y > MaxPullForce
|
||
|
|
|| attachedCharacter.GetComponentInParent<Rigidbody>().velocity.y < -MaxPullForce)
|
||
|
|
{
|
||
|
|
attachedCharacter.Force_Add(-forceDirection, Vector3.Distance(Player.transform.position, attachedPoint), pullForce * 0.05f, false );
|
||
|
|
}
|
||
|
|
limitingPosition = true;
|
||
|
|
}
|
||
|
|
if (limitingPosition && Vector3.Distance(Player.transform.position, attachedPoint) < maxDistance)
|
||
|
|
{
|
||
|
|
Debug.Log("Removing force");
|
||
|
|
Player.Force_Remove();
|
||
|
|
if (attachedObject != null)
|
||
|
|
{
|
||
|
|
attachedObject.velocity = new Vector3(0.0f, 0.0f, 0.0f);
|
||
|
|
}
|
||
|
|
if (attachedCharacter != null)
|
||
|
|
{
|
||
|
|
attachedCharacter.Force_Remove();
|
||
|
|
}
|
||
|
|
limitingPosition = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
var lineRenderer = chain.GetComponent<LineRenderer>();
|
||
|
|
lineRenderer.SetColors (Color.blue, Color.blue);
|
||
|
|
lineRenderer.material = new Material(Shader.Find("Legacy Shaders/Particles/Additive"));
|
||
|
|
lineRenderer.SetWidth(1f, 1f);
|
||
|
|
lineRenderer.SetPosition(0, Player.transform.position);
|
||
|
|
lineRenderer.SetPosition(1, attachedPoint);
|
||
|
|
|
||
|
|
// Position
|
||
|
|
if (ropeSegment != null)
|
||
|
|
{
|
||
|
|
ropeSegment.transform.position = (attachedPoint + cameraTransform.position) / 2.0f;
|
||
|
|
|
||
|
|
// Rotation
|
||
|
|
var heading = attachedPoint - cameraTransform.position;
|
||
|
|
var direction = heading / heading.magnitude;
|
||
|
|
|
||
|
|
ropeSegment.transform.rotation = new Quaternion(direction.x, direction.y, direction.z + defaultRopeSegmentOrientation, 0);
|
||
|
|
|
||
|
|
// Scale
|
||
|
|
var distance = Vector3.Distance(attachedPoint, Player.transform.position);
|
||
|
|
|
||
|
|
ropeSegment.transform.localScale = new Vector3(0.1f, distance / 2, 0.1f);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (hasPullChainInputSequenceStarted && timer > pullChainInputTiming)
|
||
|
|
{
|
||
|
|
Debug.Log("Detaching");
|
||
|
|
isAttached = false;
|
||
|
|
inputPaused = true;
|
||
|
|
timer = 0.0f;
|
||
|
|
hasPullChainInputSequenceStarted = false;
|
||
|
|
attachedObject = null;
|
||
|
|
attachedCharacter = null;
|
||
|
|
attachment.transform.parent = null;
|
||
|
|
GameObject.Destroy(ropeSegment);
|
||
|
|
GameObject.Destroy(attachment);
|
||
|
|
return;
|
||
|
|
lineRenderer.SetWidth(0, 0);
|
||
|
|
}
|
||
|
|
else if (hasPullChainInputSequenceStarted && CheckInputDepressedThisFrame())
|
||
|
|
{
|
||
|
|
Debug.Log("Pulling");
|
||
|
|
// This is the preferred way of calculating direction between two Vectors
|
||
|
|
// other ways might cause performance issues
|
||
|
|
// See here: https://docs.unity3d.com/2018.3/Documentation/Manual/DirectionDistanceFromOneObjectToAnother.html
|
||
|
|
// TODO: look into syntax/performance impact for (vector.position - vector.position).normalized
|
||
|
|
var forceHeading = attachedPoint - cameraTransform.position;
|
||
|
|
var forceDirection = forceHeading / forceHeading.magnitude;
|
||
|
|
|
||
|
|
var applyToSelf = true;
|
||
|
|
|
||
|
|
if (attachedObject != null)
|
||
|
|
{
|
||
|
|
attachedObject.AddForce(-forceDirection * pullForce);
|
||
|
|
applyToSelf = false;
|
||
|
|
}
|
||
|
|
if (attachedCharacter != null)
|
||
|
|
{
|
||
|
|
attachedCharacter.Force_Add(-forceDirection, pullForce, pullAccel, false );
|
||
|
|
applyToSelf = false;
|
||
|
|
}
|
||
|
|
if (applyToSelf)
|
||
|
|
{
|
||
|
|
Player.Force_Add(forceDirection, pullForce, pullAccel, false );
|
||
|
|
}
|
||
|
|
attachedPoint = new Vector3(0, 0, 0);
|
||
|
|
inputPaused = true;
|
||
|
|
timer = 0.0f;
|
||
|
|
hasPullChainInputSequenceStarted = false;
|
||
|
|
}
|
||
|
|
else if (!hasPullChainInputSequenceStarted && !CheckInputDepressedThisFrame())
|
||
|
|
{
|
||
|
|
Debug.Log("Starting Dettachment");
|
||
|
|
hasPullChainInputSequenceStarted = true;
|
||
|
|
timer = 0.0f;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (attachment != null)
|
||
|
|
{
|
||
|
|
if (attachment.GetComponent<GrappleAttachment>().CollisionStuck)
|
||
|
|
{
|
||
|
|
// attachment.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.FreezeAll;
|
||
|
|
inputPaused = false;
|
||
|
|
isAttached = true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// attachment.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None;
|
||
|
|
}
|
||
|
|
if (Vector3.Distance(Player.transform.position, transform.position) > Player.GetComponent<Grapple>().maxDistance)
|
||
|
|
{
|
||
|
|
timer = 0.0f;
|
||
|
|
GameObject.Destroy(attachment);
|
||
|
|
inputPaused = false;
|
||
|
|
isAttached = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
var lineRenderer = chain.GetComponent<LineRenderer>();
|
||
|
|
if (CheckInputDepressedThisFrame())
|
||
|
|
{
|
||
|
|
var raycastStart = cameraTransform.position + transform.forward * minDistance;
|
||
|
|
if (Physics.Raycast(raycastStart, cameraTransform.forward, out RaycastHit raycastHit))
|
||
|
|
{
|
||
|
|
if (Vector3.Distance(Player.transform.position, raycastHit.point) < maxDistance)
|
||
|
|
{
|
||
|
|
Debug.Log("Attaching");
|
||
|
|
attachedPoint = raycastHit.point;
|
||
|
|
isAttached = true;
|
||
|
|
inputPaused = true;
|
||
|
|
timer = 0.0f;
|
||
|
|
hasPullChainInputSequenceStarted = false;
|
||
|
|
if (raycastHit.transform != null && raycastHit.transform.gameObject != null)
|
||
|
|
{
|
||
|
|
if (raycastHit.transform.gameObject.GetComponent<Rigidbody>() != null)
|
||
|
|
{
|
||
|
|
attachedObject = raycastHit.transform.gameObject.GetComponent<Rigidbody>();
|
||
|
|
}
|
||
|
|
else if (raycastHit.transform.gameObject.GetComponentInChildren<Rigidbody>() != null)
|
||
|
|
{
|
||
|
|
attachedObject = raycastHit.transform.gameObject.GetComponentInChildren<Rigidbody>();
|
||
|
|
}
|
||
|
|
if (raycastHit.transform.gameObject.GetComponent<MalbersAnimations.Controller.MAnimal>() != null)
|
||
|
|
{
|
||
|
|
attachedCharacter = raycastHit.transform.gameObject.GetComponent<MalbersAnimations.Controller.MAnimal>();
|
||
|
|
}
|
||
|
|
if (raycastHit.transform.gameObject.GetComponentInChildren<MalbersAnimations.Controller.MAnimal>() != null)
|
||
|
|
{
|
||
|
|
attachedCharacter = raycastHit.transform.gameObject.GetComponentInChildren<MalbersAnimations.Controller.MAnimal>();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (attachment == null)
|
||
|
|
{
|
||
|
|
attachment = Instantiate(AttachmentPrefab);
|
||
|
|
}
|
||
|
|
|
||
|
|
timer = 0.0f;
|
||
|
|
inputPaused = true;
|
||
|
|
hasPullChainInputSequenceStarted = false;
|
||
|
|
|
||
|
|
attachment.transform.localScale = new Vector3(6.25f, 6.25f, 18.75f);
|
||
|
|
var heading = attachedPoint - cameraTransform.position;
|
||
|
|
var direction = heading / heading.magnitude;
|
||
|
|
attachment.transform.position = Player.transform.position + Quaternion.AngleAxis(direction.x, Vector3.right) * transform.forward * 1;
|
||
|
|
// attachment.transform.position = new Vector3(Player.transform.position.x, Player.transform.position.y + playerHeight + playerHeightBuffer, Player.transform.position.z + playerWidth * 2);
|
||
|
|
attachment.GetComponent<Rigidbody>().AddForce(direction * PushForce);
|
||
|
|
// attachment.GetComponent<Rigidbody>().AddForce(direction * PushForce, ForceMode.Impulse);
|
||
|
|
attachment.transform.position = raycastHit.point;
|
||
|
|
attachment.transform.rotation = (Quaternion.Euler(cameraTransform.rotation.x, gameObject.transform.rotation.y, 0));
|
||
|
|
if (attachedObject != null)
|
||
|
|
{
|
||
|
|
attachment.transform.parent = attachedObject.transform;
|
||
|
|
}
|
||
|
|
if (attachedCharacter != null)
|
||
|
|
{
|
||
|
|
attachment.transform.parent = attachedCharacter.transform;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Debug.Log("Missing / Too Far");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Debug.Log("Missing");
|
||
|
|
inputPaused = true;
|
||
|
|
timer = 0.0f;
|
||
|
|
hasPullChainInputSequenceStarted = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|