【问题标题】:Why teleportation doesn't work right?为什么传送不能正常工作?
【发布时间】:2017-07-26 20:14:21
【问题描述】:

我正在尝试使用重新创建门户场景 this 视频。场景资产和脚本的链接在视频下方。

我正面临一个传送问题

玩家应该穿过传送门中的平面触发器,以移动到第二个传送门的位置。但在我看来,在传送之后,他出现在第二个传送门的平面触发器中间。如果他继续移动,他会跳回第一个传送门,然后再跳到第二个传送门,以此类推。

为什么会发生,如何解决?据我了解脚本的作者,它应该在通过触发器后传送玩家,但脚本对我来说不是那样的。

这是传送的脚本:

using UnityEngine;
using System.Collections;

public class Sender : MonoBehaviour {

    public GameObject player;
    public GameObject receiver;

    private float prevDot = 0;
    private bool playerOverlapping = false;

    void Start () {
    }

    void Update()
    {
        if (playerOverlapping) {
            var currentDot = Vector3.Dot(transform.up, player.transform.position - transform.position);

            if (currentDot < 10) // only transport the player once he's moved across plane
            {
                // transport him to the equivalent position in the other portal
                float rotDiff = -Quaternion.Angle(transform.rotation, receiver.transform.rotation);
                rotDiff += 180;
                player.transform.Rotate(Vector3.up, rotDiff);

                Vector3 positionOffset = player.transform.position - transform.position;
                positionOffset = Quaternion.Euler(0, rotDiff, 0) * positionOffset;
                var newPosition = receiver.transform.position + positionOffset;
                player.transform.position = newPosition;

                playerOverlapping = false;
            }

            prevDot = currentDot;
        }
    }


    void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")
        {
            playerOverlapping = true;
        }
    }

    void OnTriggerExit(Collider other)
    {
        if (other.tag == "Player")
        {
            playerOverlapping = false;
        }
    }
}

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    您可以做到这一点的一种方法是在传送时简单地增加玩家位置的偏移量,但这样您将无法实现所需的平滑过渡。

    我想到的另一种方法是向 Sender 脚本添加一个公共布尔变量(我假设 Sender 脚本在所有门户上),默认值为 false。 传送时,您使用接收传送器的位置将玩家的位置设置为新位置。因为您可以访问接收传送器 GameObject,所以可以使用 GetComponent 来获取它的 Sender 脚本。然后,您可以在传送玩家之前将此布尔变量设置为 true。 一旦玩家被传送, OnTriggerEnter 方法就会自动调用,这是你的问题。您可以在 OnTriggerEnter 中放置一个 if 语句,这样当它被激活时,它只会在布尔变量为 false 时传送。因为当玩家传送时它是真的,所以在你离开传送门触发器之前你不能传送回来,那么你可以将布尔变量设置回 false。这意味着穿过门户的正常行为不受影响,因为默认布尔值为 false。

    此外,如果您像 Absinthe 所说的那样在 OnTriggerEnter 而不是 Update 中进行实际的传送,那么这段代码可能会好得多。

    希望这会有所帮助!

    【讨论】:

    • 非常感谢,我会尝试这种方式,但看起来这正是我需要的!
    【解决方案2】:

    我不知道您将使用原始代码(不是双关语),而且我没有观看视频 (TLDR),但您需要从头开始重新考虑这一点。使用 Update 方法是完全不合适的;更新每一帧都会触发 - 你想传送每一帧吗?

    改为使用 OnTriggerEnter 方法:

    void OnTriggerEnter(Collider other)
    {
       other.transform.position = theVectorYouWantToTeleportTo
    }
    

    【讨论】:

    • 谢谢,问题是我试图实现无缝过渡,当用户在第二个场景中看到来自第二个摄像机的渲染图像时,下一刻他传送到同一个位置在第二个场景中,看起来他就像穿过门一样穿过门户。问题是,在这种情况下,用户将出现在第二个传送门的对撞机中间,这也将使用 OnTriggerEnter 方法将玩家传送回来。这样玩家就永远不会穿过传送门。
    • 您可以在玩家、传送器或一些全局对象上设置一个“teleportedAlready”布尔变量,以防止玩家立即被传送回来。如果您希望第二次传送再次可用,您可以使用协程在一定时间后重置变量。
    • 谢谢,这也是一个有趣的选择!但在这种情况下,如果玩家在触碰它的触发器时在传送门附近停留一段时间,他会在协程时间结束后再次传送回来。
    • 所以使用 OnTriggerExit 启动协程。有很多方法可以做事:)
    猜你喜欢
    • 2016-07-16
    • 2019-01-04
    • 2020-09-03
    • 2016-10-10
    • 2016-10-24
    • 2017-02-27
    • 2017-07-08
    • 2014-11-23
    • 2021-03-07
    相关资源
    最近更新 更多