IEnumerator shootZRootCoroutine(Vector3 originPosition, Vector3 direction) { zRootObject.gameObject.SetActive(true); float distance = 0; currentAngle = 0; bool isHit = false; ZRootInteractableObject interactable = null; Vector3 hitPos = originPosition + direction * zRootMaximumDistance; shakeOffset = new Vector2(Random.Range(0f, 10f), Random.Range(0f, 10f)); StartCoroutine(spawnGauntletVFX()); // Find object to attach RaycastHit[] hits; hits = Physics.RaycastAll(originPosition, direction, zRootMaximumDistance, ~characterLayerMask ^ Physics.IgnoreRaycastLayer); float closestDist = zRootMaximumDistance; Vector3 hitNormal = -direction; foreach (RaycastHit hit in hits) { ZRootInteractableObject t = hit.collider.transform.GetComponent <ZRootInteractableObject>(); float dist = float.MaxValue; if (t) { if (t.zRootGrabHandle) { dist = (t.zRootGrabHandle.position - originPosition).magnitude - t.zRootGrabOffset; } else { dist = (hit.point - originPosition).magnitude - t.zRootGrabOffset; } } else if (!hit.collider.isTrigger) { dist = (hit.point - originPosition).magnitude; } if (dist < closestDist) { closestDist = dist; isHit = true; if (t) { interactable = t; if (t.zRootGrabHandle) { hitPos = t.zRootGrabHandle.position - direction * t.zRootGrabOffset; } else { hitPos = hit.point - direction * t.zRootGrabOffset; hitNormal = hit.normal; } } else { interactable = null; hitPos = hit.point; } } } // Animate ZRoot to reach object AkSoundEngine.PostEvent("lev_zroot_shoot", gameObject); playVFX(); direction = (hitPos - originPosition).normalized; float timeToReach = closestDist / zRootSpeed; float currentTime = 0; int zRootShape = 0; if (interactable) { zRootShape = (int)interactable.zRootClawType; } zRootObject.GetComponent <Animator> ().SetInteger("shape", zRootShape); zRootObject.GetComponent <Animator> ().SetTrigger("shot"); while (currentTime < timeToReach) { currentTime += Time.deltaTime; if (currentTime > timeToReach) { currentTime = timeToReach; } distance = zRootSpeed * currentTime; attachPoint = originPosition + direction * distance; currentAngle += angularSpeed * Time.deltaTime; updateVFX(); yield return(null); } AkSoundEngine.PostEvent("lev_zroot_stop", gameObject); stopVFX(); // Notify the object when it's hit AkSoundEngine.PostEvent("lev_zroot_impact", gameObject); zRootObject.GetComponent <Animator> ().SetTrigger("onImpact"); if (isHit) { if (interactable) { if (interactable.zRootClawType != ZRootClawType.Knuckle) { yield return(new WaitForSeconds(0.05f)); shakeTime = 0.35f; shakeMultiplier = 1; yield return(new WaitForSeconds(0.35f)); shakeTime = 0; } interactable.HitByZRoot(this, levController.GetComponent <Rigidbody> ()); if (interactable.zRootClawType == ZRootClawType.Knuckle) { float t = 0; MainObjectSingleton.shared(MainObjectType.Camera).GetComponent <CameraController> ().shake(0.1f, 0.3f); while (currentTime + t < timeToReach + 0.2f) { t += Time.deltaTime; if (t > 0.2f) { t = 0.2f; } distance = zRootSpeed * currentTime + zRootSpeed / 10 * t; attachPoint = originPosition + direction * distance; currentAngle += angularSpeed * Time.deltaTime; yield return(null); } } if (interactable.interactDefinition == ZRootInteractableObject.InteractType.Grapple) { yield return(new WaitForSeconds(0.1f)); } } } yield return(null); // Animate ZRoot back to Lev's gauntlet AkSoundEngine.PostEvent("lev_zroot_retract", gameObject); zRootObject.GetComponent <Animator> ().ResetTrigger("onImpact"); zRootObject.GetComponent <Animator> ().SetTrigger("retracted"); direction = attachPoint - transform.position; distance = direction.magnitude; direction.Normalize(); while (distance > 0.1f) { distance -= zRootSpeed * Time.deltaTime; if (distance < 0.1f) { distance = 0.1f; } attachPoint = transform.position + direction * distance; currentAngle -= angularSpeed * Time.deltaTime; yield return(null); } zRootObject.GetComponent <Animator> ().ResetTrigger("retracted"); zRootObject.gameObject.SetActive(false); }