private void CompensateForWalls(Vector3 fromObject, ref Vector3 toTarget) { // Compensate for walls between camera RaycastHit wallHit = new RaycastHit(); if (Physics.Linecast(fromObject, toTarget, out wallHit)) { Debug.DrawRay(wallHit.point, wallHit.normal, Color.red); toTarget = wallHit.point; } // Compensate for geometry intersecting with near clip plane Vector3 camPosCache = GetComponent <Camera>().transform.position; GetComponent <Camera>().transform.position = toTarget; viewFrustum = DebugDraw.CalculateViewFrustum(GetComponent <Camera>(), ref nearClipDimensions); for (int i = 0; i < (viewFrustum.Length / 2); i++) { RaycastHit cWHit = new RaycastHit(); RaycastHit cCWHit = new RaycastHit(); // Cast lines in both directions around near clipping plane bounds while (Physics.Linecast(viewFrustum[i], viewFrustum[(i + 1) % (viewFrustum.Length / 2)], out cWHit) || Physics.Linecast(viewFrustum[(i + 1) % (viewFrustum.Length / 2)], viewFrustum[i], out cCWHit)) { Vector3 normal = wallHit.normal; if (wallHit.normal == Vector3.zero) { // If there's no available wallHit, use normal of geometry intersected by LineCasts instead if (cWHit.normal == Vector3.zero) { if (cCWHit.normal == Vector3.zero) { Debug.LogError("No available geometry normal from near clip plane LineCasts. Something must be amuck.", this); } else { normal = cCWHit.normal; } } else { normal = cWHit.normal; } } toTarget += (compensationOffset * normal); GetComponent <Camera>().transform.position += toTarget; // Recalculate positions of near clip plane viewFrustum = DebugDraw.CalculateViewFrustum(GetComponent <Camera>(), ref nearClipDimensions); } } GetComponent <Camera>().transform.position = camPosCache; viewFrustum = DebugDraw.CalculateViewFrustum(GetComponent <Camera>(), ref nearClipDimensions); }
/// <summary> /// <para>Compensa la camara para que no ocurran colisiones.</para> /// </summary> /// <param name="fromObject"></param> /// <param name="toTarget"></param> private void CompensarColisiones(Vector3 fromObject, ref Vector3 toTarget) { // Compensar las paredes entre la camara RaycastHit hitCollider = new RaycastHit(); if (Physics.Linecast(fromObject, toTarget, out hitCollider)) { Debug.DrawRay(hitCollider.point, hitCollider.normal, Color.red); toTarget = hitCollider.point; } // Compensar geo Vector3 camPosCache = GetComponent <Camera>().transform.position; GetComponent <Camera>().transform.position = toTarget; vistaDebug = DebugDraw.CalculateViewFrustum(GetComponent <Camera>(), ref dimension); for (int i = 0; i < (vistaDebug.Length / 2); i++) { RaycastHit cWHit = new RaycastHit(); RaycastHit cCWHit = new RaycastHit(); // Reparte lineas en ambas direcciones alrededor de los limites del plano de recorte while (Physics.Linecast(vistaDebug[i], vistaDebug[(i + 1) % (vistaDebug.Length / 2)], out cWHit) || Physics.Linecast(vistaDebug[(i + 1) % (vistaDebug.Length / 2)], vistaDebug[i], out cCWHit)) { Vector3 normal = hitCollider.normal; if (hitCollider.normal == Vector3.zero) { // Si no hay hitCollider disponible, usa la geometria if (cWHit.normal == Vector3.zero) { if (cCWHit.normal == Vector3.zero) { Debug.LogError("No hay geometria disponible cerca del plano de LineCasts.", this); } else { normal = cCWHit.normal; } } else { normal = cWHit.normal; } } toTarget += (0.2f * normal); GetComponent <Camera>().transform.position += toTarget; // Recalcular posicion vistaDebug = DebugDraw.CalculateViewFrustum(GetComponent <Camera>(), ref dimension); } } GetComponent <Camera>().transform.position = camPosCache; vistaDebug = DebugDraw.CalculateViewFrustum(GetComponent <Camera>(), ref dimension); }
void LateUpdate() { viewFrustum = DebugDraw.CalculateViewFrustum(GetComponent <Camera>(), ref nearClipDimensions); // Pull values from controller/keyboard float rightX = Input.GetAxis("RightStickX"); float rightY = Input.GetAxis("RightStickY"); float leftX = Input.GetAxis("Horizontal"); float leftY = Input.GetAxis("Vertical"); //float mouseWheel = Input.GetAxis("Mouse ScrollWheel"); //float mouseWheelScaled = mouseWheel * mouseWheelSensitivity; //float leftTrigger = Input.GetAxis("Target"); //bool bButtonPressed = Input.GetButton("ExitFPV"); bool qKeyDown = Input.GetKey(KeyCode.Q); bool eKeyDown = Input.GetKey(KeyCode.E); bool lShiftKeyDown = Input.GetKey(KeyCode.LeftShift); // Abstraction to set right Y when using mouse if (qKeyDown) { //rightX = 1; } if (eKeyDown) { //rightX = -1; } if (lShiftKeyDown) { //leftTrigger = 1; } characterOffset = followXform.position + (distanceUp * followXform.up) - characterOffset2; Vector3 lookAt = characterOffset; targetPosition = Vector3.zero; // Determine camera state // * Targeting * /* * if (leftTrigger > TARGETING_THRESHOLD) * { * barEffect.coverage = Mathf.SmoothStep(barEffect.coverage, widescreen, targetingTime); * * camState = CamStates.Target; * }*/ if (Input.GetButton("TargetCam")) { barEffect.coverage = Mathf.SmoothStep(barEffect.coverage, widescreen, targetingTime); camState = CamStates.Target; } else { barEffect.coverage = Mathf.SmoothStep(barEffect.coverage, 0f, targetingTime); // * First Person * if (Input.GetButton("FirstPersonCam")) { // Reset look before entering the first person mode //xAxisRot = 0; //lookWeight = 0f; camState = CamStates.FirstPerson; } // * Free * } if (Input.GetButton("BehindCam")) { camState = CamStates.Behind; } if (Input.GetButton("FreeCam")) { camState = CamStates.Free; } //---- // Set the Look At Weight - amount to use look at IK vs using the head's animation // follow.Animator.SetLookAtWeight(lookWeight); // Execute camera state switch (camState) { case CamStates.Behind: ResetCamera(); // Only update camera look direction if moving /* * if (follow.Speed > follow.LocomotionThreshold && follow.IsInLocomotion() && !follow.IsInPivot()) * { * lookDir = Vector3.Lerp(followXform.right * (leftX < 0 ? 1f : -1f), followXform.forward * (leftY < 0 ? -1f : 1f), Mathf.Abs(Vector3.Dot(this.transform.forward, followXform.forward))); * Debug.DrawRay(this.transform.position, lookDir, Color.white); * * // Calculate direction from camera to player, kill Y, and normalize to give a valid direction with unit magnitude * curLookDir = Vector3.Normalize(characterOffset - this.transform.position); * curLookDir.y = 0; * Debug.DrawRay(this.transform.position, curLookDir, Color.green); * * // Damping makes it so we don't update targetPosition while pivoting; camera shouldn't rotate around player * curLookDir = Vector3.SmoothDamp(curLookDir, lookDir, ref velocityLookDir, lookDirDampTime); * } */ targetPosition = characterOffset + followXform.up * distanceUp - Vector3.Normalize(curLookDir) * distanceAway; Debug.DrawLine(followXform.position, targetPosition, Color.magenta); firstPersonCamPos.SetActive(false); break; case CamStates.Target: ResetCamera(); lookDir = followXform.forward; curLookDir = followXform.forward; targetPosition = characterOffset + followXform.up * distanceUp - lookDir * distanceAway; firstPersonCamPos.SetActive(false); break; case CamStates.FirstPerson: /*// Looking up and down * // Calculate the amount of rotation and apply to the firstPersonCamPos GameObject * xAxisRot += (leftY * 0.5f * firstPersonLookSpeed); * xAxisRot = Mathf.Clamp(xAxisRot, firstPersonXAxisClamp.x, firstPersonXAxisClamp.y); * firstPersonCamPos.XForm.localRotation = Quaternion.Euler(xAxisRot, 0, 0); * * // Superimpose firstPersonCamPos GameObject's rotation on camera * Quaternion rotationShift = Quaternion.FromToRotation(this.transform.forward, firstPersonCamPos.XForm.forward); * this.transform.rotation = rotationShift * this.transform.rotation; * * // Move character model's head * follow.Animator.SetLookAtPosition(firstPersonCamPos.XForm.position + firstPersonCamPos.XForm.forward); * lookWeight = Mathf.Lerp(lookWeight, 1.0f, Time.deltaTime * firstPersonLookSpeed); * * * // Looking left and right * // Similarly to how character is rotated while in locomotion, use Quaternion * to add rotation to character * Vector3 rotationAmount = Vector3.Lerp(Vector3.zero, new Vector3(0f, fPSRotationDegreePerSecond * (leftX < 0f ? -1f : 1f), 0f), Mathf.Abs(leftX)); * Quaternion deltaRotation = Quaternion.Euler(rotationAmount * Time.deltaTime); * follow.transform.rotation = (follow.transform.rotation * deltaRotation); * * // Move camera to firstPersonCamPos * //targetPosition = firstPersonCamPos.XForm.position; * * // Smoothly transition look direction towards firstPersonCamPos when entering first person mode * lookAt = Vector3.Lerp(targetPosition + followXform.forward, this.transform.position + this.transform.forward, camSmoothDampTime * Time.deltaTime); * Debug.DrawRay(Vector3.zero, lookAt, Color.black); * Debug.DrawRay(Vector3.zero, targetPosition + followXform.forward, Color.white); * Debug.DrawRay(Vector3.zero, firstPersonCamPos.XForm.position + firstPersonCamPos.XForm.forward, Color.cyan); * * // Choose lookAt target based on distance * lookAt = (Vector3.Lerp(this.transform.position + this.transform.forward, lookAt, Vector3.Distance(this.transform.position, firstPersonCamPos.XForm.position))); */ targetPosition = firstPersonCamPos.transform.position; lookAt = Vector3.Lerp(targetPosition + followXform.forward, this.transform.position + this.transform.forward, camSmoothDampTime * Time.deltaTime); if (Vector3.Distance(targetPosition, this.transform.position) < 2) { firstPersonCamPos.SetActive(true); } break; case CamStates.Free: lookWeight = Mathf.Lerp(lookWeight, 0.0f, Time.deltaTime * firstPersonLookSpeed); Vector3 rigToGoal = characterOffset - cameraXform.position; rigToGoal.y = 0f; Debug.DrawRay(cameraXform.transform.position, rigToGoal, Color.red); // Panning in and out // If statement works for positive values; don't tween if stick not increasing in either direction; also don't tween if user is rotating // Checked against rightStickThreshold because very small values for rightY mess up the Lerp function if (rightY < lastStickMin && rightY < -1f * rightStickThreshold && rightY <= rightStickPrevFrame.y && Mathf.Abs(rightX) < rightStickThreshold) { // Zooming out distanceUpFree = Mathf.Lerp(distanceUp, distanceUp * distanceUpMultiplier, Mathf.Abs(rightY)); distanceAwayFree = Mathf.Lerp(distanceAway, distanceAway * distanceAwayMultipler, Mathf.Abs(rightY)); targetPosition = characterOffset + followXform.up * distanceUpFree - RigToGoalDirection * distanceAwayFree; lastStickMin = rightY; } else if (rightY > rightStickThreshold && rightY >= rightStickPrevFrame.y && Mathf.Abs(rightX) < rightStickThreshold) { // Zooming in // Subtract height of camera from height of player to find Y distance distanceUpFree = Mathf.Lerp(Mathf.Abs(transform.position.y - characterOffset.y), camMinDistFromChar.y, rightY); // Use magnitude function to find X distance distanceAwayFree = Mathf.Lerp(rigToGoal.magnitude, camMinDistFromChar.x, rightY); targetPosition = characterOffset + followXform.up * distanceUpFree - RigToGoalDirection * distanceAwayFree; lastStickMin = float.PositiveInfinity; } // Store direction only if right stick inactive if (rightX != 0 || rightY != 0) { savedRigToGoal = RigToGoalDirection; } // Rotating around character cameraXform.RotateAround(characterOffset, followXform.up, freeRotationDegreePerSecond * -1 * (Mathf.Abs(rightX) > rightStickThreshold ? rightX : 0f)); // Still need to track camera behind player even if they aren't using the right stick; achieve this by saving distanceAwayFree every frame if (targetPosition == Vector3.zero) { targetPosition = characterOffset + followXform.up * distanceUpFree - savedRigToGoal * distanceAwayFree; } firstPersonCamPos.SetActive(false); break; } CompensateForWalls(characterOffset, ref targetPosition); SmoothPosition(cameraXform.position, targetPosition); transform.LookAt(lookAt); // Make sure to cache the unscaled mouse wheel value if using mouse/keyboard instead of controller rightStickPrevFrame = new Vector2(rightX, rightY); //mouseWheel != 0 ? mouseWheelScaled : rightY); }
private void LateUpdate() { vistaDebug = DebugDraw.CalculateViewFrustum(GetComponent <Camera>(), ref dimension); // Obtener valores de controller/teclado float rightX = Input.GetAxis("RightStickX"); float rightY = Input.GetAxis("RightStickY"); float leftX = Input.GetAxis("Horizontal"); float leftY = Input.GetAxis("Vertical"); float mouseRuleta = Input.GetAxis("Mouse ScrollWheel"); float mouseRuletaEscala = mouseRuleta * sensibilidad; float leftTrigger = Input.GetAxis("Target"); bool btnB = Input.GetButton("ExitFPV"); bool keyQ = Input.GetKey(KeyCode.Q); bool keyE = Input.GetKey(KeyCode.E); bool keyShift = Input.GetKey(KeyCode.LeftShift); // Abstraccion para establecer Y correctamente al usar el raton if (mouseRuleta != 0) { rightY = mouseRuletaEscala; } if (keyQ) { rightX = 1; } if (keyE) { rightX = -1; } if (keyShift) { leftTrigger = 1; } offSetPersonaje = personaje.position + (distanciaArriba * personaje.up); Vector3 lookAt = offSetPersonaje; posicionTarget = Vector3.zero; // Establece el valor del peso motor.Animator.SetLookAtWeight(fuerzaLook); // Logica // Reseteo de camara ResetCamara(); // Solo actualice la direccion de la camara si se mueve if (motor.Velocidad > motor.LocomotionLimite && motor.IsInLocomotion() && !motor.IsPivotando()) { dirFija = Vector3.Lerp(personaje.right * (leftX < 0 ? 1f : -1f), personaje.forward * (leftY < 0 ? -1f : 1f), Mathf.Abs(Vector3.Dot(this.transform.forward, personaje.forward))); Debug.DrawRay(this.transform.position, dirFija, Color.white); // Calcula la direccion de la camara al jugador, mata Y y normaliza para dar una direccion valida con la magnitud de la unidad actualDirFija = Vector3.Normalize(offSetPersonaje - this.transform.position); actualDirFija.y = 0; Debug.DrawRay(this.transform.position, actualDirFija, Color.green); // La interpolacion actualDirFija = Vector3.SmoothDamp(actualDirFija, dirFija, ref velActualCam, tiempoLookAt); } posicionTarget = offSetPersonaje + personaje.up * distanciaArriba - Vector3.Normalize(actualDirFija) * distanciaLejana; Debug.DrawLine(personaje.position, posicionTarget, Color.magenta); CompensarColisiones(offSetPersonaje, ref posicionTarget); TransicionPosicion(camara.position, posicionTarget); transform.LookAt(lookAt); }
private void FixedUpdate() { viewFrustum = DebugDraw.CalculateViewFrustum(GetComponent<Camera>(), ref nearClipDimensions); }