//***********************************************************
// Filename: CurveTeleport.cs
// Author: Moritz Kolvenbach, Marco Fendrich
// Last changes: Wednesday, 8th of August 2018
// Content: Class that adds a tilt and a rotation via controller to AdjustableSpeedTeleport
//***********************************************************
using UnityEngine;
///
/// Child class of AdjustableSpeedTeleport adding a tilt and a rotation via controller
///
public class CurveTeleport : AdjustableSpeedTeleport
{
private Vector3 normalisedAcceleration;
///
/// Entire calculation is analogue to except:
/// the commented lines
/// acceleration was replaced with normalisedAcceleration (simply being tilted according to controller)
///
protected override void UpdateProjectionPoints()
{
// tilt rotation corresponding to tilt of controller but limit this tilt to 80°
normalisedAcceleration = Quaternion.Euler(limitRotation(transform.rotation.eulerAngles, 80)) * acceleration;
normalisedVelocity = transform.TransformDirection(initialVelocity);
projectionPoints.Clear();
projectionPoints.Add(transform.position);
Vector3 last = transform.position;
float t = 0;
for (int i = 0; i < pointCount; i++)
{
t += pointSpacing / CalculateNewVelocity(normalisedVelocity, normalisedAcceleration, t).magnitude;
Vector3 next = CalculateNewPosition(transform.position, normalisedVelocity, normalisedAcceleration, t);
Vector3 castHit;
Vector3 norm;
bool endOnNavmesh;
if (navMesh.Linecast(last, next, out endOnNavmesh, out castHit, out norm))
{
// add rotation according to the angle in which the last point stands to the hit point on the ground times 1.5
// get angle of last point to hit point
Vector2 projectedEnd = new Vector2(castHit.x - projectionPoints[projectionPoints.Count - 1].x, castHit.z - projectionPoints[projectionPoints.Count - 1].z);
// get angle of controller
Vector2 controllerDirection = new Vector2(transform.forward.x, transform.forward.z);
// get difference between those two angles to get actual offset independent of world space
rotation = Vector2.SignedAngle(projectedEnd, controllerDirection) * 1.5F;
projectionPoints.Add(castHit);
normalisedHitPoint = norm;
pointOnNavMesh = endOnNavmesh;
return;
}
else
{
projectionPoints.Add(next);
}
last = next;
}
normalisedHitPoint = Vector3.up;
pointOnNavMesh = false;
}
///
/// Limits the eulerAngle vector given as input in its z rotation to the second input given
///
/// eulerAngle vector that will be limited in z rotation
/// limit in degrees of z rotation left and right
/// eulerAngle vector with limited z rotation
protected Vector3 limitRotation(Vector3 toBeLimited, float limit)
{
if (toBeLimited.z < 360-limit && toBeLimited.z > 180)
{
toBeLimited.z = 360-limit;
}
else if (toBeLimited.z > limit && toBeLimited.z < 180)
{
toBeLimited.z = limit;
}
return toBeLimited;
}
}