portal driver clones

This commit is contained in:
2022-10-10 21:14:16 +02:00
parent 36e8538bb9
commit 2d4bd97b8e
11 changed files with 357 additions and 91 deletions

View File

@@ -11,7 +11,10 @@ GameObject:
- component: {fileID: 3680365890358827431}
- component: {fileID: 3680365890358827424}
- component: {fileID: 3680365890358827425}
m_Layer: 0
- component: {fileID: 9003874053127290317}
- component: {fileID: 6670815188493146868}
- component: {fileID: 7213930867242206722}
m_Layer: 6
m_Name: Hand
m_TagString: Untagged
m_Icon: {fileID: 0}
@@ -83,3 +86,49 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!136 &9003874053127290317
CapsuleCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3680365890358827426}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
m_Radius: 0.5
m_Height: 2
m_Direction: 1
m_Center: {x: 0, y: 0, z: 0}
--- !u!54 &6670815188493146868
Rigidbody:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3680365890358827426}
serializedVersion: 2
m_Mass: 1
m_Drag: 0
m_AngularDrag: 0.05
m_UseGravity: 0
m_IsKinematic: 1
m_Interpolate: 0
m_Constraints: 0
m_CollisionDetection: 0
--- !u!114 &7213930867242206722
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3680365890358827426}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ee06bb2aa499a594c9761498039d73a7, type: 3}
m_Name:
m_EditorClassIdentifier:
traveller: {fileID: 0}
hasClone: 1
entrySide: 0
clone: {fileID: 0}

View File

@@ -0,0 +1,11 @@
namespace Escape_Room_Engine.Portal
{
public class HandPortalDriver : PortalDriver
{
private new void Start()
{
traveller = transform.parent.parent.parent; // get the hand portal offset
base.Start();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ee06bb2aa499a594c9761498039d73a7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -34,25 +34,35 @@ namespace Escape_Room_Engine.Portal
for (var i = 0; i < _closePortalDrivers.Count; i++)
{
var portalDriver = _closePortalDrivers[i];
var side = CalculateSide(portalDriver.transform);
if (portalDriver.entrySide < 0 && side >= 0) // must have entered from the front and exited the back
if (portalDriver.entrySide < 0 && CalculateSide(portalDriver.transform) >= 0) // must have entered from the front and exited the back
{
_closePortalDrivers.Remove(portalDriver);
linkedPortal._closePortalDrivers.Add(portalDriver);
portalDriver.entrySide = -1;
StopTrackingDriver(portalDriver);
linkedPortal.StartTrackingDriver(portalDriver, -1);
portalDriver.Teleport(this, linkedPortal);
i--; // decrease the loop counter because the list is one element smaller now
}
}
}
private void StartTrackingDriver(PortalDriver portalDriver, int entrySide)
{
_closePortalDrivers.Add(portalDriver);
portalDriver.EnableClone(linkedPortal);
portalDriver.entrySide = entrySide;
}
private void StopTrackingDriver(PortalDriver portalDriver)
{
_closePortalDrivers.Remove(portalDriver);
portalDriver.DisableClone(linkedPortal);
}
private void OnTriggerEnter(Collider other)
{
var portalDriver = other.GetComponent<PortalDriver>();
if (portalDriver && !_closePortalDrivers.Contains(portalDriver))
{
_closePortalDrivers.Add(portalDriver);
portalDriver.entrySide = CalculateSide(portalDriver.transform);
StartTrackingDriver(portalDriver, CalculateSide(portalDriver.transform));
}
}
@@ -60,9 +70,7 @@ namespace Escape_Room_Engine.Portal
{
var portalDriver = other.GetComponent<PortalDriver>();
if (portalDriver)
{
_closePortalDrivers.Remove(portalDriver);
}
StopTrackingDriver(portalDriver);
}
private int CalculateSide(Transform portalDriverTransform)

View File

@@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 2246995198243242195}
- component: {fileID: 1249363658}
- component: {fileID: 7604291350124895408}
m_Layer: 0
m_Layer: 7
m_Name: Portal
m_TagString: Untagged
m_Icon: {fileID: 0}

View File

@@ -10,25 +10,29 @@ namespace Escape_Room_Engine.Portal
/// The object that will be transported through the portal. Usually either this object or a parent offset object.
/// If left empty, it will default to this object.
/// </summary>
[SerializeField] private Transform traveller;
public Transform traveller;
/// <summary>
/// Whether this portal driver has a clone mirroring it at other portals. Disable this for the player.
/// </summary>
public bool hasClone = true;
/// <summary>
/// The side of the portal this became tracked on.
/// </summary>
[HideInInspector] public int entrySide;
/// <summary>
/// A reference to the collider of this portal driver.
/// The clone that is used to mirror this portal driver at another portal.
/// </summary>
public Collider Collider { get; private set; }
[HideInInspector] public PortalDriverClone clone;
private Collider _collider;
private Rigidbody _rigidbody;
private void Awake()
{
// check whether the collider is set up correctly
Collider = GetComponent<Collider>();
if (Collider.isTrigger) throw new Exception("Collider must not be a trigger.");
_collider = GetComponent<Collider>();
if (_collider.isTrigger) throw new Exception("Collider must not be a trigger.");
// check whether the traveller is set
if (!traveller) traveller = transform;
@@ -37,11 +41,41 @@ namespace Escape_Room_Engine.Portal
_rigidbody = GetComponent<Rigidbody>();
}
protected void Start()
{
if (hasClone)
clone = PortalDriverClone.Create(this);
}
private void Update()
{
if (hasClone && clone.gameObject.activeSelf)
clone.UpdatePosition(transform);
}
public void EnableClone(Portal at)
{
if (hasClone)
{
clone.portal = at;
clone.gameObject.SetActive(true);
}
}
public void DisableClone(Portal at)
{
if (hasClone && at.Equals(clone.portal)) // don't disable clones that are already at a different portal
{
clone.portal = null;
clone.gameObject.SetActive(false);
}
}
public void Teleport(Portal from, Portal to)
{
var m = to.transform.localToWorldMatrix * Portal.HalfRotation * from.transform.worldToLocalMatrix *
traveller.localToWorldMatrix;
traveller.transform.SetPositionAndRotation(m.GetPosition(), m.rotation);
traveller.SetPositionAndRotation(m.GetPosition(), m.rotation);
if (_rigidbody)
{
_rigidbody.velocity = to.transform.TransformDirection(

View File

@@ -0,0 +1,44 @@
using UnityEngine;
using UnityEngine.InputSystem.XR;
using UnityEngine.XR.Interaction.Toolkit;
namespace Escape_Room_Engine.Portal
{
public class PortalDriverClone : MonoBehaviour
{
/// <summary>
/// The portal where this clone is mirroring the portal driver.
/// </summary>
[HideInInspector] public Portal portal;
public static PortalDriverClone Create(PortalDriver portalDriver)
{
// copy the portal driver object
var clone = Instantiate(portalDriver).gameObject;
// destroy all unnecessary components
Destroy(clone.GetComponent<PortalDriver>());
foreach (var xrGrabInteractable in clone.GetComponentsInChildren<XRGrabInteractable>())
Destroy(xrGrabInteractable);
foreach (var rigidbody in clone.GetComponentsInChildren<Rigidbody>())
Destroy(rigidbody);
foreach (var trackedPoseDriver in clone.GetComponentsInChildren<TrackedPoseDriver>())
Destroy(trackedPoseDriver);
// add a clone component
clone.AddComponent<PortalDriverClone>();
// set up the clone
var portalDriverClone = clone.GetComponent<PortalDriverClone>();
portalDriverClone.gameObject.SetActive(false);
return portalDriverClone;
}
public void UpdatePosition(Transform cloning)
{
var m = portal.transform.localToWorldMatrix * Portal.HalfRotation *
portal.linkedPortal.transform.worldToLocalMatrix * cloning.localToWorldMatrix;
transform.SetPositionAndRotation(m.GetPosition(), m.rotation);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 088fae7d750b41e4eb8d333853ffa41a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: