因此,门户基本上是一个虫洞。进入的物体将保留其本地位置和方向。
![wormhole](https://istack.dev59.com/UkmQF.gif)
功能:
Unity拥有用于在世界空间和本地空间之间进行转换的函数。
位置:
Transform.InverseTransformPoint
将位置从世界空间转换为本地空间。
Transform.TransformPoint
将位置从局部空间转换到世界空间。
![jumping](https://istack.dev59.com/whp8L.gif)
方向:
要转换方向,您需要使用以下内容:
Transform.InverseTransformDirection
将世界空间中的方向转换为本地空间。与Transform.TransformDirection相反。
Transform.TransformDirection
将方向从本地空间转换为世界空间。
简单的例子:
一个脚本,你可以将它附加到两个门上。它可以移动带有标签"Ball"的物体到exitPortal
中。
public class Portal : MonoBehaviour
{
[SerializeField] Portal exitPortal;
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.CompareTag("Ball"))
{
GameObject ball = collider.gameObject;
Rigidbody2D rigidbody = ball.GetComponent<Rigidbody2D>();
Vector3 inPosition = this.transform.InverseTransformPoint(ball.transform.position);
inPosition.x = -inPosition.x;
Vector3 outPosition = exitPortal.transform.TransformPoint(inPosition);
Vector3 inDirection = this.transform.InverseTransformDirection(rigidbody.velocity);
Vector3 outDirection = exitPortal.transform.TransformDirection(inDirection);
ball.transform.position = outPosition;
rigidbody.velocity = -outDirection;
}
}
}
你得到这个:
![fun](https://istack.dev59.com/2eewO.gif)
复杂示例:
您需要3个脚本才能使其工作:
- Portal:触碰可传送物体的物品
- Warpable:通过传送门旅行的物品
- Ghost:镜像 Warpable,在穿过传送门时显示
这就是 Ghost 的外观:
您需要两个额外的层——Portal和Ghost,其中碰撞矩阵设置如图所示。
![matrix](https://istack.dev59.com/jcQmd.webp)
脚本:
我已经在代码中添加了足够的注释,让您能够理解它正在做什么。
门户:
public class Portal : MonoBehaviour
{
[SerializeField] Portal exitPortal;
void OnTriggerEnter2D(Collider2D collider)
{
if (collider.TryGetComponent(out Warpable warpable))
{
if (warpable.Ghost == null) warpable.CreateGhost(this, exitPortal);
}
}
void OnTriggerExit2D(Collider2D collider)
{
if (collider.TryGetComponent(out Warpable warpable))
{
if (warpable.Ghost != null)
{
Vector3 portalToWarpable = warpable.transform.position - this.transform.position;
Vector3 portalDownwards = -this.transform.up;
float dot = Vector3.Dot(portalDownwards, portalToWarpable);
bool passedThroughPortal = dot >= 0f;
if (passedThroughPortal)
{
warpable.Position = warpable.Ghost.warpable.Position;
warpable.Rotation = warpable.Ghost.warpable.Rotation;
warpable.Velocity = warpable.Ghost.warpable.Velocity;
}
warpable.DestroyGhost();
}
}
}
void OnDrawGizmos()
{
Gizmos.color = Color.magenta;
Gizmos.DrawRay(this.transform.position, this.transform.up);
}
}
可扭曲的:
public class Warpable : MonoBehaviour
{
[SerializeField] new Rigidbody2D rigidbody;
public Ghost Ghost { get; private set; }
public void CreateGhost(Portal inPortal, Portal outPortal)
{
GameObject original = this.gameObject;
GameObject duplicate = GameObject.Instantiate(original);
duplicate.layer = LayerMask.NameToLayer("Ghost");
Physics2D.IgnoreCollision(
original.GetComponent<Collider2D>(),
duplicate.GetComponent<Collider2D>()
);
Ghost = duplicate.AddComponent<Ghost>();
Ghost.observing = original.GetComponent<Warpable>();
Ghost.warpable = duplicate.GetComponent<Warpable>();
Ghost.inPortal = inPortal;
Ghost.outPortal = outPortal;
}
public void DestroyGhost()
{
GameObject.Destroy(Ghost.gameObject);
Ghost = null;
}
public Vector3 Position
{
get { return transform.position; }
set { transform.position = value; }
}
public Quaternion Rotation
{
get { return transform.rotation; }
set { transform.rotation = value; }
}
public Vector3 Velocity
{
get { return rigidbody.velocity; }
set { rigidbody.velocity = value; }
}
}
幽灵:
public class Ghost : MonoBehaviour
{
public Warpable observing;
public Warpable warpable;
public Portal inPortal;
public Portal outPortal;
void FixedUpdate()
{
warpable.Position = OutPosition(observing.Position);
warpable.Rotation = OutRotation(observing.Rotation);
warpable.Velocity = OutDirection(observing.Velocity);
}
Vector3 OutPosition(Vector3 position)
{
Vector3 inPosition = -inPortal.transform.InverseTransformPoint(position);
return outPortal.transform.TransformPoint(inPosition);
}
Quaternion OutRotation(Quaternion rotation)
{
return Quaternion.Inverse(inPortal.transform.rotation) * outPortal.transform.rotation * rotation;
}
Vector3 OutDirection(Vector3 velocity)
{
Vector3 inDirection = -inPortal.transform.InverseTransformDirection(velocity);
return outPortal.transform.TransformDirection(inDirection);
}
void OnDrawGizmos()
{
Gizmos.color = Color.cyan;
Gizmos.DrawWireSphere(warpable.Position, 1f);
Gizmos.DrawLine(warpable.Position, warpable.Position + warpable.Velocity);
}
}
最终结果是这样的:
![warping](https://istack.dev59.com/xneDy.gif)