You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
5.7 KiB
C#
158 lines
5.7 KiB
C#
6 months ago
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Events;
|
||
|
|
||
|
namespace Autohand{
|
||
|
[HelpURL("https://app.gitbook.com/s/5zKO0EvOjzUDeT2aiFk3/auto-hand/teleportation")]
|
||
|
public class Teleporter : MonoBehaviour{
|
||
|
[Header("Teleport")]
|
||
|
[Tooltip("The object to teleport")]
|
||
|
public GameObject teleportObject;
|
||
|
[Tooltip("Can be left empty - Used for if there is a container that should be teleported in addition to the main teleport object")]
|
||
|
public Transform[] additionalTeleports;
|
||
|
|
||
|
[Header("Aim Settings")]
|
||
|
[Tooltip("The Object to Shoot the Beam From")]
|
||
|
public Transform aimer;
|
||
|
[Tooltip("Layers You Can Teleport On")]
|
||
|
public LayerMask layer;
|
||
|
[Tooltip("The Maximum Slope You Can Teleport On")]
|
||
|
public float maxSurfaceAngle = 45;
|
||
|
[Min(0)]
|
||
|
public float distanceMultiplyer = 1;
|
||
|
[Min(0)]
|
||
|
public float curveStrength = 1;
|
||
|
[Tooltip("Use Worldspace Must be True")]
|
||
|
public LineRenderer line;
|
||
|
[Tooltip("Maximum Length of The Teleport Line")]
|
||
|
public int lineSegments = 50;
|
||
|
|
||
|
[Header("Line Settings")]
|
||
|
public Gradient canTeleportColor = new Gradient(){ colorKeys = new GradientColorKey[] { new GradientColorKey(){ color = Color.green, time = 0 } } };
|
||
|
public Gradient cantTeleportColor = new Gradient(){ colorKeys = new GradientColorKey[] { new GradientColorKey(){ color = Color.red, time = 0 } } };
|
||
|
|
||
|
[Tooltip("This gameobject will match the position of the teleport point when aiming")]
|
||
|
public GameObject indicator;
|
||
|
|
||
|
[Header("Unity Events")]
|
||
|
public UnityEvent OnStartTeleport;
|
||
|
public UnityEvent OnStopTeleport;
|
||
|
public UnityEvent OnTeleport;
|
||
|
|
||
|
Vector3[] lineArr;
|
||
|
bool aiming;
|
||
|
bool hitting;
|
||
|
RaycastHit aimHit;
|
||
|
HandTeleportGuard[] teleportGuards;
|
||
|
AutoHandPlayer playerBody;
|
||
|
|
||
|
private void Awake() {
|
||
|
line.enabled = false;
|
||
|
}
|
||
|
|
||
|
private void Start() {
|
||
|
playerBody = AutoHandExtensions.CanFindObjectOfType<AutoHandPlayer>();
|
||
|
if (playerBody != null && playerBody.transform.gameObject == teleportObject)
|
||
|
teleportObject = null;
|
||
|
|
||
|
lineArr = new Vector3[lineSegments];
|
||
|
teleportGuards = AutoHandExtensions.CanFindObjectsOfType<HandTeleportGuard>();
|
||
|
}
|
||
|
|
||
|
void Update(){
|
||
|
if(aiming)
|
||
|
CalculateTeleport();
|
||
|
else
|
||
|
line.positionCount = 0;
|
||
|
|
||
|
DrawIndicator();
|
||
|
}
|
||
|
|
||
|
void CalculateTeleport() {
|
||
|
line.colorGradient = cantTeleportColor;
|
||
|
var lineList = new List<Vector3>();
|
||
|
int i;
|
||
|
hitting = false;
|
||
|
for(i = 0; i < lineSegments; i++) {
|
||
|
var time = i/60f;
|
||
|
lineArr[i] = aimer.transform.position;
|
||
|
lineArr[i] += transform.forward*time*distanceMultiplyer*15;
|
||
|
lineArr[i].y += curveStrength * (time - Mathf.Pow(9.8f*0.5f*time, 2));
|
||
|
lineList.Add(lineArr[i]);
|
||
|
if(i != 0) {
|
||
|
if(Physics.Raycast(lineArr[i-1], lineArr[i]-lineArr[i-1], out aimHit, Vector3.Distance(lineArr[i], lineArr[i-1]), ~Hand.GetHandsLayerMask(), QueryTriggerInteraction.Ignore)) {
|
||
|
//Makes sure the angle isnt too steep
|
||
|
if(Vector3.Angle(aimHit.normal, Vector3.up) <= maxSurfaceAngle && layer == (layer | (1 << aimHit.collider.gameObject.layer))) {
|
||
|
line.colorGradient = canTeleportColor;
|
||
|
lineList.Add(aimHit.point);
|
||
|
hitting = true;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
line.enabled = true;
|
||
|
line.positionCount = i;
|
||
|
line.SetPositions(lineArr);
|
||
|
|
||
|
}
|
||
|
|
||
|
void DrawIndicator(){
|
||
|
if(indicator != null){
|
||
|
if(hitting){
|
||
|
indicator.gameObject.SetActive(true);
|
||
|
indicator.transform.position = aimHit.point;
|
||
|
indicator.transform.up = aimHit.normal;
|
||
|
}
|
||
|
else
|
||
|
indicator.gameObject.SetActive(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void StartTeleport(){
|
||
|
aiming = true;
|
||
|
OnStartTeleport?.Invoke();
|
||
|
}
|
||
|
|
||
|
public void CancelTeleport(){
|
||
|
line.positionCount = 0;
|
||
|
line.enabled = false;
|
||
|
hitting = false;
|
||
|
aiming = false;
|
||
|
OnStopTeleport?.Invoke();
|
||
|
}
|
||
|
|
||
|
public void Teleport(){
|
||
|
Queue<Vector3> fromPos = new Queue<Vector3>();
|
||
|
foreach(var guard in teleportGuards) {
|
||
|
if(guard.gameObject.activeInHierarchy)
|
||
|
fromPos.Enqueue(guard.transform.position);
|
||
|
}
|
||
|
|
||
|
if(hitting) {
|
||
|
if (teleportObject != null){
|
||
|
var diff = aimHit.point - teleportObject.transform.position;
|
||
|
teleportObject.transform.position = aimHit.point;
|
||
|
foreach (var teleport in additionalTeleports){
|
||
|
teleport.position += diff;
|
||
|
}
|
||
|
}
|
||
|
playerBody?.SetPosition(aimHit.point);
|
||
|
|
||
|
OnTeleport?.Invoke();
|
||
|
|
||
|
|
||
|
foreach(var guard in teleportGuards) {
|
||
|
if(guard.gameObject.activeInHierarchy) {
|
||
|
guard.TeleportProtection(fromPos.Dequeue(), guard.transform.position);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CancelTeleport();
|
||
|
}
|
||
|
}
|
||
|
}
|