using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class GrappleHook : MonoBehaviour { [SerializeField] private float maxGrappleDist = 200; [SerializeField] private float grappleExtendSpeed = 20; [SerializeField] private LayerMask grappleableLayer; [SerializeField] private Transform gunPos; private Vector3 hitPosLocal; private SpringJoint joint; private LineRenderer lr; RaycastHit hit; private bool grappled = false; private Vector3 currGrappleEndPos; [SerializeField] private RectTransform canvasRect; [SerializeField] private RectTransform hitMarkerRect; // Start is called before the first frame update void Start() { lr = gameObject.GetComponentInChildren(); lr.enabled = false; hitMarkerRect.gameObject.SetActive(false); } // Update is called once per frame void Update() { if(Input.GetMouseButtonUp(0)){//TODO Change to correct input system EndGrapple(); } if(grappled){ DrawRope(Time.deltaTime); if(Input.GetMouseButtonDown(1)){ joint.minDistance = 0f; joint.maxDistance = 0f; } return; } Aim(); // TODO extend and retract rope } private void Aim(){ Vector3 mousePos; mousePos = Input.mousePosition; mousePos.z = Mathf.Abs(Camera.main.transform.position.z); mousePos = Camera.main.ScreenToWorldPoint(mousePos); Vector3 aimDir = (mousePos - gameObject.transform.position).normalized; if(!hitMarkerRect.gameObject.activeSelf)hitMarkerRect.gameObject.SetActive(true); hitMarkerRect.anchoredPosition = WorldToUI(gameObject.transform.position + aimDir * maxGrappleDist); if(Physics.Raycast(gameObject.transform.position, aimDir, out hit, maxGrappleDist, grappleableLayer)){ hitMarkerRect.anchoredPosition = WorldToUI(hit.point); hitMarkerRect.gameObject.GetComponent().color = Color.green; if(Input.GetMouseButtonDown(0)){ StartGrapple(hit); } }else{ hitMarkerRect.gameObject.GetComponent().color = Color.red; } } private void DrawRope(float deltaTime){ // TODO animate a wiggle on the rope if(!grappled)return; lr.SetPosition(0, gunPos.position); Vector3 endPoint; if(hit.rigidbody != null){ endPoint = hit.transform.TransformPoint(hitPosLocal); }else{ endPoint = hit.point; } currGrappleEndPos = Vector3.Lerp(currGrappleEndPos, endPoint, deltaTime * grappleExtendSpeed); lr.SetPosition(1, currGrappleEndPos); if(!lr.enabled)lr.enabled = true; } private void StartGrapple(RaycastHit hit){ grappled = true; //Display hitMarkerRect.gameObject.SetActive(false); // Rope phys joint = gameObject.AddComponent(); joint.anchor = transform.InverseTransformPoint(gunPos.position); joint.autoConfigureConnectedAnchor = false; joint.maxDistance = hit.distance * 0.8f; joint.minDistance = hit.distance * 0.25f; if(hit.rigidbody != null){ Rigidbody hitRb = hit.rigidbody; joint.connectedBody = hitRb; joint.connectedAnchor = hit.transform.InverseTransformPoint(hit.point); hitPosLocal = hit.transform.InverseTransformPoint(hit.point); }else{ joint.connectedAnchor = hit.point; } joint.spring = 4.5f * 5f; joint.damper = 7f; joint.massScale = 4.5f; currGrappleEndPos = transform.position; } private void EndGrapple(){ grappled = false; lr.enabled = false; Destroy(joint); } private Vector2 WorldToUI(Vector3 point){ Vector2 viewPortPos = Camera.main.WorldToViewportPoint(point); Vector2 pointScreenPos = new Vector2(((viewPortPos.x*canvasRect.sizeDelta.x)-(canvasRect.sizeDelta.x*0.5f)), ((viewPortPos.y*canvasRect.sizeDelta.y)-(canvasRect.sizeDelta.y*0.5f))); return pointScreenPos; } }