using System.Collections; using System.Collections.Generic; using UnityEngine; public class CustomSmoothFollow : MonoBehaviour { public Transform target; public float distance = -200.0f; public float height = 200.0f; public float altDistance = -100.0f; public float altHeight = 250.0f; public Vector3 damping; public string layerToMask = "CameraObstruct"; private int layerMask; [Range (0,360)] public float offsetAngle = 90; public float shakeStrength = 5f; private float shakeCurrent; // Use this for initialization void Start() { layerMask = LayerMask.NameToLayer(layerToMask); NotificationServer.register("shake camera", shake); } // Update is called once per frame void LateUpdate() { // Early out if we don't have a target if (!target) return; // Calculate the current and wanted height / XZ pos float wantedHeight = target.position.y + height; float wantedDistance = target.position.z + distance; float wantedSide = target.position.x; bool isBlocked = false; Vector3 wantedPos = new Vector3(wantedSide, wantedHeight, wantedDistance); wantedPos = RotatePointAroundPivot(wantedPos, target.transform.position, offsetAngle); RaycastHit hitInfo; if (Physics.Raycast(wantedPos, target.position-wantedPos, out hitInfo, (target.position-wantedPos).magnitude * 2f)) { // Debug.LogWarning (hitInfo.collider.name + " -- " + hitInfo.collider.gameObject.layer + " -- " + layerMask); if (hitInfo.collider.gameObject.layer == layerMask) isBlocked = true; } if (isBlocked) { wantedPos.y = target.position.y + altHeight; wantedPos.z = target.position.z + altDistance; wantedPos.x = target.position.x; wantedPos = RotatePointAroundPivot(wantedPos, target.transform.position, offsetAngle); } float currentHeight = transform.position.y; float currentDistance = transform.position.z; float currentSide = transform.position.x; // Damp the height currentHeight = Mathf.Lerp(currentHeight, wantedPos.y, damping.y * Time.deltaTime); currentDistance = Mathf.Lerp(currentDistance, wantedPos.z, damping.z * Time.deltaTime); currentSide = Mathf.Lerp(currentSide, wantedPos.x, damping.x * Time.deltaTime); // Set the position of the camera on the x-z plane to: // distance meters behind the target transform.position = target.position; // Set the height of the camera transform.position = new Vector3(currentSide, currentHeight, currentDistance); if (shakeCurrent > 0f) { transform.position += Random.insideUnitSphere * shakeStrength; shakeCurrent -= Time.deltaTime * shakeStrength; } // Always look at the target Vector3 lookTarget = target.position; lookTarget.z = transform.position.z; transform.LookAt(lookTarget); } public void shake() { shakeCurrent = shakeStrength; } private Vector3 RotatePointAroundPivot(Vector3 point,Vector3 pivot,float angles ){ Vector3 dir = point - pivot; // get point direction relative to pivot dir = Quaternion.Euler(angles * Vector3.up) * dir; // rotate it point = dir + pivot; // calculate rotated point return point; // return it } }