446 lines
14 KiB
C#
446 lines
14 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
public class launchTrayectory : MonoBehaviour
|
|
{
|
|
[Header ("Main Settings")]
|
|
[Space]
|
|
|
|
public LayerMask layer;
|
|
|
|
public bool showLineRendererEnabled = true;
|
|
|
|
public float width;
|
|
public float numberOfPoints;
|
|
public float animationSpeed;
|
|
public float tillingOffset;
|
|
public bool animateTexture;
|
|
public Color textureColor;
|
|
|
|
public bool useMaxDistanceWhenNoSurfaceFound;
|
|
public float maxDistanceWhenNoSurfaceFound;
|
|
|
|
public bool raycastCheckingEnabled = true;
|
|
|
|
public bool checkIfLockedCameraActive;
|
|
|
|
[Space]
|
|
[Header ("Other Settings")]
|
|
[Space]
|
|
|
|
public bool checkForPlayerCollider;
|
|
public Collider playerCollider;
|
|
|
|
[Space]
|
|
|
|
public bool useHoldThrowArmAnimation;
|
|
public string actionActiveAnimatorName = "Action Active";
|
|
public string holdThrowMeleeWeaponAnimatorName = "Action ID";
|
|
public int holdThrowMeleeWeaponAnimatorID;
|
|
public string setExitStateOnArmsTriggerName = "Set Exit State On Arms";
|
|
|
|
[Space]
|
|
|
|
public bool useHeadTrackCheckingLaunchDirection;
|
|
public float headTrackBodyWeightOnAim = 1;
|
|
|
|
[Space]
|
|
[Header ("Show Target Position Icon Settings")]
|
|
[Space]
|
|
|
|
public bool showTargetPositionIcon;
|
|
public GameObject targetPositionIcon;
|
|
public bool rotateTargetPositionIcon;
|
|
public float rotateTargetPositionIconSpeed;
|
|
|
|
[Space]
|
|
[Header ("Debug")]
|
|
[Space]
|
|
|
|
public bool parableEnabled = false;
|
|
public bool surfaceFound;
|
|
public bool checkBodyAimStateActive;
|
|
|
|
[Space]
|
|
[Header ("Components")]
|
|
[Space]
|
|
|
|
public playerCamera mainPlayerCamera;
|
|
public Transform shootPosition;
|
|
public GameObject character;
|
|
|
|
public Transform mainCameraTransform;
|
|
public LineRenderer lineRenderer;
|
|
|
|
public headTrack mainHeadTrack;
|
|
|
|
public Animator mainAnimator;
|
|
|
|
[Space]
|
|
[Header ("Gizmo Settings")]
|
|
[Space]
|
|
|
|
public bool showGizmo;
|
|
|
|
float currentAnimationOffset;
|
|
Vector3 rayPoint;
|
|
RaycastHit hit;
|
|
bool rayColliding;
|
|
|
|
float hitDistance;
|
|
|
|
Vector3 startPosition;
|
|
Vector3 endPosition;
|
|
|
|
Vector3 currentRendererPosition;
|
|
|
|
float currentRaycastDistance;
|
|
|
|
public Vector3 raycastDirection;
|
|
Vector3 raycastOrigin;
|
|
|
|
Ray newRay;
|
|
|
|
Coroutine mainCoroutine;
|
|
|
|
bool isPlayerMovingOn3dWorld;
|
|
|
|
|
|
void Start ()
|
|
{
|
|
changeParableState (false);
|
|
}
|
|
|
|
public void stopUpdateCoroutine ()
|
|
{
|
|
if (mainCoroutine != null) {
|
|
StopCoroutine (mainCoroutine);
|
|
}
|
|
}
|
|
|
|
IEnumerator updateCoroutine ()
|
|
{
|
|
var waitTime = new WaitForFixedUpdate ();
|
|
|
|
while (true) {
|
|
updateTrayectoryState ();
|
|
|
|
yield return waitTime;
|
|
}
|
|
}
|
|
|
|
void updateTrayectoryState ()
|
|
{
|
|
//if the player is using the barrel launcher
|
|
if (parableEnabled) {
|
|
//get the start position of the parable
|
|
startPosition = shootPosition.position;
|
|
|
|
if (raycastCheckingEnabled) {
|
|
currentRaycastDistance = Mathf.Infinity;
|
|
} else {
|
|
currentRaycastDistance = maxDistanceWhenNoSurfaceFound;
|
|
}
|
|
|
|
raycastDirection = mainCameraTransform.TransformDirection (Vector3.forward);
|
|
raycastOrigin = mainCameraTransform.position;
|
|
|
|
if (checkIfLockedCameraActive) {
|
|
if (mainPlayerCamera != null) {
|
|
if (!mainPlayerCamera.isCameraTypeFree () && isPlayerMovingOn3dWorld) {
|
|
newRay = mainPlayerCamera.getCameraRaycastDirection ();
|
|
raycastDirection = newRay.direction;
|
|
raycastOrigin = newRay.origin;
|
|
}
|
|
}
|
|
}
|
|
|
|
surfaceFound = false;
|
|
|
|
//check where the camera is looking and
|
|
if (Physics.Raycast (raycastOrigin, raycastDirection, out hit, currentRaycastDistance, layer)) {
|
|
if (showGizmo) {
|
|
Debug.DrawRay (raycastOrigin, raycastDirection * currentRaycastDistance, Color.green);
|
|
}
|
|
|
|
if (checkForPlayerCollider) {
|
|
if (playerCollider != null) {
|
|
if (hit.collider == playerCollider) {
|
|
raycastOrigin = hit.point + raycastDirection * 0.2f;
|
|
|
|
if (Physics.Raycast (raycastOrigin, raycastDirection, out hit, currentRaycastDistance, layer)) {
|
|
surfaceFound = true;
|
|
}
|
|
} else {
|
|
surfaceFound = true;
|
|
}
|
|
} else {
|
|
surfaceFound = true;
|
|
}
|
|
} else {
|
|
surfaceFound = true;
|
|
}
|
|
|
|
if (surfaceFound) {
|
|
//enable the linerender
|
|
hitDistance = hit.distance;
|
|
rayPoint = hit.point;
|
|
|
|
rayColliding = true;
|
|
|
|
if (showLineRendererEnabled) {
|
|
if (!lineRenderer.enabled) {
|
|
lineRenderer.enabled = true;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (showGizmo) {
|
|
Debug.DrawRay (raycastOrigin, raycastDirection * currentRaycastDistance, Color.red);
|
|
}
|
|
|
|
if (useMaxDistanceWhenNoSurfaceFound) {
|
|
|
|
hitDistance = maxDistanceWhenNoSurfaceFound;
|
|
rayPoint = raycastOrigin + raycastDirection * maxDistanceWhenNoSurfaceFound;
|
|
|
|
rayColliding = true;
|
|
|
|
if (showLineRendererEnabled) {
|
|
if (!lineRenderer.enabled) {
|
|
lineRenderer.enabled = true;
|
|
}
|
|
}
|
|
} else {
|
|
//disable it
|
|
rayColliding = false;
|
|
|
|
if (showLineRendererEnabled) {
|
|
if (lineRenderer.enabled) {
|
|
lineRenderer.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rayColliding) {
|
|
//if the ray detects a surface, set the linerenderer positions and animated it
|
|
endPosition = rayPoint;
|
|
|
|
if (showLineRendererEnabled) {
|
|
lineRenderer.positionCount = (int)numberOfPoints + 1;
|
|
|
|
//get every linerendere position according to the number of points
|
|
for (float i = 0; i < numberOfPoints + 1; i++) {
|
|
currentRendererPosition = getParablePoint (startPosition, endPosition, i / numberOfPoints);
|
|
|
|
lineRenderer.SetPosition ((int)i, currentRendererPosition);
|
|
}
|
|
|
|
//animate the texture of the line renderer by changing its offset texture
|
|
lineRenderer.startWidth = width;
|
|
lineRenderer.endWidth = width;
|
|
|
|
int propertyNameID = Shader.PropertyToID ("_Color");
|
|
|
|
if (animateTexture) {
|
|
currentAnimationOffset -= animationSpeed * Time.deltaTime * hitDistance * 0.05f;
|
|
lineRenderer.material.mainTextureScale = new Vector2 (tillingOffset * hitDistance * 0.2f, 1);
|
|
lineRenderer.material.mainTextureOffset = new Vector2 (currentAnimationOffset, lineRenderer.material.mainTextureOffset.y);
|
|
|
|
if (lineRenderer.material.HasProperty (propertyNameID)) {
|
|
lineRenderer.material.color = textureColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (showTargetPositionIcon) {
|
|
updateShowTargetPositionIcon (rayColliding);
|
|
}
|
|
}
|
|
}
|
|
|
|
void updateShowTargetPositionIcon (bool surfaceLocated)
|
|
{
|
|
if (surfaceLocated) {
|
|
|
|
if (!targetPositionIcon.activeSelf) {
|
|
targetPositionIcon.SetActive (true);
|
|
}
|
|
|
|
targetPositionIcon.transform.position = hit.point + hit.normal * 0.08f;
|
|
|
|
Vector3 targetForwardDirection = Vector3.Cross (targetPositionIcon.transform.right, hit.normal);
|
|
Quaternion targetRotation = Quaternion.LookRotation (targetForwardDirection, hit.normal);
|
|
|
|
targetPositionIcon.transform.rotation = targetRotation;
|
|
|
|
if (rotateTargetPositionIcon) {
|
|
targetPositionIcon.transform.Rotate (0, rotateTargetPositionIconSpeed * Time.deltaTime, 0);
|
|
}
|
|
} else {
|
|
if (targetPositionIcon.activeSelf) {
|
|
targetPositionIcon.SetActive (false);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void changeParableState (bool state)
|
|
{
|
|
//enable or disable the barrel launcher parable
|
|
parableEnabled = state;
|
|
|
|
if (showLineRendererEnabled) {
|
|
if (lineRenderer != null) {
|
|
if (parableEnabled) {
|
|
lineRenderer.enabled = true;
|
|
} else {
|
|
lineRenderer.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (parableEnabled) {
|
|
mainCoroutine = StartCoroutine (updateCoroutine ());
|
|
} else {
|
|
stopUpdateCoroutine ();
|
|
|
|
if (showTargetPositionIcon) {
|
|
if (targetPositionIcon.activeSelf) {
|
|
targetPositionIcon.SetActive (false);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mainPlayerCamera != null) {
|
|
isPlayerMovingOn3dWorld = !mainPlayerCamera.is2_5ViewActive ();
|
|
|
|
if (!isPlayerMovingOn3dWorld) {
|
|
if (useHeadTrackCheckingLaunchDirection) {
|
|
if (mainHeadTrack == null) {
|
|
mainHeadTrack = GKC_Utils.getCharacterHeadTrack (character);
|
|
}
|
|
}
|
|
|
|
checkBodyAimState (state);
|
|
}
|
|
|
|
if (useHoldThrowArmAnimation) {
|
|
if (holdThrowMeleeWeaponAnimatorID != 0) {
|
|
if (mainAnimator == null) {
|
|
mainAnimator = GKC_Utils.getCharacterAnimator (character);
|
|
}
|
|
|
|
if (mainAnimator != null) {
|
|
if (state) {
|
|
GKC_Utils.resetAnimatorTriggerOnCharacter (character, setExitStateOnArmsTriggerName);
|
|
|
|
mainAnimator.SetInteger (holdThrowMeleeWeaponAnimatorName, holdThrowMeleeWeaponAnimatorID);
|
|
mainAnimator.SetBool (actionActiveAnimatorName, true);
|
|
} else {
|
|
if (GKC_Utils.isActionActiveOnCharacter (character)) {
|
|
GKC_Utils.setAnimatorTriggerOnCharacter (character, setExitStateOnArmsTriggerName);
|
|
} else {
|
|
mainAnimator.SetInteger (holdThrowMeleeWeaponAnimatorName, 0);
|
|
mainAnimator.SetBool (actionActiveAnimatorName, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void checkBodyAimState (bool state)
|
|
{
|
|
if (!useHeadTrackCheckingLaunchDirection) {
|
|
return;
|
|
}
|
|
|
|
if (mainHeadTrack == null) {
|
|
return;
|
|
}
|
|
|
|
if (checkBodyAimStateActive == state) {
|
|
return;
|
|
}
|
|
|
|
checkBodyAimStateActive = state;
|
|
|
|
if (state) {
|
|
mainHeadTrack.setCameraBodyWeightValue (headTrackBodyWeightOnAim);
|
|
} else {
|
|
mainHeadTrack.setOriginalCameraBodyWeightValue ();
|
|
}
|
|
|
|
mainHeadTrack.setHeadTrackActiveWhileAimingState (state);
|
|
|
|
mainHeadTrack.setCanUseHeadTrackOnLockedCameraActiveState (state);
|
|
}
|
|
|
|
Vector3 getParablePoint (Vector3 start, Vector3 end, float t)
|
|
{
|
|
//set the height of the parable according to the final position
|
|
float value = GKC_Utils.distance (start, end) / 65;
|
|
float v0y = Physics.gravity.magnitude * value;
|
|
float height = v0y;
|
|
|
|
//translate to local position, to work correctly with the gravity control in the character
|
|
float heightY = Mathf.Abs (transform.InverseTransformDirection (start).y - transform.InverseTransformDirection (end).y);
|
|
if (heightY < 0.1f) {
|
|
//start and end are roughly level
|
|
Vector3 travelDirection = end - start;
|
|
Vector3 result = start + t * travelDirection;
|
|
result += Mathf.Sin (t * Mathf.PI) * height * character.transform.up;
|
|
|
|
return result;
|
|
} else {
|
|
//start and end are not level
|
|
Vector3 travelDirection = end - start;
|
|
Vector3 startNew = start - transform.InverseTransformDirection (start).y * character.transform.up;
|
|
startNew += transform.InverseTransformDirection (end).y * character.transform.up;
|
|
|
|
Vector3 levelDirection = end - startNew;
|
|
Vector3 right = Vector3.Cross (travelDirection, levelDirection);
|
|
Vector3 up = Vector3.Cross (right, levelDirection);
|
|
if (transform.InverseTransformDirection (end).y > transform.InverseTransformDirection (start).y) {
|
|
up = -up;
|
|
}
|
|
|
|
Vector3 result = start + t * travelDirection;
|
|
result += (Mathf.Sin (t * Mathf.PI) * height) * up.normalized;
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public void setMainCameraTransform (Transform newCameraTransform)
|
|
{
|
|
mainCameraTransform = newCameraTransform;
|
|
}
|
|
|
|
public void setShowLineRendererEnabledState (bool state)
|
|
{
|
|
showLineRendererEnabled = state;
|
|
|
|
}
|
|
|
|
void OnDrawGizmos ()
|
|
{
|
|
//draw the parable in the editor
|
|
if (showGizmo && Application.isPlaying) {
|
|
GUI.skin.box.fontSize = 16;
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawLine (startPosition, endPosition);
|
|
Vector3 lastP = startPosition;
|
|
|
|
for (float i = 0; i < numberOfPoints + 1; i++) {
|
|
Vector3 p = getParablePoint (startPosition, endPosition, i / numberOfPoints);
|
|
Gizmos.color = i % 2 == 0 ? Color.blue : Color.green;
|
|
Gizmos.DrawLine (lastP, p);
|
|
lastP = p;
|
|
}
|
|
}
|
|
}
|
|
} |